main
yml 121 lines 4.5 KB
Raw
1 name: Squad Promote
2
3 on:
4 workflow_dispatch:
5 # checkov:skip=CKV_GHA_7:Operational promotion workflow (not a release build). The single dry_run toggle only switches between simulate/apply; it does not change the content being promoted. Input is required for safe manual operation.
6 inputs:
7 dry_run:
8 description: 'Dry run show what would happen without pushing'
9 required: false
10 default: 'false'
11 type: choice
12 options: ['false', 'true']
13
14 permissions:
15 contents: write
16
17 jobs:
18 dev-to-preview:
19 name: Promote dev → preview
20 runs-on: ubuntu-latest
21 steps:
22 - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
23 with:
24 fetch-depth: 0
25 token: ${{ secrets.GITHUB_TOKEN }}
26
27 - name: Configure git
28 run: |
29 git config user.name "github-actions[bot]"
30 git config user.email "github-actions[bot]@users.noreply.github.com"
31
32 - name: Fetch all branches
33 run: git fetch --all
34
35 - name: Show current state (dry run info)
36 run: |
37 echo "=== dev HEAD ===" && git log origin/dev -1 --oneline
38 echo "=== preview HEAD ===" && git log origin/preview -1 --oneline
39 echo "=== Files that would be stripped ==="
40 git diff origin/preview..origin/dev --name-only | grep -E "^(\.(ai-team|squad|ai-team-templates)|team-docs/|docs/proposals/)" || echo "(none)"
41
42 - name: Merge dev → preview (strip forbidden paths)
43 if: ${{ inputs.dry_run == 'false' }}
44 run: |
45 git checkout preview
46 git merge origin/dev --no-commit --no-ff -X theirs || true
47
48 # Strip forbidden paths from merge commit
49 git rm -rf --cached --ignore-unmatch \
50 .ai-team/ \
51 .squad/ \
52 .ai-team-templates/ \
53 team-docs/ \
54 "docs/proposals/" || true
55
56 # Commit if there are staged changes
57 if ! git diff --cached --quiet; then
58 git commit -m "chore: promote dev → preview (v$(node -e "console.log(require('./package.json').version)"))"
59 git push origin preview
60 echo "✅ Pushed preview branch"
61 else
62 echo "ℹ️ Nothing to commit — preview is already up to date"
63 fi
64
65 - name: Dry run complete
66 if: ${{ inputs.dry_run == 'true' }}
67 run: echo "🔍 Dry run complete — no changes pushed."
68
69 preview-to-main:
70 name: Promote preview → main (release)
71 needs: dev-to-preview
72 runs-on: ubuntu-latest
73 steps:
74 - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
75 with:
76 fetch-depth: 0
77 token: ${{ secrets.GITHUB_TOKEN }}
78
79 - name: Configure git
80 run: |
81 git config user.name "github-actions[bot]"
82 git config user.email "github-actions[bot]@users.noreply.github.com"
83
84 - name: Fetch all branches
85 run: git fetch --all
86
87 - name: Show current state
88 run: |
89 echo "=== preview HEAD ===" && git log origin/preview -1 --oneline
90 echo "=== main HEAD ===" && git log origin/main -1 --oneline
91 echo "=== Version ===" && node -e "console.log('v' + require('./package.json').version)"
92
93 - name: Validate preview is release-ready
94 run: |
95 git checkout preview
96 VERSION=$(node -e "console.log(require('./package.json').version)")
97 if ! grep -q "## \[$VERSION\]" CHANGELOG.md 2>/dev/null; then
98 echo "::error::Version $VERSION not found in CHANGELOG.md — update before releasing"
99 exit 1
100 fi
101 echo "✅ Version $VERSION has CHANGELOG entry"
102
103 # Verify no forbidden files on preview
104 FORBIDDEN=$(git ls-files | grep -E "^(\.(ai-team|squad|ai-team-templates)/|team-docs/|docs/proposals/)" || true)
105 if [ -n "$FORBIDDEN" ]; then
106 echo "::error::Forbidden files found on preview: $FORBIDDEN"
107 exit 1
108 fi
109 echo "✅ No forbidden files on preview"
110
111 - name: Merge preview → main
112 if: ${{ inputs.dry_run == 'false' }}
113 run: |
114 git checkout main
115 git merge origin/preview --no-ff -m "chore: promote preview → main (v$(node -e "console.log(require('./package.json').version)"))"
116 git push origin main
117 echo "✅ Pushed main — squad-release.yml will tag and publish the release"
118
119 - name: Dry run complete
120 if: ${{ inputs.dry_run == 'true' }}
121 run: echo "🔍 Dry run complete — no changes pushed."