Skip to content

Add --dry-run mode to update and upgrade commands and dashboard#42361

Closed
pelikhan with Copilot wants to merge 5 commits into
mainfrom
copilot/update-github-extension-dashboard-dry-run
Closed

Add --dry-run mode to update and upgrade commands and dashboard#42361
pelikhan with Copilot wants to merge 5 commits into
mainfrom
copilot/update-github-extension-dashboard-dry-run

Conversation

Copilot AI commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

gh aw update and gh aw upgrade had no way to preview what they would do before modifying files. Adds --dry-run to both commands and wires it through the MCP tools (defaulting to checked) and the dashboard Maintenance tab.

CLI

  • update --dry-run: skips file writes in updateWorkflow; skips UpdateActions, UpdateActionsInWorkflowFiles, UpdateContainerPins, and recompile in RunUpdateWorkflows
  • upgrade --dry-run: skips extension self-upgrade, Copilot artifact update, codemods, action version updates, and recompile; prints a (dry run) Would … line for each skipped step

MCP tools

  • update tool: added dry_run field; schema now uses AddSchemaDefault(…, "dry_run", true) so the checkbox is checked by default
  • New upgrade MCP tool with the same dry-run-default schema pattern; registered in mcp_server.go

Dashboard

  • Dry run checkbox added to Maintenance tab header, enabled by default
  • buildMaintenanceCommand appends --dry-run to run-update/run-upgrade when the checkbox is on
  • Label--attention badge shown when dry run is active
$ gh aw update --dry-run
ℹ (dry run) Previewing workflow updates — no files will be modified
(dry run) Would update agentic-ops from v1.2.0 to v1.3.0

$ gh aw upgrade --dry-run
ℹ (dry run) Previewing upgrades — no files will be modified
ℹ (dry run) Would check gh-aw extension version
ℹ (dry run) Would update dispatcher skill
ℹ (dry run) Would apply codemods to all workflows
ℹ (dry run) Would update GitHub Actions versions
ℹ (dry run) Would recompile all workflows

Copilot AI and others added 2 commits June 29, 2026 22:34
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Add dry-run mode to update/upgrade commands and dashboard Add --dry-run mode to update and upgrade commands and dashboard Jun 29, 2026
Copilot AI requested a review from pelikhan June 29, 2026 22:36
@pelikhan pelikhan marked this pull request as ready for review June 29, 2026 22:37
Copilot AI review requested due to automatic review settings June 29, 2026 22:37

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

Adds a --dry-run preview mode to gh aw update and gh aw upgrade, wires it into MCP tools (with dry_run defaulting to true for safe elicitation), and exposes a “Dry run” toggle in the Agentic Workflows Dashboard Maintenance tab so users can preview maintenance actions before mutating files.

Changes:

  • Add --dry-run flag to update and upgrade CLI commands and short-circuit file-mutating steps while emitting “(dry run) Would …” output.
  • Extend MCP management tooling with dry_run input (default true) and introduce a new upgrade MCP tool.
  • Update dashboard UI/state to default to dry-run and append --dry-run to maintenance run commands when enabled.
Show a summary per file
File Description
pkg/cli/upgrade_command.go Adds --dry-run flag and a dry-run early-exit path with “Would …” messaging.
pkg/cli/update_workflows.go Adds DryRun option and skips workflow file writes/compilation when enabled.
pkg/cli/update_command.go Adds --dry-run flag plumbed into update options and prints preview header.
pkg/cli/mcp_tools_management.go Adds dry_run to MCP update tool schema (default true) and introduces MCP upgrade tool.
pkg/cli/mcp_server.go Registers update/upgrade MCP tools with error handling.
pkg/cli/mcp_server_unit_test.go Updates expected tool list to include upgrade.
pkg/cli/mcp_server_tools_test.go Updates expected tool list to include upgrade.
.github/extensions/agentic-workflows-dashboard/web/index.html Adds a Dry run checkbox and a “Dry run” badge in Maintenance UI.
.github/extensions/agentic-workflows-dashboard/web/app.js Builds in dry-run default state and appends --dry-run to run commands.
.github/extensions/agentic-workflows-dashboard/src/app.ts Source changes for dashboard dry-run state and command construction.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 10/10 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment thread pkg/cli/update_command.go
Comment on lines 93 to 97
targetRepo, _ := cmd.Flags().GetString("repo")
targetOrg, _ := cmd.Flags().GetString("org")
repoGlobs, _ := cmd.Flags().GetStringSlice("repos")
dryRun, _ := cmd.Flags().GetBool("dry-run")

Comment on lines 92 to +96
approveUpgrade, _ := cmd.Flags().GetBool("approve")
preReleases, _ := cmd.Flags().GetBool("pre-releases")
targetOrg, _ := cmd.Flags().GetString("org")
repoGlobs, _ := cmd.Flags().GetStringSlice("repos")
dryRun, _ := cmd.Flags().GetBool("dry-run")
Comment thread pkg/cli/update_command.go
cmd.Flags().Bool("create-issue", false, "Open a GitHub issue in each org repository that has pending workflow updates (requires --org)")
cmd.Flags().BoolP("yes", "y", false, "Auto-accept org-mode create confirmations (required in CI)")
cmd.Flags().String("cool-down", "7d", coolDownFlagUsage)
cmd.Flags().Bool("dry-run", false, "Preview updates without applying any changes")
@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer failed during the skills-based review.

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 2 modified test(s): 2 design, 0 implementation, 0 guideline violation(s).

📊 Metrics & Test Classification (2 tests analyzed)
Metric Value
New/modified tests analyzed 2
✅ Design tests (behavioral contracts) 2 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 2 (100%)
Duplicate test clusters 0
Test inflation detected No
🚨 Coding-guideline violations 0
Test File Classification Issues Detected
TestMCPServer_ListTools pkg/cli/mcp_server_tools_test.go:47 ✅ Design
TestMCPServerUnit_ListTools pkg/cli/mcp_server_unit_test.go:28 ✅ Design

Go: 2 (*_test.go); JavaScript: 0. No other languages detected.

Notes: Both changes are single-line updates adding "upgrade" to the expectedTools list — directly tracking the new MCP tool registered by this PR. The count assertion (assert.Len / t.Errorf) enforces an exact match, which also catches unexpected extra tools.

Verdict

Check passed. 0% implementation tests (threshold: 30%). Both modified tests verify a behavioral contract — which tools the MCP server exposes to clients — and correctly reflect the addition of the upgrade dry-run tool.

🧪 Test quality analysis by Test Quality Sentinel · 49.3 AIC · ⌖ 19.3 AIC · ⊞ 8.1K ·
Comment /review to run again

@github-actions github-actions Bot 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.

