Repository navigation
150 lines (134 loc) · 6.8 KB
/
Copy pathsquad-workflow-lint.yml
File metadata and controls
150 lines (134 loc) · 6.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
name: Workflow Lint
# Lints Squad's own workflows AND the bundled workflow templates that get
# shipped to downstream repos via `squad upgrade`. Templates live in
# packages/squad-cli/templates/workflows/ and packages/squad-sdk/templates/workflows/
# (both mirrored from .squad-templates/ at build time). Because templates are
# NOT under .github/workflows/, actionlint won't pick them up by default — we
# pass them as explicit file arguments so they receive the same shellcheck
# scrutiny as live workflows.
on:
workflow_dispatch:
inputs:
sha:
description: 'Full lowercase 40-hex commit SHA to lint'
required: true
type: string
pull_request:
branches: [dev, preview, main]
paths:
- '.github/workflows/**'
- 'packages/squad-cli/templates/workflows/**'
- 'packages/squad-sdk/templates/workflows/**'
- '.squad-templates/workflows/**'
- 'templates/workflows/**'
- 'workflows/**'
- 'scripts/check-workflow-input-interpolation.mjs'
push:
branches: [dev, main]
paths:
- '.github/workflows/**'
- 'packages/squad-cli/templates/workflows/**'
- 'packages/squad-sdk/templates/workflows/**'
- '.squad-templates/workflows/**'
- 'templates/workflows/**'
- 'workflows/**'
- 'scripts/check-workflow-input-interpolation.mjs'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
actionlint:
name: Lint workflows and templates
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Validate requested SHA
if: github.event_name == 'workflow_dispatch'
env:
SOURCE_SHA: ${{ inputs.sha }}
run: |
[[ "$SOURCE_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::sha must be a full lowercase 40-hex SHA, got '$SOURCE_SHA'"; exit 1; }
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
if: github.event_name != 'workflow_dispatch'
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 #v7
if: github.event_name == 'workflow_dispatch'
with:
ref: ${{ inputs.sha }}
fetch-depth: 0
- name: Assert checkout is exactly the requested SHA
if: github.event_name == 'workflow_dispatch'
env:
SOURCE_SHA: ${{ inputs.sha }}
run: |
head="$(git rev-parse HEAD)"
test "$head" = "$SOURCE_SHA" || { echo "::error::checkout HEAD $head != requested $SOURCE_SHA"; exit 1; }
- name: Install actionlint 1.7.12 and shellcheck 0.10.0
shell: bash
run: |
set -euo pipefail
# Installer pinned to v1.7.12 tag — not `main` — to avoid moving-ref RCE surface.
# Download to a named file before executing: curl -f hard-fails on non-200 so
# an unavailable URL aborts the step rather than silently feeding error HTML to bash.
# A named file is also inspectable on failure (vs opaque process substitution).
curl -fsSL https://raw.githubusercontent.com/rhysd/actionlint/v1.7.12/scripts/download-actionlint.bash \
> install-actionlint.bash
bash install-actionlint.bash 1.7.12
rm install-actionlint.bash
sudo mv actionlint /usr/local/bin/actionlint
# ubuntu-latest ships shellcheck 0.9.0 (via apt); install 0.10.0 explicitly
# to match the version that surfaced the original SC2086 reports.
# pipefail (set above) ensures a failed curl is not masked by tar's exit status.
curl -fsSL https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz \
| tar -xJf - --strip-components=1 shellcheck-v0.10.0/shellcheck
sudo mv shellcheck /usr/local/bin/shellcheck
echo "✅ actionlint $(actionlint --version)"
echo "✅ shellcheck $(shellcheck --version | grep 'version:')"
- name: Lint .github/workflows/*.yml
run: |
# Every workflow here is linted, including DO-NOT-EDIT generated output
# (*.lock.yml from `gh aw compile`, agentics-maintenance.yml from gh-aw's
# code generators).
#
# These files used to be skipped wholesale via a generated-header grep,
# because actionlint v1.7.12 — still the latest release, so this cannot be
# fixed by upgrading — reports errors against them for schema gaps rather
# than real defects. But skipping meant the artifact that actually runs got
# no lint at all, so a genuine defect in generated output was indistinguishable
# from the expected noise.
#
# Those gaps are now suppressed by exact error message and scoped file path in
# .github/actionlint.yaml, so every other error class still fails this job.
# Each suppression was verified by compiling the sources and linting the emitted
# output against the pinned actionlint version (#1827); see that file for the
# rationale, and re-check the list whenever actionlint is upgraded.
echo "--- Linting .github/workflows/ ---"
actionlint .github/workflows/*.yml
- name: Lint squad-cli template workflows
run: |
echo "--- Linting packages/squad-cli/templates/workflows/ ---"
actionlint packages/squad-cli/templates/workflows/*.yml
- name: Lint squad-sdk template workflows
run: |
echo "--- Linting packages/squad-sdk/templates/workflows/ ---"
actionlint packages/squad-sdk/templates/workflows/*.yml
# Lint the canonical source and root mirror independently from their committed state.
# All five directories contain tracked files; we lint what is actually committed rather
# than running sync-then-lint, because:
# (a) a bug introduced in .squad-templates/ is caught here before sync propagates it, and
# (b) mirror drift is already enforced by template-sync.test.ts as a separate gate.
- name: Lint canonical template source (.squad-templates/workflows/)
run: |
echo "--- Linting .squad-templates/workflows/ (canonical source) ---"
actionlint .squad-templates/workflows/*.yml
- name: Lint root mirror template workflows (templates/workflows/)
run: |
echo "--- Linting templates/workflows/ (root mirror) ---"
actionlint templates/workflows/*.yml
# actionlint only reads YAML. Agentic workflow prompts are Markdown, where a
# `github.event.inputs.x` reference written as prose is silently inert: the
# dispatched value never reaches the agent, the run still reports success, and
# the workflow no-ops with no visible signal. See #1740.
- name: Check agentic prompt input interpolation
run: node scripts/check-workflow-input-interpolation.mjs