Skip to content

refactor(admin-control-panel): extract shared awk script, fix div regex, add atomic write protection - #220

Merged
PDowney merged 5 commits into
masterfrom
copilot/refactor-adminer-awk-scripts
May 1, 2026
Merged

PDowney merged 5 commits into
masterfrom
copilot/refactor-adminer-awk-scripts

Conversation

Copilot AI commented May 1, 2026

Copy link
Copy Markdown
Contributor
  • Replace single-quoted AWK_ADMINER_BLOCK_SCRIPT='...' with a quoted heredoc (read -r -d '' AWK_ADMINER_BLOCK_SCRIPT << 'AWKEOF' || true) to resolve shellcheck SC2016 without requiring backslash-escaping every $ and " in the awk program
  • Update CHANGELOG.md
Original prompt
Please apply the following diffs and create a pull request.
Once the PR is ready, give it a title based on the messages of the fixes being applied.

[{"message":"The awk script for extracting the adminer block (lines 60-77) and the awk script for removing it (lines 82-100) contain nearly identical logic for depth tracking. Consider extracting this into a shared awk function or script to reduce duplication and improve maintainability.","fixFiles":[{"filePath":"scripts/install/tools/frontend/admin-control-panel-install.sh","diff":"diff --git a/scripts/install/tools/frontend/admin-control-panel-install.sh b/scripts/install/tools/frontend/admin-control-panel-install.sh\n--- a/scripts/install/tools/frontend/admin-control-panel-install.sh\n+++ b/scripts/install/tools/frontend/admin-control-panel-install.sh\n@@ -46,6 +46,39 @@\n # Remove Adminer tool card if INSTALL_ADMINER=0\n if [[ \"${INSTALL_ADMINER}\" -eq 0 ]]; then\n     CONTROL_PANEL_INDEX=\"/var/www/admin/control-panel/index.html\"\n+    AWK_ADMINER_BLOCK_SCRIPT='\n+        BEGIN { in_block=0; depth=0 }\n+        {\n+            line=$0\n+            if (!in_block && line ~ /<div[^>]*id=\"adminer-tool\"[^>]*>/) {\n+                in_block=1\n+            }\n+            if (in_block) {\n+                opens=gsub(/<div[^>]*>/, \"&\", line)\n+                closes=gsub(/<\\/div>/, \"&\", line)\n+                depth += opens - closes\n+\n+                if (mode == \"extract\") {\n+                    print line\n+                    if (depth == 0) {\n+                        exit\n+                    }\n+                    next\n+                }\n+\n+                if (mode == \"remove\") {\n+                    if (depth == 0) {\n+                        in_block=0\n+                    }\n+                    next\n+                }\n+            }\n+\n+            if (mode == \"remove\") {\n+                print line\n+            }\n+        }\n+    '\n     # NOTE: This sed range depends on the HTML structure of index.html:\n     #   - the Adminer card must be wrapped in a single <div ... id=\"adminer-tool\" ...> ... </div> block\n     #   - the opening <div> with id=\"adminer-tool\" and its matching closing </div> must each be on a single line\n@@ -57,47 +90,12 @@\n         # Extract the exact Adminer block using depth-aware matching so nested <div> elements\n         # are handled correctly and we only stop at the true matching closing </div>.\n         adminer_block=\"$(\n-            awk '\n-                BEGIN { in_block=0; depth=0 }\n-                {\n-                    line=$0\n-                    if (!in_block && line ~ /<div[^>]*id=\"adminer-tool\"[^>]*>/) {\n-                        in_block=1\n-                    }\n-                    if (in_block) {\n-                        print line\n-                        opens=gsub(/<div[^>]*>/, \"&\", line)\n-                        closes=gsub(/<\\/div>/, \"&\", line)\n-                        depth += opens - closes\n-                        if (depth == 0) {\n-                            exit\n-                        }\n-                    }\n-                }\n-            ' \"${CONTROL_PANEL_INDEX}\"\n+            awk -v mode=\"extract\" \"$AWK_ADMINER_BLOCK_SCRIPT\" \"${CONTROL_PANEL_INDEX}\"\n         )\"\n         open_div_count=$(printf '%s\\n' \"$adminer_block\" | grep -Eo '<div([[:space:]>])' | wc -l | tr -d '[:space:]')\n         close_div_count=$(printf '%s\\n' \"$adminer_block\" | grep -Eo '</div[[:space:]]*>' | wc -l | tr -d '[:space:]')\n         if [[ -n \"$adminer_block\" && \"$open_div_count\" -eq \"$close_div_count\" ]]; then\n-            awk '\n-                BEGIN { in_block=0; depth=0 }\n-                {\n-                    line=$0\n-                    if (!in_block && line ~ /<div[^>]*id=\"adminer-tool\"[^>]*>/) {\n-                        in_block=1\n-                    }\n-                    if (in_block) {\n-                        opens=gsub(/<div[^>]*>/, \"&\", line)\n-                        closes=gsub(/<\\/div>/, \"&\", line)\n-                        depth += opens - closes\n-                        if (depth == 0) {\n-                            in_block=0\n-                        }\n-                        next\n-                    }\n-                    print line\n-                }\n-            ' \"${CONTROL_PANEL_INDEX}\" > \"${CONTROL_PANEL_INDEX}.tmp\" && mv \"${CONTROL_PANEL_INDEX}.tmp\" \"${CONTROL_PANEL_INDEX}\"\n+            awk -v mode=\"remove\" \"$AWK_ADMINER_BLOCK_SCRIPT\" \"${CONTROL_PANEL_INDEX}\" > \"${CONTROL_PANEL_INDEX}.tmp\" && mv \"${CONTROL_PANEL_INDEX}.tmp\" \"${CONTROL_PANEL_INDEX}\"\n         else\n             echo \"Warning: Adminer tool block appears malformed or unmatched; skipping Adminer card removal to avoid corrupting index.html.\" >&2\n         fi\n"}]},{"message":"The regex pattern '<div([[:space:]>])' only matches '<div' followed by exactly one space or '>' character, miss...

…ex, add atomic write protection

Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/c2a8fc75-8c5b-447a-8b1a-bb4b8a36fc1b

Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor awk scripts for adminer block to reduce duplication refactor(admin-control-panel): extract shared awk script, fix div regex, add atomic write protection May 1, 2026
Copilot finished work on behalf of PDowney May 1, 2026 01:10
Copilot AI requested a review from PDowney May 1, 2026 01:10
@github-actions

github-actions Bot commented May 1, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

…wk script with quoted heredoc

Agent-Logs-Url: https://github.com/EngineScript/EngineScript/sessions/3eda393c-220d-4bba-a0d3-d19529a1bed9

Co-authored-by: PDowney <11467177+PDowney@users.noreply.github.com>
Copilot finished work on behalf of PDowney May 1, 2026 02:08
Copilot AI requested a review from PDowney May 1, 2026 02:08
@sonarqubecloud

sonarqubecloud Bot commented May 1, 2026

Copy link
Copy Markdown

@PDowney
PDowney marked this pull request as ready for review May 1, 2026 02:20
Copilot AI review requested due to automatic review settings May 1, 2026 02:20
@PDowney
PDowney merged commit 84983af into master May 1, 2026
10 checks passed
@github-actions
github-actions Bot deleted the copilot/refactor-adminer-awk-scripts branch May 1, 2026 02:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Admin Control Panel installer’s “remove Adminer tool card” logic by extracting duplicated awk depth-tracking into a shared awk program string, adjusts the <div> counting regex used for sanity-checking, and switches the index.html rewrite to a safer temp-file + move flow.

Changes:

  • Extract duplicated awk depth-tracking logic into a single shared awk script (heredoc) and reuse it for both “extract” and “remove” modes.
  • Update the <div> open-tag counting regex used to validate the extracted block.
  • Add mktemp + trap cleanup and replace-in-place via mv to reduce the risk of corrupting index.html.
Comments suppressed due to low confidence (1)

scripts/install/tools/frontend/admin-control-panel-install.sh:85

  • The NOTE block still refers to a “sed range” and claims the Adminer block must not contain nested <div> elements, but the implementation now uses an awk depth counter specifically to handle nested <div> tags. Updating this comment to reflect the current awk-based approach (and its actual assumptions, e.g. the single-line opening tag grep pre-check) would prevent future confusion/mis-maintenance.
AWKEOF
    # NOTE: This sed range depends on the HTML structure of index.html:
    #   - the Adminer card must be wrapped in a single <div ... id="adminer-tool" ...> ... </div> block
    #   - the opening <div> with id="adminer-tool" and its matching closing </div> must each be on a single line
    #   - the block must not contain nested <div> elements whose closing tags appear before the end of the card

Comment on lines +104 to +105
mv "$tmp_index" "${CONTROL_PANEL_INDEX}"
trap - EXIT INT TERM

Copilot AI May 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mv "$tmp_index" "${CONTROL_PANEL_INDEX}" is not checked for success, but the cleanup trap is cleared unconditionally right after. If mv fails, the script will silently continue with the original index.html and may leak the temp file because the trap was removed. Consider checking mv's exit status (and only clearing the trap on success), and exiting with an error if the move fails so the install doesn't proceed in a partially-updated state.

Suggested change
mv "$tmp_index" "${CONTROL_PANEL_INDEX}"
trap - EXIT INT TERM
if mv "$tmp_index" "${CONTROL_PANEL_INDEX}"; then
trap - EXIT INT TERM
else
echo "Error: Failed to replace index.html after Adminer card removal." >&2
exit 1
fi

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants