Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions pkg/cli/update_actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ type latestReleaseResult struct {
// major version. Updated files are recompiled. By default all actions are updated to
// the latest major version; pass disableReleaseBump=true to only update core
// (actions/*) references.
Comment on lines 481 to 483
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The doc comment still states "Updated files are recompiled", but compilation is now optional via the noCompile parameter. Please adjust the comment to reflect that recompilation is skipped when --no-compile is set.

Suggested change
// major version. Updated files are recompiled. By default all actions are updated to
// the latest major version; pass disableReleaseBump=true to only update core
// (actions/*) references.
// major version. By default, updated files are recompiled unless --no-compile is set.
// By default all actions are updated to the latest major version; pass
// disableReleaseBump=true to only update core (actions/*) references.

Copilot uses AI. Check for mistakes.
func UpdateActionsInWorkflowFiles(workflowsDir, engineOverride string, verbose, disableReleaseBump bool) error {
func UpdateActionsInWorkflowFiles(workflowsDir, engineOverride string, verbose, disableReleaseBump bool, noCompile bool) error {
if workflowsDir == "" {
workflowsDir = getWorkflowsDir()
}
Expand Down Expand Up @@ -528,10 +528,12 @@ func UpdateActionsInWorkflowFiles(workflowsDir, engineOverride string, verbose,
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Updated action references in "+d.Name()))
updatedFiles = append(updatedFiles, path)

// Recompile the updated workflow
if err := compileWorkflowWithRefresh(path, verbose, false, engineOverride, false); err != nil {
if verbose {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to recompile %s: %v", path, err)))
// Recompile the updated workflow (unless --no-compile is set)
if !noCompile {
if err := compileWorkflowWithRefresh(path, verbose, false, engineOverride, false); err != nil {
if verbose {
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to recompile %s: %v", path, err)))
Comment on lines +531 to +535
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

UpdateActionsInWorkflowFiles now has a noCompile path that skips the recompilation step, but there are no tests covering that behavior. Since compilation generates .lock.yml files, consider adding a test that asserts no lock file is created (and/or compilation isn't attempted) when noCompile=true.

Copilot uses AI. Check for mistakes.
}
}
}
return nil
Expand Down
13 changes: 8 additions & 5 deletions pkg/cli/update_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Examples:
` + string(constants.CLIExtensionPrefix) + ` update repo-assist --major # Allow major version updates
` + string(constants.CLIExtensionPrefix) + ` update --force # Force update even if no changes
` + string(constants.CLIExtensionPrefix) + ` update --disable-release-bump # Update without force-bumping all action versions
` + string(constants.CLIExtensionPrefix) + ` update --no-compile # Update without regenerating lock files
` + string(constants.CLIExtensionPrefix) + ` update --dir custom/workflows # Update workflows in custom directory
` + string(constants.CLIExtensionPrefix) + ` update --create-pull-request # Update and open a pull request`,
RunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -56,6 +57,7 @@ Examples:
stopAfter, _ := cmd.Flags().GetString("stop-after")
noMergeFlag, _ := cmd.Flags().GetBool("no-merge")
disableReleaseBump, _ := cmd.Flags().GetBool("disable-release-bump")
noCompile, _ := cmd.Flags().GetBool("no-compile")
createPRFlag, _ := cmd.Flags().GetBool("create-pull-request")
prFlagAlias, _ := cmd.Flags().GetBool("pr")
createPR := createPRFlag || prFlagAlias
Expand All @@ -70,7 +72,7 @@ Examples:
}
}

if err := RunUpdateWorkflows(args, majorFlag, forceFlag, verbose, engineOverride, workflowDir, noStopAfter, stopAfter, noMergeFlag, disableReleaseBump); err != nil {
if err := RunUpdateWorkflows(args, majorFlag, forceFlag, verbose, engineOverride, workflowDir, noStopAfter, stopAfter, noMergeFlag, disableReleaseBump, noCompile); err != nil {
return err
}

Expand All @@ -92,6 +94,7 @@ Examples:
cmd.Flags().String("stop-after", "", "Override stop-after value in the workflow (e.g., '+48h', '2025-12-31 23:59:59')")
cmd.Flags().Bool("no-merge", false, "Override local changes with upstream version instead of merging")
cmd.Flags().Bool("disable-release-bump", false, "Disable automatic major version bumps for all actions (only core actions/* are force-updated)")
cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files)")
cmd.Flags().Bool("create-pull-request", false, "Create a pull request with the update changes")
cmd.Flags().Bool("pr", false, "Alias for --create-pull-request")
_ = cmd.Flags().MarkHidden("pr") // Hide the short alias from help output
Expand All @@ -106,12 +109,12 @@ Examples:

// RunUpdateWorkflows updates workflows from their source repositories.
// Each workflow is compiled immediately after update.
func RunUpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool, engineOverride string, workflowsDir string, noStopAfter bool, stopAfter string, noMerge bool, disableReleaseBump bool) error {
updateLog.Printf("Starting update process: workflows=%v, allowMajor=%v, force=%v, noMerge=%v, disableReleaseBump=%v", workflowNames, allowMajor, force, noMerge, disableReleaseBump)
func RunUpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool, engineOverride string, workflowsDir string, noStopAfter bool, stopAfter string, noMerge bool, disableReleaseBump bool, noCompile bool) error {
Comment on lines 110 to +112
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The function doc comment says each workflow is compiled immediately after update, but this is no longer true when --no-compile is passed through (noCompile skips compilation). Please update this comment (and any related help text in this file) to reflect that compilation is conditional.

Copilot uses AI. Check for mistakes.
updateLog.Printf("Starting update process: workflows=%v, allowMajor=%v, force=%v, noMerge=%v, disableReleaseBump=%v, noCompile=%v", workflowNames, allowMajor, force, noMerge, disableReleaseBump, noCompile)

var firstErr error

if err := UpdateWorkflows(workflowNames, allowMajor, force, verbose, engineOverride, workflowsDir, noStopAfter, stopAfter, noMerge); err != nil {
if err := UpdateWorkflows(workflowNames, allowMajor, force, verbose, engineOverride, workflowsDir, noStopAfter, stopAfter, noMerge, noCompile); err != nil {
firstErr = fmt.Errorf("workflow update failed: %w", err)
}

Expand All @@ -125,7 +128,7 @@ func RunUpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool,

// Update action references in user-provided steps within workflow .md files.
// By default all org/repo@version references are updated to the latest major version.
if err := UpdateActionsInWorkflowFiles(workflowsDir, engineOverride, verbose, disableReleaseBump); err != nil {
if err := UpdateActionsInWorkflowFiles(workflowsDir, engineOverride, verbose, disableReleaseBump, noCompile); err != nil {
// Non-fatal: warn but don't fail the update
fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Warning: Failed to update action references in workflow files: %v", err)))
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/update_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ func TestRunUpdateWorkflows_NoSourceWorkflows(t *testing.T) {
os.Chdir(tmpDir)

// Running update with no source workflows should succeed with an info message, not an error
err := RunUpdateWorkflows(nil, false, false, false, "", "", false, "", false, false)
err := RunUpdateWorkflows(nil, false, false, false, "", "", false, "", false, false, false)
assert.NoError(t, err, "Should not error when no workflows with source field exist")
}

Expand All @@ -996,7 +996,7 @@ func TestRunUpdateWorkflows_SpecificWorkflowNotFound(t *testing.T) {
os.Chdir(tmpDir)

// Running update with a specific name that doesn't exist should fail
err := RunUpdateWorkflows([]string{"nonexistent"}, false, false, false, "", "", false, "", false, false)
err := RunUpdateWorkflows([]string{"nonexistent"}, false, false, false, "", "", false, "", false, false, false)
require.Error(t, err, "Should error when specified workflow not found")
assert.Contains(t, err.Error(), "no workflows found matching the specified names")
}
22 changes: 13 additions & 9 deletions pkg/cli/update_workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
)

// UpdateWorkflows updates workflows from their source repositories
func UpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool, engineOverride string, workflowsDir string, noStopAfter bool, stopAfter string, noMerge bool) error {
updateLog.Printf("Scanning for workflows with source field: dir=%s, filter=%v, noMerge=%v", workflowsDir, workflowNames, noMerge)
func UpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool, engineOverride string, workflowsDir string, noStopAfter bool, stopAfter string, noMerge bool, noCompile bool) error {
updateLog.Printf("Scanning for workflows with source field: dir=%s, filter=%v, noMerge=%v, noCompile=%v", workflowsDir, workflowNames, noMerge, noCompile)

// Use provided workflows directory or default
if workflowsDir == "" {
Expand Down Expand Up @@ -47,7 +47,7 @@ func UpdateWorkflows(workflowNames []string, allowMajor, force, verbose bool, en
// Update each workflow
for _, wf := range workflows {
updateLog.Printf("Updating workflow: %s (source: %s)", wf.Name, wf.SourceSpec)
if err := updateWorkflow(wf, allowMajor, force, verbose, engineOverride, noStopAfter, stopAfter, noMerge); err != nil {
if err := updateWorkflow(wf, allowMajor, force, verbose, engineOverride, noStopAfter, stopAfter, noMerge, noCompile); err != nil {
updateLog.Printf("Failed to update workflow %s: %v", wf.Name, err)
failedUpdates = append(failedUpdates, updateFailure{
Name: wf.Name,
Expand Down Expand Up @@ -319,7 +319,7 @@ func resolveLatestRelease(repo, currentRef string, allowMajor, verbose bool) (st
}

// updateWorkflow updates a single workflow from its source
func updateWorkflow(wf *workflowWithSource, allowMajor, force, verbose bool, engineOverride string, noStopAfter bool, stopAfter string, noMerge bool) error {
func updateWorkflow(wf *workflowWithSource, allowMajor, force, verbose bool, engineOverride string, noStopAfter bool, stopAfter string, noMerge bool, noCompile bool) error {
updateLog.Printf("Updating workflow: name=%s, source=%s, force=%v, noMerge=%v", wf.Name, wf.SourceSpec, force, noMerge)

if verbose {
Expand Down Expand Up @@ -544,11 +544,15 @@ func updateWorkflow(wf *workflowWithSource, allowMajor, force, verbose bool, eng
updateLog.Printf("Successfully updated workflow %s from %s to %s", wf.Name, currentRef, latestRef)
fmt.Fprintln(os.Stderr, console.FormatSuccessMessage(fmt.Sprintf("Updated %s from %s to %s", wf.Name, shortRef(currentRef), shortRef(latestRef))))

// Compile the updated workflow with refreshStopTime enabled
updateLog.Printf("Compiling updated workflow: %s", wf.Name)
if err := compileWorkflowWithRefresh(wf.Path, verbose, false, engineOverride, true); err != nil {
updateLog.Printf("Compilation failed for workflow %s: %v", wf.Name, err)
return fmt.Errorf("failed to compile updated workflow: %w", err)
// Compile the updated workflow with refreshStopTime enabled (unless --no-compile is set)
if !noCompile {
updateLog.Printf("Compiling updated workflow: %s", wf.Name)
if err := compileWorkflowWithRefresh(wf.Path, verbose, false, engineOverride, true); err != nil {
updateLog.Printf("Compilation failed for workflow %s: %v", wf.Name, err)
return fmt.Errorf("failed to compile updated workflow: %w", err)
}
} else {
updateLog.Printf("Skipping compilation of workflow %s (--no-compile specified)", wf.Name)
}

return nil
Expand Down
23 changes: 17 additions & 6 deletions pkg/cli/upgrade_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type UpgradeConfig struct {
Verbose bool
WorkflowDir string
NoFix bool
NoCompile bool
CreatePR bool
NoActions bool
Audit bool
Expand Down Expand Up @@ -59,6 +60,7 @@ Examples:
` + string(constants.CLIExtensionPrefix) + ` upgrade # Upgrade all workflows
` + string(constants.CLIExtensionPrefix) + ` upgrade --no-fix # Update agent files only (skip codemods, actions, and compilation)
` + string(constants.CLIExtensionPrefix) + ` upgrade --no-actions # Skip updating GitHub Actions versions
` + string(constants.CLIExtensionPrefix) + ` upgrade --no-compile # Skip recompiling workflows (do not modify lock files)
` + string(constants.CLIExtensionPrefix) + ` upgrade --create-pull-request # Upgrade and open a pull request
` + string(constants.CLIExtensionPrefix) + ` upgrade --dir custom/workflows # Upgrade workflows in custom directory
` + string(constants.CLIExtensionPrefix) + ` upgrade --audit # Check dependency health without upgrading
Expand All @@ -72,6 +74,7 @@ Examples:
prFlagAlias, _ := cmd.Flags().GetBool("pr")
createPR := createPRFlag || prFlagAlias
noActions, _ := cmd.Flags().GetBool("no-actions")
noCompile, _ := cmd.Flags().GetBool("no-compile")
auditFlag, _ := cmd.Flags().GetBool("audit")
jsonOutput, _ := cmd.Flags().GetBool("json")

Expand All @@ -86,7 +89,7 @@ Examples:
}
}

if err := runUpgradeCommand(verbose, dir, noFix, false, noActions); err != nil {
if err := runUpgradeCommand(verbose, dir, noFix, noCompile, noActions); err != nil {
return err
}

Expand All @@ -104,6 +107,7 @@ Examples:
cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")
cmd.Flags().Bool("no-fix", false, "Skip applying codemods, action updates, and compiling workflows (only update agent files)")
cmd.Flags().Bool("no-actions", false, "Skip updating GitHub Actions versions")
cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files)")
cmd.Flags().Bool("create-pull-request", false, "Create a pull request with the upgrade changes")
cmd.Flags().Bool("pr", false, "Alias for --create-pull-request")
_ = cmd.Flags().MarkHidden("pr") // Hide the short alias from help output
Expand Down Expand Up @@ -210,8 +214,8 @@ func runUpgradeCommand(verbose bool, workflowDir string, noFix bool, noCompile b
}
}

// Step 4: Compile all workflows (unless --no-fix is specified)
if !noFix {
// Step 4: Compile all workflows (unless --no-fix or --no-compile is specified)
if !noFix && !noCompile {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Compiling all workflows..."))
upgradeLog.Print("Compiling all workflows")

Expand Down Expand Up @@ -243,9 +247,16 @@ func runUpgradeCommand(verbose bool, workflowDir string, noFix bool, noCompile b
}
}
} else {
upgradeLog.Print("Skipping compilation (--no-fix specified)")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Skipping compilation (--no-fix specified)"))
if noFix {
upgradeLog.Print("Skipping compilation (--no-fix specified)")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Skipping compilation (--no-fix specified)"))
}
} else if noCompile {
upgradeLog.Print("Skipping compilation (--no-compile specified)")
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Skipping compilation (--no-compile specified)"))
}
}
}

Expand Down
Loading