Skip to content

squad upgrade regenerates workflows that fail actionlint/shellcheck (SC2086) and downgrade actions/checkout v7 -> v4 #1556

Closed

Description

@serbrech

Summary

squad upgrade regenerates the squad-* workflows from the upstream templates and, in doing so, reverts fixes the downstream repo had already applied. We hit two concrete regressions upgrading a repo from v0.9.6-build.1 → v0.11.0.

Repo: kubefleet-dev/kubefleet (squad workflows are committed there).

1. squad-heartbeat.yml fails actionlint + shellcheck (SC2086)

The generated .github/workflows/squad-heartbeat.yml writes to $GITHUB_OUTPUT unquoted:

      - name: Check triage script
        id: check-script
        run: |
          if [ -f ".squad/templates/ralph-triage.js" ]; then
            echo "has_script=true" >> $GITHUB_OUTPUT
          else
            echo "has_script=false" >> $GITHUB_OUTPUT

Any repo that runs actionlint (with shellcheck available) in CI now fails:

.github/workflows/squad-heartbeat.yml:32:9: shellcheck reported issue in this script: SC2086:info:2:29: Double quote to prevent globbing and word splitting [shellcheck]
.github/workflows/squad-heartbeat.yml:32:9: shellcheck reported issue in this script: SC2086:info:4:30: Double quote to prevent globbing and word splitting [shellcheck]

Reproduced locally with actionlint 1.7.12 + shellcheck 0.10.0 (same versions as our CI).

Fix: quote the redirect target — >> "$GITHUB_OUTPUT".

Worth running actionlint/shellcheck over the workflow templates in the squad repo's own CI so these don't ship.

2. actions/checkout downgraded v7 → v4

Our repo had already bumped actions/checkout to v7 in the squad workflows. squad upgrade reverted all of them back to v4 — 12 occurrences across 11 files:

squad-ci.yml, squad-docs.yml, squad-heartbeat.yml, squad-insider-release.yml, squad-issue-assign.yml, squad-label-enforce.yml, squad-preview.yml, squad-promote.yml (x2), squad-release.yml, squad-triage.yml, sync-squad-labels.yml

This is a silent dependency downgrade — nothing in the upgrade output flags it, so it is easy to merge without noticing.

Related: #1502 (making generated runners/checkout configurable) would help here, though this specific report is about the regression rather than configurability.

Impact

Because these files are regenerated wholesale, any downstream fix is reverted on the next squad upgrade. We're working around it by excluding squad-owned workflows from our actionlint job via .github/actionlint.yaml, but that means real issues in those workflows stop being caught downstream.

Suggestions

  • Quote "$GITHUB_OUTPUT" in the heartbeat template (and audit the other templates for the same pattern)
  • Lint the workflow templates in squad's own CI with actionlint + shellcheck
  • Consider not clobbering uses: action versions on upgrade, or at least reporting which generated files diverged from the previous content so the downgrade is visible

Environment

  • squad-cli 0.11.0 (global npm install)
  • upgraded from 0.9.6-build.1
  • Windows 11, Node v24.18.0
  • stateBackend: two-layer

Activity

  1. 1 remaining item

  2. added
    squadSquad triage inbox — Lead will assign to a member
    on Aug 23, 2026
  3. bradygaster commented on Aug 23, 2026

    @bradygaster
    Collaborator

    Owner & rationale

    Owner: Booster (squad:booster). This is about conventional GitHub Actions workflow templates emitted by squad upgrade, plus the CI lint gate that should catch bad generated YAML before release. Implementation may touch CLI upgrade plumbing, but the failure mode is workflow safety.

    This issue targets the templated workflow surface (packages/*/templates/workflows/*.yml copied to downstream .github/workflows/* by squad upgrade), not the gh-aw source workflow surface (workflows/*.md → .lock.yml).

    Files in scope

    Verified existing paths:

    • packages/squad-cli/templates/workflows/squad-ci.yml
    • packages/squad-cli/templates/workflows/squad-docs.yml
    • packages/squad-cli/templates/workflows/squad-heartbeat.yml
    • packages/squad-cli/templates/workflows/squad-insider-release.yml
    • packages/squad-cli/templates/workflows/squad-issue-assign.yml
    • packages/squad-cli/templates/workflows/squad-label-enforce.yml
    • packages/squad-cli/templates/workflows/squad-preview.yml
    • packages/squad-cli/templates/workflows/squad-promote.yml
    • packages/squad-cli/templates/workflows/squad-release.yml
    • packages/squad-cli/templates/workflows/squad-triage.yml
    • packages/squad-cli/templates/workflows/sync-squad-labels.yml
    • packages/squad-sdk/templates/workflows/squad-ci.yml
    • packages/squad-sdk/templates/workflows/squad-docs.yml
    • packages/squad-sdk/templates/workflows/squad-heartbeat.yml
    • packages/squad-sdk/templates/workflows/squad-insider-release.yml
    • packages/squad-sdk/templates/workflows/squad-issue-assign.yml
    • packages/squad-sdk/templates/workflows/squad-label-enforce.yml
    • packages/squad-sdk/templates/workflows/squad-preview.yml
    • packages/squad-sdk/templates/workflows/squad-promote.yml
    • packages/squad-sdk/templates/workflows/squad-release.yml
    • packages/squad-sdk/templates/workflows/squad-triage.yml
    • packages/squad-sdk/templates/workflows/sync-squad-labels.yml
    • packages/squad-cli/src/cli/core/upgrade.ts
    • packages/squad-cli/src/cli/core/templates.ts
    • index.cjs
    • .github/workflows/squad-workflow-lint.yml

    Reproduction / measurement

    I execution-tested the local lint tools first:

    actionlint --version

    Output:

    actionlint: The term 'actionlint' is not recognized as a name of a cmdlet, function, script file, or executable program.
    
    shellcheck --version

    Output:

    shellcheck: The term 'shellcheck' is not recognized as a name of a cmdlet, function, script file, or executable program.
    

    Local actionlint/shellcheck are unavailable in this environment. The exact CI job to read instead is Workflow Lint run 32522441420 on dev, which installs actionlint 1.7.12 and shellcheck 0.10.0 in .github/workflows/squad-workflow-lint.yml.

    Current-template measurement command I did run:

    git --no-pager grep -n "actions/checkout@\|GITHUB_OUTPUT" -- packages\squad-cli\templates\workflows packages\squad-sdk\templates\workflows

    Relevant output excerpt:

    packages/squad-cli/templates/workflows/squad-heartbeat.yml:28:      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 #v4
    packages/squad-cli/templates/workflows/squad-heartbeat.yml:34:            echo "has_script=true" >> "$GITHUB_OUTPUT"
    packages/squad-cli/templates/workflows/squad-heartbeat.yml:36:            echo "has_script=false" >> "$GITHUB_OUTPUT"
    packages/squad-cli/templates/workflows/sync-squad-labels.yml:22:      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
    packages/squad-sdk/templates/workflows/squad-heartbeat.yml:28:      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 #v4
    packages/squad-sdk/templates/workflows/squad-heartbeat.yml:34:            echo "has_script=true" >> "$GITHUB_OUTPUT"
    packages/squad-sdk/templates/workflows/squad-heartbeat.yml:36:            echo "has_script=false" >> "$GITHUB_OUTPUT"
    packages/squad-sdk/templates/workflows/sync-squad-labels.yml:22:      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
    

    So the heartbeat GITHUB_OUTPUT quoting appears already fixed on current dev, but checkout pin drift remains visible across the emitted templates/stubs.

    Verification bar

    A complete fix must make this fail before the fix and pass after it:

    • Run the existing workflow lint gate (.github/workflows/squad-workflow-lint.yml) against all conventional workflow templates with actionlint 1.7.12 + shellcheck 0.10.0.
    • Add a regression check that runs squad upgrade into a scratch repo and fails if generated workflow checkout refs drift from the repository-pinned checkout policy (for the reported regression, no generated output may downgrade a v7 pin back to a v4 tag/hash).
    • The guard must cover both verbatim template copies and non-npm stubs generated by generateProjectWorkflowStub.

    Traps

    • The actions/checkout v7→v4 downgrade is a regression in generated output. Do not just bump one template once; add a guard that fails when generated workflows drift from the pinned action versions.
    • .github/workflows/squad-workflow-lint.yml already exists and already lints the template directories. Reconcile with it; do not add a parallel workflow-lint path.
    • Do not confuse this with gh-aw compilation. Emitted .lock.yml fails actionlint with 6 errors (copilot-requests scope, concurrency.queue) #1827 concerns .lock.yml emitted from workflows/*.md; this issue concerns conventional YAML templates copied by squad upgrade. They share the “generated YAML must lint clean” theme but are separate code paths, with no sequential dependency.
    • Current dev already quotes $GITHUB_OUTPUT in the heartbeat templates, so a fix that only reapplies that change may be a no-op for this repo.

    Out of scope

    Session-stall guard

    Before starting: this repo has phantom CRLF diffs (#1793). If git status shows files modified that you did not touch, run git diff --ignore-cr-at-eol. If that output is empty, the diff is line-ending churn, not real edits — run git add --renormalize . and continue. Do not halt and ask for confirmation; halting on phantom diffs is the documented cause of stuck sessions in this repo.

  4. bradygaster commented on Aug 30, 2026

    @bradygaster
    Collaborator

    PR #1557 fixed the SC2086/shellcheck and actionlint failures. The remaining concern — \squad upgrade\ downgrading \�ctions/checkout\ from v7 to v4 when regenerating workflows — is consolidated into #1502 (the runner/checkout configurability umbrella). Closing as completed/superseded; checkout-version preservation tracking continues in #1502.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    go:spec-readyReady for formal spec/proposalpriority:p1This sprintsquadSquad triage inbox — Lead will assign to a membertriagedIssue has been triagedtype:bugSomething brokenwave:1-nextWave 1 — immediate next sprintworkflows

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions