breakaway 1.4.0-main.2 → 1.4.0-main.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,212 @@
1
+ # {{header}}
2
+ #
3
+ # Release: the npm package {{packageName}}. Every merge to {{branchName}} that passes its checks stages a pre-release,
4
+ # X.Y.Z-main.N, on next; the owner releases one as the stable X.Y.Z, on latest, from the same commit. Nothing is
5
+ # published by itself: each version waits, staged on npm, until the owner approves it with 2FA (npm stage approve, or
6
+ # Staged Packages on npmjs.com). The version comes from {{packageDirectory}}/package.json. Keep this file's name: npm's
7
+ # trusted publisher names it, with the npm environment. Agents never run this workflow.
8
+ name: Release
9
+
10
+ on:
11
+ workflow_run:
12
+ workflows: {{checks}}
13
+ types: [completed]
14
+ branches: [{{branch}}]
15
+ # The owner releases a pre-release as stable: the board's Release button, or Actions, Run workflow.
16
+ workflow_dispatch:
17
+ inputs:
18
+ prerelease:
19
+ description: The pre-release to release as stable, like {{prefixName}}1.4.0-main.5
20
+ required: true
21
+ type: string
22
+
23
+ permissions: {}
24
+
25
+ concurrency:
26
+ group: release
27
+ cancel-in-progress: false
28
+
29
+ env:
30
+ PACKAGE: {{package}}
31
+ DIRECTORY: {{directory}}
32
+ ACCESS: {{access}}
33
+ # The tags that count the versions: <prefix>X.Y.Z-main.N for each pre-release, <prefix>X.Y.Z for each stable.
34
+ PREFIX: {{prefix}}
35
+ CHECKS: {{checksEnv}}
36
+
37
+ jobs:
38
+ prerelease:
39
+ name: pre-release
40
+ if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && github.event.workflow_run.head_repository.full_name == github.repository
41
+ runs-on: ubuntu-latest
42
+ timeout-minutes: 20
43
+ # The npm environment, which only {{branchName}} may use, is where npm's trusted publisher points, and holds
44
+ # NPM_TOKEN until that applies.
45
+ environment: npm
46
+ permissions:
47
+ contents: write
48
+ id-token: write
49
+ actions: read
50
+ env:
51
+ GITHUB_TOKEN: ${{ github.token }}
52
+ GH_TOKEN: ${{ github.token }}
53
+ SHA: ${{ github.event.workflow_run.head_sha }}
54
+ DEPLOYS_PAUSED: ${{ vars.DEPLOYS_PAUSED }}
55
+ steps:
56
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
57
+ with:
58
+ ref: ${{ github.event.workflow_run.head_sha }}
59
+ fetch-depth: 0
60
+ persist-credentials: false
61
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
62
+ with:
63
+ node-version: 22
64
+ registry-url: https://registry.npmjs.org
65
+
66
+ - name: Check it should release
67
+ id: plan
68
+ run: |
69
+ set -euo pipefail
70
+ if [ "$DEPLOYS_PAUSED" = true ]; then
71
+ echo "::notice title=Paused::Releases are paused (DEPLOYS_PAUSED is true), so ${SHA:0:7} staged nothing."
72
+ echo "ready=false" >> "$GITHUB_OUTPUT"
73
+ exit 0
74
+ fi
75
+ node scripts/deploy-plan.mjs checks --sha "$SHA" --checks "$CHECKS" >> "$GITHUB_OUTPUT"
76
+
77
+ - name: Pick the version
78
+ id: version
79
+ if: steps.plan.outputs.ready == 'true'
80
+ run: node scripts/package-release.mjs prerelease --dir "$DIRECTORY" --prefix "$PREFIX" --sha "$SHA" >> "$GITHUB_OUTPUT"
81
+
82
+ - name: Install and build
83
+ if: steps.plan.outputs.ready == 'true' && steps.version.outputs.exists == 'false'
84
+ env:
85
+ VERSION: ${{ steps.version.outputs.version }}
86
+ run: |
87
+ set -euo pipefail
88
+ if grep -q '"packageManager"' package.json 2>/dev/null; then corepack enable; fi
89
+ {{@install}}
90
+ {{@build}}
91
+ node -e "const f=require('path').join(process.env.DIRECTORY,'package.json'),p=JSON.parse(require('fs').readFileSync(f));p.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(p,null,2)+'\n')"
92
+
93
+ # Staged, never published: it goes live on next once the owner approves it with 2FA. npm tries trusted publishing
94
+ # first; NPM_TOKEN stands in until it applies, a token that can't bypass 2FA, so it never publishes by itself.
95
+ - name: Stage it on npm
96
+ if: steps.plan.outputs.ready == 'true' && steps.version.outputs.exists == 'false'
97
+ env:
98
+ VERSION: ${{ steps.version.outputs.version }}
99
+ DIST_TAG: next
100
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
101
+ # npm refuses provenance from a private repository.
102
+ PROVENANCE: ${{ github.event.repository.private && 'no' || 'yes' }}
103
+ run: |
104
+ set -euo pipefail
105
+ cd "$DIRECTORY"
106
+ npm install -g npm@^11.15.0
107
+ provenance=""
108
+ if [ "$PROVENANCE" = yes ]; then provenance=--provenance; fi
109
+ # npm says why trusted publishing didn't apply only in its verbose log. Keep that log to the runner and show
110
+ # npm's usual lines, and on a failure its oidc lines: never the whole verbose log.
111
+ if npm stage publish $provenance --access "$ACCESS" --tag "$DIST_TAG" --loglevel verbose > "$RUNNER_TEMP/npm.log" 2>&1; then
112
+ grep -vE '^npm (verbose|http|timing|silly)' "$RUNNER_TEMP/npm.log" || true
113
+ echo "::notice title=Staged on npm::$PACKAGE@$VERSION goes live on $DIST_TAG once the owner approves it with 2FA: npm stage approve <id>, or Staged Packages on npmjs.com."
114
+ else
115
+ grep -vE '^npm (verbose|http|timing|silly)' "$RUNNER_TEMP/npm.log" || true
116
+ if grep -qiE 'previously published|cannot publish over' "$RUNNER_TEMP/npm.log"; then
117
+ echo "::error title=Already on npm::$PACKAGE@$VERSION is already on npm, and npm takes a version once. Nothing was staged."
118
+ exit 1
119
+ fi
120
+ echo "npm's trusted publishing (OIDC):"
121
+ oidc=$(grep -i 'oidc' "$RUNNER_TEMP/npm.log" | grep -v 'eyJ' | cut -c1-300 || true)
122
+ echo "${oidc:-npm logged nothing about it.}"
123
+ echo "::error title=npm refused to stage it::npm's trusted publisher for $PACKAGE must name exactly: GitHub Actions, user ${GITHUB_REPOSITORY%%/*}, repository ${GITHUB_REPOSITORY#*/}, workflow release.yml, environment npm. Until it applies, the npm environment needs NPM_TOKEN: a granular token with read and write access to $PACKAGE that doesn't bypass 2FA."
124
+ exit 1
125
+ fi
126
+
127
+ - name: Tag it
128
+ if: steps.plan.outputs.ready == 'true' && steps.version.outputs.exists == 'false'
129
+ env:
130
+ TAG: ${{ steps.version.outputs.tag }}
131
+ run: gh api -X POST "repos/$GITHUB_REPOSITORY/git/refs" -f "ref=refs/tags/$TAG" -f "sha=$SHA" > /dev/null
132
+
133
+ stable:
134
+ name: stable
135
+ if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/{{branchName}}'
136
+ runs-on: ubuntu-latest
137
+ timeout-minutes: 20
138
+ environment: npm
139
+ permissions:
140
+ contents: write
141
+ id-token: write
142
+ env:
143
+ GITHUB_TOKEN: ${{ github.token }}
144
+ GH_TOKEN: ${{ github.token }}
145
+ PRERELEASE: ${{ inputs.prerelease }}
146
+ DEPLOYS_PAUSED: ${{ vars.DEPLOYS_PAUSED }}
147
+ steps:
148
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
149
+ with:
150
+ fetch-depth: 0
151
+ persist-credentials: false
152
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
153
+ with:
154
+ node-version: 22
155
+ registry-url: https://registry.npmjs.org
156
+
157
+ - name: Pick the stable
158
+ id: version
159
+ run: |
160
+ set -euo pipefail
161
+ if [ "$DEPLOYS_PAUSED" = true ]; then
162
+ echo "::error title=Paused::Releases are paused (DEPLOYS_PAUSED is true). Release again when the pause is over."
163
+ exit 1
164
+ fi
165
+ node scripts/package-release.mjs stable "$PRERELEASE" --prefix "$PREFIX" >> "$GITHUB_OUTPUT"
166
+
167
+ # The pre-release's own commit, under the stable version: nothing from a later commit.
168
+ - name: Install and build the pre-release's commit
169
+ env:
170
+ VERSION: ${{ steps.version.outputs.version }}
171
+ COMMIT: ${{ steps.version.outputs.commit }}
172
+ run: |
173
+ set -euo pipefail
174
+ git checkout --detach "$COMMIT"
175
+ if grep -q '"packageManager"' package.json 2>/dev/null; then corepack enable; fi
176
+ {{@install}}
177
+ {{@build}}
178
+ node -e "const f=require('path').join(process.env.DIRECTORY,'package.json'),p=JSON.parse(require('fs').readFileSync(f));p.version=process.env.VERSION;require('fs').writeFileSync(f,JSON.stringify(p,null,2)+'\n')"
179
+
180
+ - name: Stage it on npm
181
+ env:
182
+ VERSION: ${{ steps.version.outputs.version }}
183
+ DIST_TAG: latest
184
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
185
+ PROVENANCE: ${{ github.event.repository.private && 'no' || 'yes' }}
186
+ run: |
187
+ set -euo pipefail
188
+ cd "$DIRECTORY"
189
+ npm install -g npm@^11.15.0
190
+ provenance=""
191
+ if [ "$PROVENANCE" = yes ]; then provenance=--provenance; fi
192
+ if npm stage publish $provenance --access "$ACCESS" --tag "$DIST_TAG" --loglevel verbose > "$RUNNER_TEMP/npm.log" 2>&1; then
193
+ grep -vE '^npm (verbose|http|timing|silly)' "$RUNNER_TEMP/npm.log" || true
194
+ echo "::notice title=Staged on npm::$PACKAGE@$VERSION goes live on $DIST_TAG once the owner approves it with 2FA: npm stage approve <id>, or Staged Packages on npmjs.com."
195
+ else
196
+ grep -vE '^npm (verbose|http|timing|silly)' "$RUNNER_TEMP/npm.log" || true
197
+ if grep -qiE 'previously published|cannot publish over' "$RUNNER_TEMP/npm.log"; then
198
+ echo "::error title=Already on npm::$PACKAGE@$VERSION is already on npm, and npm takes a version once. Nothing was staged."
199
+ exit 1
200
+ fi
201
+ echo "npm's trusted publishing (OIDC):"
202
+ oidc=$(grep -i 'oidc' "$RUNNER_TEMP/npm.log" | grep -v 'eyJ' | cut -c1-300 || true)
203
+ echo "${oidc:-npm logged nothing about it.}"
204
+ echo "::error title=npm refused to stage it::npm's trusted publisher for $PACKAGE must name exactly: GitHub Actions, user ${GITHUB_REPOSITORY%%/*}, repository ${GITHUB_REPOSITORY#*/}, workflow release.yml, environment npm. Until it applies, the npm environment needs NPM_TOKEN: a granular token with read and write access to $PACKAGE that doesn't bypass 2FA."
205
+ exit 1
206
+ fi
207
+
208
+ - name: Tag it
209
+ env:
210
+ TAG: ${{ steps.version.outputs.tag }}
211
+ COMMIT: ${{ steps.version.outputs.commit }}
212
+ run: gh api -X POST "repos/$GITHUB_REPOSITORY/git/refs" -f "ref=refs/tags/$TAG" -f "sha=$COMMIT" > /dev/null
@@ -0,0 +1,98 @@
1
+ # {{header}}
2
+ #
3
+ # Roll back: puts production, the Worker {{productionName}}, back on a version it ran before. The board's Roll back
4
+ # button starts it, or Actions, Run workflow (the GitHub mobile app too). It is never paused. Staging goes back by
5
+ # deploying again. Agents never run this workflow.
6
+ name: Roll back
7
+
8
+ on:
9
+ workflow_dispatch:
10
+ inputs:
11
+ worker:
12
+ description: The Worker to roll back (production's)
13
+ required: true
14
+ default: {{production}}
15
+ type: string
16
+ version:
17
+ description: The version to go back to (blank for the one before)
18
+ required: false
19
+ type: string
20
+ reason:
21
+ description: What broke
22
+ required: true
23
+ type: string
24
+
25
+ permissions: {}
26
+
27
+ concurrency:
28
+ group: deploy-production
29
+ cancel-in-progress: false
30
+
31
+ env:
32
+ PRODUCTION: {{production}}
33
+ HEALTH_URL: {{healthProduction}}
34
+
35
+ jobs:
36
+ rollback:
37
+ name: roll back
38
+ if: github.ref == 'refs/heads/{{branchName}}'
39
+ runs-on: ubuntu-latest
40
+ timeout-minutes: 15
41
+ environment: production
42
+ permissions:
43
+ contents: read
44
+ deployments: write
45
+ env:
46
+ GITHUB_TOKEN: ${{ github.token }}
47
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
48
+ CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
49
+ TARGET: ${{ inputs.worker }}
50
+ VERSION: ${{ inputs.version }}
51
+ REASON: ${{ inputs.reason }}
52
+ RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
53
+ steps:
54
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
55
+ with:
56
+ persist-credentials: false
57
+ - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
58
+ with:
59
+ node-version: 22
60
+
61
+ - name: Roll back
62
+ run: |
63
+ set -euo pipefail
64
+ if [ "$TARGET" != "$PRODUCTION" ]; then
65
+ echo "::error title=Production only::Roll back runs on production, $PRODUCTION, not $TARGET. Staging goes back by deploying again."
66
+ exit 1
67
+ fi
68
+ if [ -n "$VERSION" ] && ! [[ "$VERSION" =~ ^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$ ]]; then
69
+ echo "::error title=Not a version::$VERSION isn't a Worker version ID. Leave it blank to go back to the one before."
70
+ exit 1
71
+ fi
72
+ helpers="$GITHUB_WORKSPACE/scripts"
73
+ # Outside the checkout, so wrangler reads no config: the Worker is named, and only its versions change.
74
+ cd "$RUNNER_TEMP"
75
+ wrangler() { npx --yes wrangler@4 "$@" --name "$PRODUCTION"; }
76
+ wrangler rollback ${VERSION:+"$VERSION"} --message "$REASON" --yes
77
+ wrangler deployments list --json > deployments.json
78
+ now=$(node "$helpers/deploy-plan.mjs" current < deployments.json | sed 's/^version=//')
79
+ sha=$(node "$helpers/deploy-plan.mjs" sha-of --environment "$PRODUCTION" --version "$now" | sed 's/^sha=//')
80
+ if [ -z "$sha" ]; then
81
+ echo "::warning title=Commit unknown::No Deployment recorded version $now, so the rollback is recorded on $GITHUB_SHA."
82
+ sha=$GITHUB_SHA
83
+ fi
84
+ deployment=$(node "$helpers/record-deployment.mjs" --environment "$PRODUCTION" --sha "$sha" --task rollback --production --state in_progress --description "rolling back" --log-url "$RUN_URL")
85
+ state=success
86
+ if [ -n "$HEALTH_URL" ]; then
87
+ state=failure
88
+ for attempt in $(seq 1 18); do
89
+ if curl -fsS --max-time 10 -o /dev/null "$HEALTH_URL"; then state=success; break; fi
90
+ sleep 5
91
+ done
92
+ fi
93
+ node "$helpers/record-deployment.mjs" --deployment "$deployment" --state "$state" --note "rolled back: $REASON" --version "$now" --log-url "$RUN_URL" > /dev/null
94
+ if [ "$state" != success ]; then
95
+ echo "::error title=Still failing::Production went back to version $now, but $HEALTH_URL doesn't answer. Read the Worker's logs on Cloudflare."
96
+ exit 1
97
+ fi
98
+ echo "Production runs version $now again (${sha:0:7})."