updateWorkflow updates a single workflow from its source
(ctx context.Context, wf *workflowWithSource, opts UpdateWorkflowsOptions)
| 588 | |
| 589 | // updateWorkflow updates a single workflow from its source |
| 590 | func updateWorkflow(ctx context.Context, wf *workflowWithSource, opts UpdateWorkflowsOptions) error { |
| 591 | updateLog.Printf("Updating workflow: name=%s, source=%s, force=%v, noMerge=%v", wf.Name, wf.SourceSpec, opts.Force, opts.NoMerge) |
| 592 | |
| 593 | if opts.Verbose { |
| 594 | fmt.Fprintln(os.Stderr, "") |
| 595 | fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Updating workflow: "+wf.Name)) |
| 596 | fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Source: "+wf.SourceSpec)) |
| 597 | } |
| 598 | |
| 599 | // Parse source spec |
| 600 | initialSourceSpec, err := parseSourceSpec(wf.SourceSpec) |
| 601 | if err != nil { |
| 602 | updateLog.Printf("Failed to parse source spec: %v", err) |
| 603 | return fmt.Errorf("failed to parse source spec: %w", err) |
| 604 | } |
| 605 | |
| 606 | resolvedLocation, err := resolveRedirectedUpdateLocation(ctx, wf.Name, initialSourceSpec, opts.AllowMajor, opts.Verbose, opts.NoRedirect, opts.CoolDown) |
| 607 | if err != nil { |
| 608 | return err |
| 609 | } |
| 610 | |
| 611 | sourceSpec := resolvedLocation.sourceSpec |
| 612 | currentRef := resolvedLocation.currentRef |
| 613 | latestRef := resolvedLocation.latestRef |
| 614 | sourceFieldRef := resolvedLocation.sourceFieldRef |
| 615 | newContent := resolvedLocation.content |
| 616 | |
| 617 | if opts.Verbose { |
| 618 | fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Current ref: "+currentRef)) |
| 619 | fmt.Fprintln(os.Stderr, console.FormatVerboseMessage("Latest ref: "+latestRef)) |
| 620 | } |
| 621 | |
| 622 | // Check if update is needed |
| 623 | if !opts.Force && currentRef == latestRef && len(resolvedLocation.redirectHistory) == 0 { |
| 624 | updateLog.Printf("Workflow already at latest ref: %s, checking for local modifications", currentRef) |
| 625 | |
| 626 | // Download the source content to check if local file has been modified |
| 627 | sourceContent, err := downloadWorkflowContentFn(ctx, sourceSpec.Repo, sourceSpec.Path, currentRef, opts.Verbose) |
| 628 | if err != nil { |
| 629 | // If we can't download for comparison, just show the up-to-date message |
| 630 | if opts.Verbose { |
| 631 | fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("Failed to download source for comparison: %v", err))) |
| 632 | } |
| 633 | fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Workflow %s is already up to date (%s)", wf.Name, shortRef(currentRef)))) |
| 634 | return nil |
| 635 | } |
| 636 | |
| 637 | // Read current workflow content |
| 638 | currentContent, err := os.ReadFile(wf.Path) |
| 639 | if err != nil { |
| 640 | return fmt.Errorf("failed to read current workflow: %w", err) |
| 641 | } |
| 642 | |
| 643 | // Check if local file differs from source |
| 644 | if hasLocalModifications(string(sourceContent), string(currentContent), wf.SourceSpec, filepath.Dir(wf.Path), opts.Verbose) { |
| 645 | updateLog.Printf("Local modifications detected in workflow: %s", wf.Name) |
| 646 | fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Workflow %s is already up to date (%s)", wf.Name, shortRef(currentRef)))) |
| 647 | fmt.Fprintln(os.Stderr, console.FormatWarningMessage(fmt.Sprintf("⚠️ Local copy of %s has been modified from source", wf.Name))) |
no test coverage detected