@sidebase/base-config 0.2.1 → 0.3.0
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.
- package/README.md +66 -32
- package/dist/config.d.mts +14 -12
- package/dist/config.d.ts +14 -12
- package/dist/config.mjs +5 -4
- package/dist/eslint/index.d.mts +43 -4
- package/dist/eslint/index.d.ts +43 -4
- package/package.json +12 -11
- package/presets/base/AGENTS.md +0 -5
- package/presets/base/github/workflows/streamctl-upgrade.yml +358 -65
- package/presets/base/gitignore +0 -3
- package/presets/base/pnpm-workspace.yaml +1 -0
- package/presets/base/preset.json +9 -2
- package/presets/config.template.ts +2 -3
- package/presets/nuxt-app/Dockerfile +2 -1
- package/presets/nuxt-app/github/workflows/ci.yml +6 -6
- package/presets/nuxt-app/preset.json +18 -20
- package/presets/nuxt-app/templates/ci/e2e-job.yml +3 -3
- package/presets/nuxt-app/templates/ci/test-job.yml +3 -3
- package/dist/shared/base-config.BoberVUk.d.mts +0 -43
- package/dist/shared/base-config.BoberVUk.d.ts +0 -43
- package/presets/base/CLAUDE.md +0 -3
|
@@ -1,49 +1,42 @@
|
|
|
1
|
-
# Managed by streamctl.
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
# Needs `secrets.STREAMCTL_PR_TOKEN`: a PR opened with `GITHUB_TOKEN` does not trigger
|
|
5
|
-
# `pull_request` workflows, so the repo's own `check` gate would never run on it.
|
|
6
|
-
#
|
|
7
|
-
# A repo with private dependencies must opt this file out and wire its own auth:
|
|
8
|
-
# `files: { ".github/workflows/streamctl-upgrade.yml": "off" }`.
|
|
1
|
+
# Managed by streamctl. Enabled by `automation.upgradePr`.
|
|
2
|
+
# Repos with private dependencies should own this workflow.
|
|
3
|
+
# Workflow updates need the configured token with Contents, Pull requests, and Workflows write.
|
|
9
4
|
name: streamctl upgrade
|
|
10
5
|
|
|
11
6
|
on:
|
|
12
7
|
schedule:
|
|
13
|
-
- cron: "0 6 * * 1"
|
|
8
|
+
- cron: "0 6 * * 1"
|
|
14
9
|
workflow_dispatch:
|
|
15
10
|
|
|
16
|
-
# Every PR and issue write below uses STREAMCTL_PR_TOKEN, so the default token
|
|
17
|
-
# only needs to read the repo for checkout.
|
|
18
11
|
permissions:
|
|
19
|
-
contents:
|
|
12
|
+
contents: write
|
|
13
|
+
issues: write
|
|
14
|
+
pull-requests: write
|
|
20
15
|
|
|
21
16
|
env:
|
|
17
|
+
ALLOW_WORKFLOW_UPDATES: "${ALLOW_WORKFLOW_UPDATES}"
|
|
22
18
|
NODE_VERSION: "${NODE_VERSION}"
|
|
19
|
+
CI_APT_PACKAGES: "${CI_APT_PACKAGES}"
|
|
20
|
+
# Block scalar so quotes, `#` and `: ` in the command stay literal.
|
|
21
|
+
PREPARE_COMMAND: >-
|
|
22
|
+
${PREPARE_COMMAND}
|
|
23
23
|
|
|
24
24
|
jobs:
|
|
25
25
|
upgrade:
|
|
26
26
|
runs-on: ubuntu-latest
|
|
27
27
|
steps:
|
|
28
|
-
# To mint an App token in-workflow instead of storing a PAT, uncomment this
|
|
29
|
-
# and use `${{ steps.bot.outputs.token }}` in place of STREAMCTL_PR_TOKEN:
|
|
30
|
-
#
|
|
31
|
-
# - id: bot
|
|
32
|
-
# uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
|
|
33
|
-
# with:
|
|
34
|
-
# app-id: ${{ secrets.STREAMCTL_APP_ID }}
|
|
35
|
-
# private-key: ${{ secrets.STREAMCTL_APP_PRIVATE_KEY }}
|
|
36
|
-
|
|
37
28
|
- name: Checkout
|
|
38
|
-
uses: actions/checkout@
|
|
29
|
+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
39
32
|
|
|
40
33
|
- name: Set up pnpm
|
|
41
|
-
uses: pnpm/action-setup@
|
|
34
|
+
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
42
35
|
with:
|
|
43
36
|
run_install: false
|
|
44
37
|
|
|
45
38
|
- name: Set up Node.js
|
|
46
|
-
uses: actions/setup-node@
|
|
39
|
+
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
|
|
47
40
|
with:
|
|
48
41
|
node-version: ${{ env.NODE_VERSION }}
|
|
49
42
|
cache: pnpm
|
|
@@ -51,70 +44,370 @@ jobs:
|
|
|
51
44
|
- name: Install dependencies
|
|
52
45
|
run: pnpm install --frozen-lockfile
|
|
53
46
|
|
|
54
|
-
|
|
47
|
+
- name: Capture managed-file state
|
|
48
|
+
run: pnpm streamctl status --json > "$RUNNER_TEMP/streamctl-status.json"
|
|
49
|
+
|
|
55
50
|
- id: check
|
|
56
51
|
name: Check for a payload update
|
|
57
52
|
run: |
|
|
58
53
|
set +e
|
|
59
|
-
pnpm streamctl check --fail-on
|
|
60
|
-
|
|
54
|
+
pnpm streamctl check --fail-on any --json > "$RUNNER_TEMP/streamctl-check.json"
|
|
55
|
+
code=$?
|
|
61
56
|
set -e
|
|
62
|
-
|
|
57
|
+
echo "code=$code" >> "$GITHUB_OUTPUT"
|
|
58
|
+
echo "target=$(jq -r '.error.details.updateAvailable.latest // empty' "$RUNNER_TEMP/streamctl-check.json")" >> "$GITHUB_OUTPUT"
|
|
59
|
+
cat "$RUNNER_TEMP/streamctl-check.json"
|
|
60
|
+
|
|
61
|
+
- name: Fail on an unexpected check result
|
|
62
|
+
if: ${{ steps.check.outputs.code != '0' && steps.check.outputs.code != '3' && steps.check.outputs.code != '4' }}
|
|
63
|
+
run: exit 1
|
|
63
64
|
|
|
64
|
-
- name:
|
|
65
|
+
- name: Require an update target
|
|
66
|
+
if: ${{ steps.check.outputs.code == '4' }}
|
|
67
|
+
env:
|
|
68
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
69
|
+
run: test -n "$TARGET"
|
|
70
|
+
|
|
71
|
+
- name: Ensure workflow labels
|
|
72
|
+
if: ${{ steps.check.outputs.code == '3' || steps.check.outputs.code == '4' }}
|
|
73
|
+
env:
|
|
74
|
+
GH_TOKEN: ${{ github.token }}
|
|
75
|
+
run: |
|
|
76
|
+
gh label create streamctl --color 0E8A16 --description "Managed by streamctl" --force
|
|
77
|
+
gh label create needs-interactive-upgrade --color D93F0B --description "Manual upgrade work required" --force
|
|
78
|
+
|
|
79
|
+
- name: Require the PR token
|
|
80
|
+
if: ${{ steps.check.outputs.code == '4' && env.ALLOW_WORKFLOW_UPDATES == 'true' }}
|
|
81
|
+
env:
|
|
82
|
+
PR_TOKEN: ${{ secrets.${PR_TOKEN_SECRET} }}
|
|
83
|
+
run: test -n "$PR_TOKEN"
|
|
84
|
+
|
|
85
|
+
- name: Open or update the drift issue
|
|
65
86
|
if: ${{ steps.check.outputs.code == '3' }}
|
|
66
87
|
env:
|
|
67
|
-
GH_TOKEN: ${{
|
|
88
|
+
GH_TOKEN: ${{ github.token }}
|
|
68
89
|
run: |
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
title="streamctl: managed files have drifted"
|
|
91
|
+
body="The automated upgrade was skipped because managed files already differ. Run \`pnpm streamctl sync\` locally, commit the result, then rerun this workflow. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
92
|
+
issue_number=$(gh issue list --state open --label streamctl --search "\"$title\" in:title" --json number --jq '.[0].number // empty')
|
|
93
|
+
if [[ -n "$issue_number" ]]; then
|
|
94
|
+
gh issue edit "$issue_number" --body "$body"
|
|
95
|
+
else
|
|
96
|
+
gh issue create --title "$title" --label streamctl --body "$body"
|
|
97
|
+
fi
|
|
73
98
|
|
|
74
|
-
# Only upgrade when an update is actually available (check exit 4).
|
|
75
99
|
- id: upgrade
|
|
76
100
|
name: Upgrade the payload
|
|
77
101
|
if: ${{ steps.check.outputs.code == '4' }}
|
|
102
|
+
env:
|
|
103
|
+
CI: "false"
|
|
104
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
78
105
|
run: |
|
|
79
106
|
set +e
|
|
80
|
-
pnpm streamctl upgrade --json > streamctl-upgrade.
|
|
81
|
-
|
|
107
|
+
pnpm streamctl upgrade --to "$TARGET" --yes --json > "$RUNNER_TEMP/streamctl-upgrade.raw"
|
|
108
|
+
code=$?
|
|
82
109
|
set -e
|
|
83
|
-
|
|
110
|
+
tail -n 1 "$RUNNER_TEMP/streamctl-upgrade.raw" > "$RUNNER_TEMP/streamctl-upgrade.json"
|
|
111
|
+
echo "code=$code" >> "$GITHUB_OUTPUT"
|
|
112
|
+
cat "$RUNNER_TEMP/streamctl-upgrade.raw"
|
|
113
|
+
|
|
114
|
+
- name: Fail on an unexpected upgrade result
|
|
115
|
+
if: ${{ steps.upgrade.outputs.code != '' && steps.upgrade.outputs.code != '0' && steps.upgrade.outputs.code != '2' }}
|
|
116
|
+
run: exit 1
|
|
84
117
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- name: Prepare a plan-only bump (interactive sync required)
|
|
118
|
+
- id: conflicts
|
|
119
|
+
name: Classify upgrade conflicts
|
|
88
120
|
if: ${{ steps.upgrade.outputs.code == '2' }}
|
|
89
|
-
run:
|
|
121
|
+
run: |
|
|
122
|
+
jq -r --slurpfile status "$RUNNER_TEMP/streamctl-status.json" '
|
|
123
|
+
(.error.details.conflicted // [])[]
|
|
124
|
+
| select((
|
|
125
|
+
(.kind == "edit" or .kind == "adoption")
|
|
126
|
+
and (.path as $path | any($status[0].data.files[];
|
|
127
|
+
.path == $path and .strategy == "full" and .state == "in-sync"
|
|
128
|
+
))
|
|
129
|
+
) | not)
|
|
130
|
+
| .path
|
|
131
|
+
' "$RUNNER_TEMP/streamctl-upgrade.json" | sort -u > "$RUNNER_TEMP/streamctl-unsafe.txt"
|
|
132
|
+
if [[ ! -s "$RUNNER_TEMP/streamctl-unsafe.txt" ]] && jq -e '
|
|
133
|
+
.error.code == "CONFLICTS_PENDING"
|
|
134
|
+
and .error.details.rolledBack == true
|
|
135
|
+
and (.error.details.conflicted | length > 0)
|
|
136
|
+
' "$RUNNER_TEMP/streamctl-upgrade.json" > /dev/null; then
|
|
137
|
+
echo "safe=true" >> "$GITHUB_OUTPUT"
|
|
138
|
+
else
|
|
139
|
+
echo "safe=false" >> "$GITHUB_OUTPUT"
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
- id: force
|
|
143
|
+
name: Apply safe generated replacements
|
|
144
|
+
if: ${{ steps.conflicts.outputs.safe == 'true' }}
|
|
145
|
+
env:
|
|
146
|
+
CI: "false"
|
|
147
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
148
|
+
run: |
|
|
149
|
+
set +e
|
|
150
|
+
pnpm streamctl upgrade --to "$TARGET" --force --json > "$RUNNER_TEMP/streamctl-force.raw"
|
|
151
|
+
code=$?
|
|
152
|
+
set -e
|
|
153
|
+
tail -n 1 "$RUNNER_TEMP/streamctl-force.raw" > "$RUNNER_TEMP/streamctl-force.json"
|
|
154
|
+
echo "code=$code" >> "$GITHUB_OUTPUT"
|
|
155
|
+
cat "$RUNNER_TEMP/streamctl-force.raw"
|
|
156
|
+
|
|
157
|
+
- name: Fail when safe replacement fails
|
|
158
|
+
if: ${{ steps.conflicts.outputs.safe == 'true' && steps.force.outputs.code != '0' }}
|
|
159
|
+
run: exit 1
|
|
160
|
+
|
|
161
|
+
- id: outcome
|
|
162
|
+
name: Record the upgrade outcome
|
|
163
|
+
if: ${{ steps.check.outputs.code == '4' }}
|
|
164
|
+
env:
|
|
165
|
+
FORCE_CODE: ${{ steps.force.outputs.code }}
|
|
166
|
+
UPGRADE_CODE: ${{ steps.upgrade.outputs.code }}
|
|
167
|
+
run: |
|
|
168
|
+
if [[ "$UPGRADE_CODE" == "0" || "$FORCE_CODE" == "0" ]]; then
|
|
169
|
+
echo "completed=true" >> "$GITHUB_OUTPUT"
|
|
170
|
+
else
|
|
171
|
+
echo "completed=false" >> "$GITHUB_OUTPUT"
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
- id: workflow_changes
|
|
175
|
+
name: Exclude workflow changes by default
|
|
176
|
+
if: ${{ steps.outcome.outputs.completed == 'true' }}
|
|
177
|
+
run: |
|
|
178
|
+
jq -r '
|
|
179
|
+
(.data.plan // .error.details.plan // [])[]
|
|
180
|
+
| .path
|
|
181
|
+
| select(startswith(".github/workflows/"))
|
|
182
|
+
' "$RUNNER_TEMP/streamctl-upgrade.json" | sort -u > "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
183
|
+
echo "blocked=false" >> "$GITHUB_OUTPUT"
|
|
184
|
+
if [[ "$ALLOW_WORKFLOW_UPDATES" == "true" || ! -s "$RUNNER_TEMP/streamctl-workflows.txt" ]]; then
|
|
185
|
+
exit 0
|
|
186
|
+
fi
|
|
187
|
+
while IFS= read -r path; do
|
|
188
|
+
if git cat-file -e "HEAD:$path" 2>/dev/null; then
|
|
189
|
+
git restore --source=HEAD --worktree -- "$path"
|
|
190
|
+
else
|
|
191
|
+
rm -f -- "$path"
|
|
192
|
+
fi
|
|
193
|
+
done < "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
194
|
+
echo "blocked=true" >> "$GITHUB_OUTPUT"
|
|
195
|
+
|
|
196
|
+
- id: manual
|
|
197
|
+
name: Prepare the manual upgrade
|
|
198
|
+
if: ${{ steps.upgrade.outputs.code == '2' && steps.conflicts.outputs.safe == 'false' }}
|
|
199
|
+
env:
|
|
200
|
+
CI: "false"
|
|
201
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
202
|
+
run: |
|
|
203
|
+
set +e
|
|
204
|
+
pnpm streamctl upgrade --to "$TARGET" --force --json
|
|
205
|
+
code=$?
|
|
206
|
+
set -e
|
|
207
|
+
# Faults and malformed files cannot be forced; fall back to the pin bump.
|
|
208
|
+
if [[ "$code" != "0" ]]; then
|
|
209
|
+
pnpm streamctl upgrade --to "$TARGET" --no-install --json
|
|
210
|
+
pnpm install --lockfile-only --ignore-scripts
|
|
211
|
+
echo "applied=false" >> "$GITHUB_OUTPUT"
|
|
212
|
+
exit 0
|
|
213
|
+
fi
|
|
214
|
+
: > "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
215
|
+
if [[ "$ALLOW_WORKFLOW_UPDATES" != "true" ]]; then
|
|
216
|
+
jq -r '
|
|
217
|
+
(.data.plan // .error.details.plan // [])[]
|
|
218
|
+
| .path
|
|
219
|
+
| select(startswith(".github/workflows/"))
|
|
220
|
+
' "$RUNNER_TEMP/streamctl-upgrade.json" | sort -u > "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
221
|
+
fi
|
|
222
|
+
sort -u "$RUNNER_TEMP/streamctl-unsafe.txt" "$RUNNER_TEMP/streamctl-workflows.txt" > "$RUNNER_TEMP/streamctl-held.txt"
|
|
223
|
+
while IFS= read -r path; do
|
|
224
|
+
if git cat-file -e "HEAD:$path" 2>/dev/null; then
|
|
225
|
+
git restore --source=HEAD --worktree -- "$path"
|
|
226
|
+
else
|
|
227
|
+
rm -f -- "$path"
|
|
228
|
+
fi
|
|
229
|
+
done < "$RUNNER_TEMP/streamctl-held.txt"
|
|
230
|
+
echo "applied=true" >> "$GITHUB_OUTPUT"
|
|
231
|
+
|
|
232
|
+
- name: Install apt packages
|
|
233
|
+
if: ${{ steps.outcome.outputs.completed == 'true' && env.CI_APT_PACKAGES != '' }}
|
|
234
|
+
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends $CI_APT_PACKAGES
|
|
90
235
|
|
|
91
|
-
- name:
|
|
92
|
-
if: ${{ steps.
|
|
93
|
-
|
|
236
|
+
- name: Prepare the validation
|
|
237
|
+
if: ${{ steps.outcome.outputs.completed == 'true' && env.PREPARE_COMMAND != '' }}
|
|
238
|
+
run: eval "$PREPARE_COMMAND"
|
|
239
|
+
|
|
240
|
+
- name: Validate the completed upgrade
|
|
241
|
+
if: ${{ steps.outcome.outputs.completed == 'true' && steps.workflow_changes.outputs.blocked == 'false' }}
|
|
242
|
+
run: |
|
|
243
|
+
pnpm streamctl check
|
|
244
|
+
pnpm run --if-present lint
|
|
245
|
+
pnpm run --if-present typecheck
|
|
246
|
+
pnpm run --if-present test
|
|
247
|
+
pnpm run --if-present build
|
|
248
|
+
|
|
249
|
+
- name: Validate the partial upgrade
|
|
250
|
+
if: ${{ steps.workflow_changes.outputs.blocked == 'true' }}
|
|
251
|
+
run: |
|
|
252
|
+
set +e
|
|
253
|
+
pnpm streamctl check --fail-on drift --json > "$RUNNER_TEMP/streamctl-partial-check.raw"
|
|
254
|
+
code=$?
|
|
255
|
+
set -e
|
|
256
|
+
tail -n 1 "$RUNNER_TEMP/streamctl-partial-check.raw" > "$RUNNER_TEMP/streamctl-partial-check.json"
|
|
257
|
+
test "$code" -eq 3
|
|
258
|
+
jq -Rsc 'split("\n") | map(select(length > 0)) | sort' \
|
|
259
|
+
"$RUNNER_TEMP/streamctl-workflows.txt" > "$RUNNER_TEMP/streamctl-workflows.json"
|
|
260
|
+
jq -e --slurpfile expected "$RUNNER_TEMP/streamctl-workflows.json" '
|
|
261
|
+
.error.code == "DRIFT_DETECTED"
|
|
262
|
+
and (.error.details.structuralFaults | length == 0)
|
|
263
|
+
and (.error.details.versionSkew | length == 0)
|
|
264
|
+
and (([.error.details.drift[].path] | sort) == $expected[0])
|
|
265
|
+
' "$RUNNER_TEMP/streamctl-partial-check.json" > /dev/null
|
|
266
|
+
pnpm run --if-present lint
|
|
267
|
+
pnpm run --if-present typecheck
|
|
268
|
+
pnpm run --if-present test
|
|
269
|
+
pnpm run --if-present build
|
|
270
|
+
|
|
271
|
+
- name: Prepare the completed-upgrade description
|
|
272
|
+
if: ${{ steps.outcome.outputs.completed == 'true' && steps.workflow_changes.outputs.blocked == 'false' }}
|
|
273
|
+
env:
|
|
274
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
275
|
+
run: |
|
|
276
|
+
from=$(jq -r '.data.payload.pinned' "$RUNNER_TEMP/streamctl-status.json")
|
|
277
|
+
{
|
|
278
|
+
echo "## Summary"
|
|
279
|
+
echo
|
|
280
|
+
printf -- '- Updated the streamctl payload from `%s` to `%s`.\n' "$from" "$TARGET"
|
|
281
|
+
echo "- Reconciled all managed files."
|
|
282
|
+
echo "- Updated dependencies and the lockfile."
|
|
283
|
+
echo
|
|
284
|
+
echo "## Validation"
|
|
285
|
+
echo
|
|
286
|
+
echo '- `pnpm streamctl check`'
|
|
287
|
+
echo "- Available lint, typecheck, test, and build scripts"
|
|
288
|
+
} > "$RUNNER_TEMP/streamctl-pr.md"
|
|
289
|
+
|
|
290
|
+
- name: Open the completed upgrade PR
|
|
291
|
+
if: ${{ steps.outcome.outputs.completed == 'true' && steps.workflow_changes.outputs.blocked == 'false' }}
|
|
292
|
+
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
|
|
94
293
|
with:
|
|
95
|
-
token: ${{ secrets.
|
|
96
|
-
branch: chore/streamctl-upgrade
|
|
97
|
-
commit-message: "chore: upgrade
|
|
98
|
-
title: "chore: upgrade
|
|
99
|
-
body:
|
|
100
|
-
Automated payload upgrade: the managed files were reconciled cleanly by
|
|
101
|
-
`streamctl upgrade`. Review the diff; `streamctl-upgrade.json` (in the run
|
|
102
|
-
logs) has the full sync summary and dependency bumps.
|
|
294
|
+
token: ${{ env.ALLOW_WORKFLOW_UPDATES == 'true' && secrets.${PR_TOKEN_SECRET} || github.token }}
|
|
295
|
+
branch: chore/streamctl-upgrade-${{ steps.check.outputs.target }}
|
|
296
|
+
commit-message: "chore: upgrade streamctl payload to ${{ steps.check.outputs.target }}"
|
|
297
|
+
title: "chore: upgrade streamctl payload to ${{ steps.check.outputs.target }}"
|
|
298
|
+
body-path: ${{ runner.temp }}/streamctl-pr.md
|
|
103
299
|
labels: streamctl
|
|
104
300
|
|
|
105
|
-
- name:
|
|
106
|
-
if: ${{ steps.
|
|
107
|
-
|
|
301
|
+
- name: Prepare the resolve instructions
|
|
302
|
+
if: ${{ steps.workflow_changes.outputs.blocked == 'true' || steps.manual.outputs.applied != '' }}
|
|
303
|
+
env:
|
|
304
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
305
|
+
run: |
|
|
306
|
+
branch="chore/streamctl-upgrade-$TARGET"
|
|
307
|
+
{
|
|
308
|
+
echo "## Resolve"
|
|
309
|
+
echo
|
|
310
|
+
echo '```sh'
|
|
311
|
+
printf 'git fetch origin %s\n' "$branch"
|
|
312
|
+
printf 'git switch --create %s --track origin/%s\n' "$branch" "$branch"
|
|
313
|
+
echo 'pnpm install --frozen-lockfile'
|
|
314
|
+
echo 'pnpm streamctl sync --interactive'
|
|
315
|
+
echo 'pnpm streamctl check'
|
|
316
|
+
echo 'pnpm run --if-present lint'
|
|
317
|
+
echo 'pnpm run --if-present typecheck'
|
|
318
|
+
echo 'pnpm run --if-present test'
|
|
319
|
+
echo 'pnpm run --if-present build'
|
|
320
|
+
echo 'git add .'
|
|
321
|
+
echo 'git commit -m "chore: finish streamctl upgrade"'
|
|
322
|
+
echo 'git push'
|
|
323
|
+
echo '```'
|
|
324
|
+
} > "$RUNNER_TEMP/streamctl-resolve.md"
|
|
325
|
+
|
|
326
|
+
- name: Prepare the workflow-update description
|
|
327
|
+
if: ${{ steps.workflow_changes.outputs.blocked == 'true' }}
|
|
328
|
+
env:
|
|
329
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
330
|
+
run: |
|
|
331
|
+
from=$(jq -r '.data.payload.pinned' "$RUNNER_TEMP/streamctl-status.json")
|
|
332
|
+
{
|
|
333
|
+
echo "## Status"
|
|
334
|
+
echo
|
|
335
|
+
echo "This update omits GitHub Actions workflow changes. Do not merge this pull request yet."
|
|
336
|
+
echo
|
|
337
|
+
printf -- '- Updated the streamctl payload from `%s` to `%s`.\n' "$from" "$TARGET"
|
|
338
|
+
echo "- Applied every other safe managed-file change."
|
|
339
|
+
echo "- Updated dependencies and the lockfile."
|
|
340
|
+
echo
|
|
341
|
+
echo "## Omitted workflow files"
|
|
342
|
+
echo
|
|
343
|
+
sed 's|^|- `|; s|$|`|' "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
344
|
+
echo
|
|
345
|
+
cat "$RUNNER_TEMP/streamctl-resolve.md"
|
|
346
|
+
} > "$RUNNER_TEMP/streamctl-workflow-pr.md"
|
|
347
|
+
|
|
348
|
+
- name: Open the workflow-update PR
|
|
349
|
+
if: ${{ steps.workflow_changes.outputs.blocked == 'true' }}
|
|
350
|
+
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
|
|
351
|
+
with:
|
|
352
|
+
token: ${{ env.ALLOW_WORKFLOW_UPDATES == 'true' && secrets.${PR_TOKEN_SECRET} || github.token }}
|
|
353
|
+
branch: chore/streamctl-upgrade-${{ steps.check.outputs.target }}
|
|
354
|
+
commit-message: "chore: prepare streamctl payload ${{ steps.check.outputs.target }}"
|
|
355
|
+
title: "chore: upgrade streamctl payload to ${{ steps.check.outputs.target }}"
|
|
356
|
+
body-path: ${{ runner.temp }}/streamctl-workflow-pr.md
|
|
357
|
+
draft: true
|
|
358
|
+
labels: |
|
|
359
|
+
streamctl
|
|
360
|
+
needs-interactive-upgrade
|
|
361
|
+
|
|
362
|
+
- name: Prepare the manual-upgrade description
|
|
363
|
+
if: ${{ steps.upgrade.outputs.code == '2' && steps.conflicts.outputs.safe == 'false' }}
|
|
364
|
+
env:
|
|
365
|
+
APPLIED: ${{ steps.manual.outputs.applied }}
|
|
366
|
+
TARGET: ${{ steps.check.outputs.target }}
|
|
367
|
+
run: |
|
|
368
|
+
from=$(jq -r '.data.payload.pinned' "$RUNNER_TEMP/streamctl-status.json")
|
|
369
|
+
{
|
|
370
|
+
echo "## Status"
|
|
371
|
+
echo
|
|
372
|
+
echo "This update needs manual conflict resolution. Do not merge this pull request yet."
|
|
373
|
+
echo
|
|
374
|
+
printf -- '- Updated the streamctl payload from `%s` to `%s`.\n' "$from" "$TARGET"
|
|
375
|
+
if [[ "$APPLIED" == "true" ]]; then
|
|
376
|
+
echo "- Applied every safe managed-file change."
|
|
377
|
+
echo "- Left conflicting managed files unchanged."
|
|
378
|
+
else
|
|
379
|
+
echo "- Did not update managed files because \`streamctl upgrade --force\` failed. See the workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
380
|
+
fi
|
|
381
|
+
echo "- Updated dependencies and the lockfile."
|
|
382
|
+
echo
|
|
383
|
+
echo "## Conflicts"
|
|
384
|
+
echo
|
|
385
|
+
jq -r --arg applied "$APPLIED" --rawfile unsafe "$RUNNER_TEMP/streamctl-unsafe.txt" '
|
|
386
|
+
($unsafe | split("\n")) as $held
|
|
387
|
+
| .error.details.conflicted[]
|
|
388
|
+
| select($applied != "true" or (.path | IN($held[])))
|
|
389
|
+
| "- `\(.path)` (`\(.kind)`): \(.reason)"
|
|
390
|
+
' "$RUNNER_TEMP/streamctl-upgrade.json"
|
|
391
|
+
echo
|
|
392
|
+
if [[ -s "$RUNNER_TEMP/streamctl-workflows.txt" ]]; then
|
|
393
|
+
echo "## Omitted workflow files"
|
|
394
|
+
echo
|
|
395
|
+
sed 's|^|- `|; s|$|`|' "$RUNNER_TEMP/streamctl-workflows.txt"
|
|
396
|
+
echo
|
|
397
|
+
fi
|
|
398
|
+
cat "$RUNNER_TEMP/streamctl-resolve.md"
|
|
399
|
+
} > "$RUNNER_TEMP/streamctl-conflict-pr.md"
|
|
400
|
+
|
|
401
|
+
- name: Open the manual upgrade PR
|
|
402
|
+
if: ${{ steps.upgrade.outputs.code == '2' && steps.conflicts.outputs.safe == 'false' }}
|
|
403
|
+
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
|
|
108
404
|
with:
|
|
109
|
-
token: ${{ secrets.
|
|
110
|
-
branch: chore/streamctl-upgrade
|
|
111
|
-
commit-message: "chore:
|
|
112
|
-
title: "chore: streamctl payload
|
|
113
|
-
body:
|
|
114
|
-
|
|
115
|
-
only the payload pin + devDependency were bumped here. Finish the upgrade by
|
|
116
|
-
hand: check out this branch, run `pnpm streamctl sync --interactive`, resolve
|
|
117
|
-
each conflict, and push.
|
|
405
|
+
token: ${{ env.ALLOW_WORKFLOW_UPDATES == 'true' && secrets.${PR_TOKEN_SECRET} || github.token }}
|
|
406
|
+
branch: chore/streamctl-upgrade-${{ steps.check.outputs.target }}
|
|
407
|
+
commit-message: "chore: prepare streamctl payload ${{ steps.check.outputs.target }}"
|
|
408
|
+
title: "chore: upgrade streamctl payload to ${{ steps.check.outputs.target }}"
|
|
409
|
+
body-path: ${{ runner.temp }}/streamctl-conflict-pr.md
|
|
410
|
+
draft: true
|
|
118
411
|
labels: |
|
|
119
412
|
streamctl
|
|
120
413
|
needs-interactive-upgrade
|
package/presets/base/gitignore
CHANGED
package/presets/base/preset.json
CHANGED
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
{ "path": ".vscode/settings.json", "strategy": "merge", "source": "base/vscode/settings.json", "render": "editor", "projectFields": ["editor.fontSize", "editor.rulers", "editor.formatOnSave", "files.exclude", "search.exclude", "files.watcherExclude"] },
|
|
11
11
|
{ "path": ".vscode/extensions.json", "strategy": "merge", "source": "base/vscode/extensions.json", "projectFields": ["unwantedRecommendations"] },
|
|
12
12
|
{ "path": "AGENTS.md", "strategy": "full", "source": "base/AGENTS.md", "adoption": "expected" },
|
|
13
|
-
{ "path": "CLAUDE.md", "strategy": "scaffold", "source": "base/CLAUDE.md", "adoption": "expected" },
|
|
14
13
|
{ "path": ".github/workflows/streamctl-upgrade.yml", "strategy": "full", "source": "base/github/workflows/streamctl-upgrade.yml", "render": "automation-upgrade", "enabledBy": "automation.upgradePr", "adoption": "unexpected" }
|
|
15
14
|
],
|
|
16
15
|
"renders": {
|
|
17
16
|
"automation-upgrade": {
|
|
18
17
|
"placeholders": {
|
|
19
|
-
"
|
|
18
|
+
"ALLOW_WORKFLOW_UPDATES": { "configPath": "automation.allowWorkflowUpdates", "default": "false", "pattern": "^(?:true|false)$" },
|
|
19
|
+
"CI_APT_PACKAGES": { "configPath": "ci.aptPackages", "default": "", "pattern": "^$|^[a-z0-9][a-z0-9 +.-]*$", "join": "space" },
|
|
20
|
+
"NODE_VERSION": { "configPath": "versions.node", "default": "24.21.0", "pattern": "^[\\w.+-]+$" },
|
|
21
|
+
"PR_TOKEN_SECRET": { "configPath": "automation.prTokenSecret", "default": "STREAMCTL_PR_TOKEN", "pattern": "^(?![Gg][Ii][Tt][Hh][Uu][Bb]_)[A-Za-z_][A-Za-z0-9_]*$" },
|
|
22
|
+
"PREPARE_COMMAND": { "configPath": "automation.prepare", "default": "pnpm prisma generate", "pattern": "^[^\\r\\n]*$" }
|
|
20
23
|
}
|
|
21
24
|
},
|
|
22
25
|
"editor": {
|
|
@@ -34,7 +37,11 @@
|
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
"configKeys": {
|
|
40
|
+
"automation.allowWorkflowUpdates": "boolean",
|
|
41
|
+
"automation.prTokenSecret": "string",
|
|
42
|
+
"automation.prepare": "string",
|
|
37
43
|
"automation.upgradePr": "boolean",
|
|
44
|
+
"ci.aptPackages": "string[]",
|
|
38
45
|
"editor.i18nSourceLanguage": "string",
|
|
39
46
|
"security.minimumReleaseAge": "string",
|
|
40
47
|
"pnpm.onlyBuiltDependencies": "string[]",
|
|
@@ -10,10 +10,9 @@ export default defineNuxtBaseConfig({
|
|
|
10
10
|
|
|
11
11
|
// Optional knobs, uncomment to enable:
|
|
12
12
|
// ci: { unitTests: true, e2e: true, aptPackages: ['libxml2-utils'] }, // apt extras for the test/e2e jobs
|
|
13
|
-
// versions: { node: '24.
|
|
13
|
+
// versions: { node: '24.21.0', pnpm: '10.34.5' },
|
|
14
14
|
// docker: { aptPackages: ['ffmpeg'] }, // extras; openssl is always installed
|
|
15
15
|
// security: { minimumReleaseAge: '10080' }, // minutes before pnpm installs a release; '0' disables
|
|
16
|
-
// pnpm: { onlyBuiltDependencies: ['sharp'] }, // extras on top of prisma + esbuild
|
|
16
|
+
// pnpm: { onlyBuiltDependencies: ['sharp'] }, // extras on top of the prisma packages + esbuild
|
|
17
17
|
// editor: { i18nSourceLanguage: 'en' }, // i18n-ally source language (default: 'de')
|
|
18
|
-
// eslint: { trpcGuard: true },
|
|
19
18
|
})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# check=skip=JSONArgsRecommended
|
|
1
2
|
# see https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact
|
|
2
3
|
ARG NODE_VERSION=node:${NODE_VERSION}
|
|
3
4
|
ARG PNPM_VERSION=${PNPM_VERSION}
|
|
@@ -55,4 +56,4 @@ ${DOCKER_FINAL_STAGE}
|
|
|
55
56
|
# Set docker.finalStage to "USER node" to opt back in.
|
|
56
57
|
|
|
57
58
|
# start the app
|
|
58
|
-
CMD
|
|
59
|
+
CMD ${DOCKER_START_COMMAND}
|
|
@@ -26,15 +26,15 @@ jobs:
|
|
|
26
26
|
lint-typecheck:
|
|
27
27
|
runs-on: ubuntu-latest
|
|
28
28
|
steps:
|
|
29
|
-
- uses: actions/checkout@
|
|
29
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
30
30
|
|
|
31
31
|
- name: Set up pnpm
|
|
32
|
-
uses: pnpm/action-setup@
|
|
32
|
+
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
33
33
|
with:
|
|
34
34
|
run_install: false
|
|
35
35
|
|
|
36
36
|
- name: Use Node.js ${{ env.NODE_VERSION }}
|
|
37
|
-
uses: actions/setup-node@
|
|
37
|
+
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
|
|
38
38
|
with:
|
|
39
39
|
node-version: ${{ env.NODE_VERSION }}
|
|
40
40
|
cache: pnpm
|
|
@@ -51,15 +51,15 @@ jobs:
|
|
|
51
51
|
needs: lint-typecheck
|
|
52
52
|
runs-on: ubuntu-latest
|
|
53
53
|
steps:
|
|
54
|
-
- uses: actions/checkout@
|
|
54
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
55
55
|
|
|
56
56
|
- name: Set up pnpm
|
|
57
|
-
uses: pnpm/action-setup@
|
|
57
|
+
uses: pnpm/action-setup@ea17c68df8912ef543352723c149a84f56e3d413 # v6.1.0
|
|
58
58
|
with:
|
|
59
59
|
run_install: false
|
|
60
60
|
|
|
61
61
|
- name: Use Node.js ${{ env.NODE_VERSION }}
|
|
62
|
-
uses: actions/setup-node@
|
|
62
|
+
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
|
|
63
63
|
with:
|
|
64
64
|
node-version: ${{ env.NODE_VERSION }}
|
|
65
65
|
cache: pnpm
|