✅ Test Quality Sentinel: 100/100. Test quality is acceptable — 0% of new tests are implementation tests (threshold: 30%).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (166 new lines in pkg/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/42361-add-dry-run-mode-to-update-upgrade-commands.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-42361: Add Dry-Run Mode to update and upgrade Commands

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say I'll deal with this later. Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 42361-add-dry-run-mode-to-update-upgrade-commands.md for PR #42361).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 57.3 AIC · ⌖ 12.6 AIC · ⊞ 8.4K ·
Comment /review to run again

@github-actions github-actions Bot 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.

Review: Add --dry-run mode to update and upgrade commands and dashboard

The feature design is solid — --dry-run defaults to true in MCP elicitation and the dashboard, all file-writing steps are correctly gated, and the output messages accurately mirror what each skipped step would have done.

One correctness bug needs to be fixed before merge; two smaller issues are also flagged.

Issues found (3)
Severity File Issue
🔴 Bug mcp_server.go:93 Early return on registerUpdateTool failure skips registerFixTool entirely
🟡 Minor mcp_tools_management.go:114 AddSchemaDefault error is swallowed — silent failure removes the dry-run-on-by-default guarantee
🟡 Minor web/app.js:3312 days field additions to reportWindows are not present in the app.ts source

What's good:

  • Dry-run messages in both update and upgrade accurately track the conditions (noFix, noActions, noCompile) of the real steps they shadow.
  • Security scanning still runs in dry-run mode (correct — it's a read-only check).
  • MCP upgrade tool is properly registered and tested in both test files.
  • Dashboard defaults (dryRun: true) and the Label--attention badge are well-wired.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 60.3 AIC · ⌖ 6.92 AIC · ⊞ 4.9K

Comment thread pkg/cli/mcp_server.go
registerUpdateTool(server, execCmd)
if err := registerUpdateTool(server, execCmd); err != nil {
mcpLog.Printf("Failed to register update tool: %v", err)
return server

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.

Bug: early return skips registerFixTool (and any tools registered after it).

When registerUpdateTool fails — e.g. if GenerateSchema returns an error — the function returns the partially-configured server at this line, so registerUpgradeTool and registerFixTool are never called. The MCP server would be silently missing the fix tool (and the upgrade tool).

Consider logging the error and continuing rather than returning early:

if err := registerUpdateTool(server, execCmd); err != nil {
    mcpLog.Printf("Failed to register update tool: %v", err)
    // fall through — other tools must still be registered
}
if err := registerUpgradeTool(server, execCmd); err != nil {
    mcpLog.Printf("Failed to register upgrade tool: %v", err)
}
registerFixTool(server, execCmd)

If a hard-stop is truly required, at minimum move registerFixTool before the early returns so it is always registered.

@copilot please address this.

}
// Add elicitation default: dry_run defaults to true (safe preview mode)
if err := AddSchemaDefault(updateSchema, "dry_run", true); err != nil {
mcpToolsManagementLog.Printf("Failed to add default for dry_run: %v", err)

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.

Silent failure undermines the dry-run-default UX.

AddSchemaDefault errors are only logged and then swallowed. If this call fails, dry_run will have no default value in the JSON schema, so the elicitation UI will not show the checkbox pre-checked — exactly the safety property this PR is trying to guarantee.

Consider returning the error so the caller (registerUpdateTool) can propagate it:

if err := AddSchemaDefault(updateSchema, "dry_run", true); err != nil {
    return fmt.Errorf("failed to add dry_run default: %w", err)
}

Same pattern applies to the equivalent block in registerUpgradeTool (~line 283).

@copilot please address this.

{ id: "3d", label: "3 days", startDate: "-3d" },
{ id: "7d", label: "7 days", startDate: "-1w" },
{ id: "1mo", label: "1 month", startDate: "-1mo" }
{ id: "3d", label: "3 days", startDate: "-3d", days: 3 },

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.

Unrelated change in compiled output not present in the source (app.ts).

The days field addition to reportWindows entries appears in app.js but has no corresponding change in app.ts. If app.js is a compiled artefact, it should be regenerated from source and never manually edited — otherwise the build is no longer reproducible.

Please verify:

  1. Does app.ts actually contain these days fields (perhaps pre-existing, not shown in the diff)?
  2. If not, either add the matching source change to app.ts and recompile, or remove the manual edit from app.js.

@copilot please address this.

@github-actions github-actions Bot 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.

REQUEST_CHANGES — 3 issues found in dry-run wiring

The dry-run feature is well-structured overall, but there are two correctness issues in the MCP registration path and one logic bug in the upgrade command.

🔍 Blocking issues

1. — silently dropped on error path
When or fails (schema-generation error), is never called. The server is returned without the tool — a regression from the previous code where was always registered. See inline comment.

2. — error swallowed in both registrations
If fails for , execution continues and the tool is registered without the default. The stated invariant ("dry_run defaults to true for safe preview mode") is silently violated in both and . See inline comment.

**3. — fires incorrectly when **
Prints "(dry run) Would check gh-aw extension version" even when the extension step was explicitly bypassed by the internal re-launch flag. See inline comment.

i️ Pre-existing issues noted by earlier reviewers (not counted above)
    • / silently creates empty PRs/issues in org mode (already flagged on update and upgrade commands).
  • Integration tests still assert is not a valid flag for (already flagged).

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • patchdiff.githubusercontent.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "patchdiff.githubusercontent.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · 96.3 AIC · ⌖ 7.63 AIC · ⊞ 5.2K
Comment /review to run again

Comment thread pkg/cli/mcp_server.go
registerUpdateTool(server, execCmd)
if err := registerUpdateTool(server, execCmd); err != nil {
mcpLog.Printf("Failed to register update tool: %v", err)
return server

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.

registerFixTool is silently skipped on schema-generation failure — partially-configured server returned. If registerUpdateTool (or registerUpgradeTool) fails, the function returns before registerFixTool is called on line 99, so the server is missing the fix tool. This is a regression: previously fix was unconditionally registered.

💡 Suggested fix

Move registerFixTool before the guarded registrations, or register remaining tools even on error:

registerAddTool(server, execCmd)
registerFixTool(server, execCmd)  // move up — always safe

if err := registerUpdateTool(server, execCmd); err != nil {
    mcpLog.Printf("Failed to register update tool: %v", err)
    return server
}
if err := registerUpgradeTool(server, execCmd); err != nil {
    mcpLog.Printf("Failed to register upgrade tool: %v", err)
    return server
}

GenerateSchema fails only on programmer error (malformed struct tags), so this path will not be triggered in production — but the current code silently drops fix if it ever does.

}
// Add elicitation default: dry_run defaults to true (safe preview mode)
if err := AddSchemaDefault(updateSchema, "dry_run", true); err != nil {
mcpToolsManagementLog.Printf("Failed to add default for dry_run: %v", err)

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.

AddSchemaDefault failure is silently swallowed — dry_run may not default to true without any diagnostic. The error is logged and then discarded; registerUpdateTool continues and registers the tool with an incomplete schema. The "safe preview mode" invariant (dry_run=true by default) is silently violated.

💡 Suggested fix

Return the error so the caller can handle it, consistent with the pattern used for GenerateSchema just above:

if err := AddSchemaDefault(updateSchema, "dry_run", true); err != nil {
    mcpToolsManagementLog.Printf("Failed to add default for dry_run: %v", err)
    return err  // propagate instead of silently continuing
}

The same issue exists in registerUpgradeTool at the analogous AddSchemaDefault call (line ~283).

@@ -237,6 +246,24 @@ func runUpgradeCommand(opts upgradeOptions) error {
// Signal the entry-point to exit cleanly without repeating those steps.
return &ExitCodeError{Code: 0}
}
} else if opts.dryRun {

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.

Misleading dry-run message when --skip-extension-upgrade is set. The else if opts.dryRun branch fires for both skipExtensionUpgrade=false (normal dry-run) and skipExtensionUpgrade=true (internal re-launch after a real upgrade). In the latter case, printing "(dry run) Would check gh-aw extension version" is wrong — the extension check was already intentionally bypassed.

💡 Suggested fix

Guard the dry-run message with the same skip flag used in the non-dry-run path:

} else if opts.dryRun && !opts.skipExtensionUpgrade {
    upgradeLog.Print("Dry-run mode: skipping extension version check")
    fmt.Fprintln(os.Stderr, console.FormatInfoMessage("(dry run) Would check gh-aw extension version"))
}

--skip-extension-upgrade is a hidden internal flag only used when the binary re-launches itself, so this edge case will not be user-visible in practice — but the logic is semantically wrong and could confuse future readers or automated tests.

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

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