@starci/hfs 4.12.0 → 4.13.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/CHANGELOG.md +43 -0
- package/README.md +8 -9
- package/cache/app-families.d.mts +30 -0
- package/cache/app-families.mjs +94 -0
- package/cache/content-index.d.mts +13 -0
- package/cache/content-index.mjs +37 -0
- package/cache/db-family.d.mts +13 -0
- package/cache/db-family.mjs +37 -0
- package/cache/fake-session.d.mts +42 -0
- package/cache/fake-session.mjs +57 -0
- package/cache/fingerprint.d.mts +28 -0
- package/cache/fingerprint.mjs +120 -0
- package/cache/format-family.d.mts +13 -0
- package/cache/format-family.mjs +49 -0
- package/cache/git.d.mts +11 -0
- package/cache/git.mjs +13 -0
- package/cache/hash.d.mts +15 -0
- package/cache/hash.mjs +58 -0
- package/cache/hfs-family.d.mts +35 -0
- package/cache/hfs-family.mjs +164 -0
- package/cache/import-graph.d.mts +75 -0
- package/cache/import-graph.mjs +204 -0
- package/cache/jsonl.d.mts +31 -0
- package/cache/jsonl.mjs +115 -0
- package/cache/lint-family.d.mts +162 -0
- package/cache/lint-family.mjs +433 -0
- package/cache/order.d.mts +1 -0
- package/cache/order.mjs +2 -0
- package/cache/progress.d.mts +19 -0
- package/cache/progress.mjs +68 -0
- package/cache/quality-baselines.d.mts +109 -0
- package/cache/quality-baselines.mjs +235 -0
- package/cache/records.d.mts +33 -0
- package/cache/records.mjs +54 -0
- package/cache/report.d.mts +19 -0
- package/cache/report.mjs +32 -0
- package/cache/run-log.d.mts +17 -0
- package/cache/run-log.mjs +37 -0
- package/cache/run.d.mts +33 -0
- package/cache/run.mjs +65 -0
- package/cache/session.d.mts +29 -0
- package/cache/session.mjs +197 -0
- package/cache/side-key.d.mts +10 -0
- package/cache/side-key.mjs +47 -0
- package/cache/test-family.d.mts +130 -0
- package/cache/test-family.mjs +258 -0
- package/cache/trust.d.mts +53 -0
- package/cache/trust.mjs +157 -0
- package/cache/types-family.d.mts +74 -0
- package/cache/types-family.mjs +154 -0
- package/cache/types.d.mts +99 -0
- package/cache/types.mjs +8 -0
- package/cache/wiring-family.d.mts +14 -0
- package/cache/wiring-family.mjs +43 -0
- package/coverage/cli.d.mts +4 -2
- package/coverage/cli.mjs +44 -5
- package/db/migrate.d.mts +16 -0
- package/db/migrate.mjs +21 -4
- package/db/postgres.d.mts +23 -0
- package/db/postgres.mjs +32 -1
- package/lint/run.d.mts +47 -1
- package/lint/run.mjs +157 -5
- package/package.json +2 -1
- package/release/gate.d.mts +2 -0
- package/release/gate.mjs +4 -2
- package/release/records.d.mts +15 -0
- package/release/records.mjs +25 -0
- package/release/urgent.mjs +23 -4
- package/runtime/knowledge/grammars/core/playbook.yaml +12 -18
- package/runtime/knowledge/hfs/canon-pins.yaml +8 -8
- package/runtime/knowledge/hfs/ci-standard.yaml +29 -6
- package/runtime/knowledge/hfs/rules.yaml +97 -7
- package/runtime/knowledge/hfs/slots.yaml +19 -7
- package/runtime/modules/kernel/failure-codes.yaml +46 -4
- package/runtime/modules/schemas/application-stacks.schema.yaml +26 -0
- package/runtime/scripts/hfs/architecture/hfs.d.mts +6 -6
- package/runtime/scripts/hfs/check.mjs +1 -1
- package/runtime/scripts/hfs/gate-threshold.mjs +2 -1
- package/runtime/scripts/hfs/rules/boot-proof.d.mts +5 -0
- package/runtime/scripts/hfs/rules/boot-proof.mjs +15 -1
- package/runtime/scripts/hfs/rules/ci-custody.mjs +3 -1
- package/runtime/scripts/hfs/rules/ci-standard.mjs +32 -3
- package/runtime/scripts/hfs/rules/database-migrations.d.mts +14 -0
- package/runtime/scripts/hfs/rules/database-migrations.mjs +55 -0
- package/runtime/scripts/hfs/rules/database.mjs +2 -1
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +53 -6
- package/runtime/scripts/hfs/rules/release-provenance.mjs +32 -4
- package/runtime/scripts/hfs/rules/stacks.mjs +5 -1
- package/runtime/scripts/hfs/rules/supply-chain.mjs +4 -1
- package/runtime/scripts/hfs/rules/unused-symbol-translators.mjs +98 -7
- package/runtime/scripts/hfs/rules/unused-symbol.d.mts +9 -2
- package/runtime/scripts/hfs/rules/unused-symbol.mjs +15 -2
- package/runtime/scripts/hfs/runtime-rules/git-triggers.mjs +21 -5
- package/runtime/scripts/hfs/stack-deploy-config.d.mts +6 -0
- package/runtime/scripts/hfs/stack-deploy-config.mjs +32 -1
- package/runtime/scripts/hfs/stacks-gate.mjs +2 -0
- package/runtime/scripts/hfs/tree-findings.mjs +3 -1
- package/scaffold/add-inbox-lite.mjs +2 -4
- package/scaffold/add-queue-lite.mjs +2 -3
- package/scaffold/add-table.mjs +2 -4
- package/scaffold/migration-stamp.d.mts +11 -0
- package/scaffold/migration-stamp.mjs +32 -0
- package/src/helpers/hfs-arch-fixture.d.mts +1 -1
- package/src/main.d.mts +4 -1
- package/src/main.mjs +189 -74
- package/src/stack-records-double.d.mts +31 -0
- package/stack/cli.d.mts +3 -1
- package/stack/cli.mjs +17 -11
- package/stack/config.d.mts +6 -0
- package/stack/converge.d.mts +2 -0
- package/stack/converge.mjs +1 -1
- package/stack/db-phases.d.mts +185 -0
- package/stack/db-phases.mjs +346 -0
- package/stack/deploy.d.mts +18 -4
- package/stack/deploy.mjs +235 -70
- package/stack/journal.d.mts +127 -0
- package/stack/journal.mjs +182 -0
- package/stack/manager-backup.d.mts +54 -0
- package/stack/manager-backup.mjs +136 -0
- package/stack/release-store.d.mts +44 -0
- package/stack/release-store.mjs +89 -6
- package/stack/remote.d.mts +2 -0
- package/stack/remote.mjs +31 -11
- package/stack/server-key.d.mts +2 -0
- package/stack/server-key.mjs +1 -1
- package/stack/status.d.mts +49 -0
- package/stack/status.mjs +114 -0
- package/stack/urgent-floor.d.mts +10 -61
- package/stack/urgent-floor.mjs +28 -123
- package/stack/verify.mjs +26 -0
- package/sync/ci-commands.mjs +10 -5
- package/sync/format-worker.d.mts +1 -0
- package/sync/format-worker.mjs +17 -0
- package/sync/format.d.mts +21 -3
- package/sync/format.mjs +99 -7
- package/sync/index.d.mts +3 -6
- package/sync/index.mjs +12 -12
- package/sync/stack-images.d.mts +25 -10
- package/sync/stack-images.mjs +215 -54
- package/templates/app/ci-workflows/github/workflows/ci.yml +114 -7
- package/templates/app/ci-workflows/github/workflows/images.yml +21 -65
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +130 -37
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +114 -7
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +21 -65
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +130 -37
- package/templates/app/gitignore +1 -0
- package/templates/app/gitignore-lite +1 -0
- package/templates/app/package-scripts/db.json +1 -1
- package/templates/app/skeleton/.gitattributes +2 -0
- package/templates/app/skeleton-lite/.gitattributes +2 -0
- package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +2 -1
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +0 -63
|
@@ -1,33 +1,70 @@
|
|
|
1
1
|
{{header}}
|
|
2
|
-
# Deploys the app's Docker Swarm stack. This file only assembles arguments: the logic lives in the verbs connect,
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
2
|
+
# Deploys the app's Docker Swarm stack. This file only assembles arguments: the logic lives in the verbs connect, deploy, rollback and disconnect
|
|
3
|
+
# of "starci app stack". It has two callers:
|
|
4
|
+
# ci.yml calls it (workflow_call) once per environment with deploy.auto, after the verdict job, with the digests of the images that run
|
|
5
|
+
# pushed and the CI run that proves the commit. A green release tag deploys by itself.
|
|
6
|
+
# by hand Actions > deploy stack > Run workflow, from a release tag v* whose version is the package.json version.
|
|
7
|
+
# operation deploy deploys the release of the tag: the immutable digests of its images (the run's, or the registry's sha-<sha> tags when
|
|
8
|
+
# dispatched), the CI evidence of the commit, then render, store, pre-pull, migrate (expand), converge, post-deploy, verify, accept
|
|
9
|
+
# and the contract migrations; a failure redeploys the previous accepted release
|
|
10
|
+
# operation redeploy the same, although the accepted release already runs this commit
|
|
7
11
|
# operation rollback redeploys a stored release; "release" is 16 lowercase hex characters, empty means the previous accepted release
|
|
8
|
-
# The environment
|
|
9
|
-
# vars
|
|
12
|
+
# The environment names a GitHub environment whose deployment refs are restricted to the tags v* and that holds:
|
|
13
|
+
# vars STARCI_DEPLOY_PAUSED (true stops the automatic deploy of that environment without a code change; a manual run still works), and a
|
|
14
|
+
# variable named in deploy.passEnv when the stack interpolates one
|
|
10
15
|
# secrets SOPS_AGE_KEY (that environment's server identity, stored there by starci app secret server-key --env <env> --backup github --execute;
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
16
|
+
# the jobs are bound to the environment, so they read it and never a repository secret of that name)
|
|
17
|
+
# The transport is sealed: the CI deploy key, the pinned host keys and the host are the member vps-ci under .starcistacks/<env>/secrets, opened with
|
|
18
|
+
# the server identity (a key of its own, never the owner's, authorised on the manager with a forced command). Nothing else is a secret: the images
|
|
19
|
+
# are read with the workflow token. Inputs reach scripts only through env. The log of a public repository is public: no step prints a host or a path.
|
|
15
20
|
name: deploy stack
|
|
16
21
|
|
|
17
22
|
on:
|
|
23
|
+
workflow_call:
|
|
24
|
+
inputs:
|
|
25
|
+
environment:
|
|
26
|
+
description: GitHub environment holding the server identity and the sealed custody under .starcistacks
|
|
27
|
+
required: true
|
|
28
|
+
type: string
|
|
29
|
+
operation:
|
|
30
|
+
description: deploy, redeploy or rollback
|
|
31
|
+
required: false
|
|
32
|
+
type: string
|
|
33
|
+
default: deploy
|
|
34
|
+
release:
|
|
35
|
+
description: "Rollback only: release id (16 lowercase hex) to deploy again; empty means the previous accepted release"
|
|
36
|
+
required: false
|
|
37
|
+
type: string
|
|
38
|
+
default: ""
|
|
39
|
+
images:
|
|
40
|
+
description: "JSON object, service -> repository@sha256:digest of the images the calling run pushed; empty reads the registry's sha-<sha> tags"
|
|
41
|
+
required: false
|
|
42
|
+
type: string
|
|
43
|
+
default: ""
|
|
44
|
+
ci_run:
|
|
45
|
+
description: Id of the CI run that proves the commit; empty finds the green CI run of the commit
|
|
46
|
+
required: false
|
|
47
|
+
type: string
|
|
48
|
+
default: ""
|
|
49
|
+
auto:
|
|
50
|
+
description: The automatic deploy of a green release tag (it stops when STARCI_DEPLOY_PAUSED is true)
|
|
51
|
+
required: false
|
|
52
|
+
type: boolean
|
|
53
|
+
default: false
|
|
18
54
|
workflow_dispatch:
|
|
19
55
|
inputs:
|
|
20
56
|
environment:
|
|
21
|
-
description:
|
|
57
|
+
description: GitHub environment holding the server identity and the sealed custody under .starcistacks
|
|
22
58
|
required: true
|
|
23
59
|
type: environment
|
|
24
60
|
operation:
|
|
25
|
-
description: Deploy
|
|
61
|
+
description: Deploy the release of this tag, deploy it again, or roll back to a stored release
|
|
26
62
|
required: true
|
|
27
63
|
type: choice
|
|
28
64
|
default: deploy
|
|
29
65
|
options:
|
|
30
66
|
- deploy
|
|
67
|
+
- redeploy
|
|
31
68
|
- rollback
|
|
32
69
|
release:
|
|
33
70
|
description: "Rollback only: release id (16 lowercase hex) to deploy again; empty means the previous accepted release"
|
|
@@ -38,69 +75,125 @@ on:
|
|
|
38
75
|
permissions:
|
|
39
76
|
contents: read
|
|
40
77
|
|
|
41
|
-
concurrency:
|
|
42
|
-
group: stack-${{ inputs.environment }}
|
|
43
|
-
cancel-in-progress: false
|
|
44
|
-
|
|
45
78
|
jobs:
|
|
46
|
-
|
|
47
|
-
if: ${{ inputs.operation
|
|
79
|
+
deploy:
|
|
80
|
+
if: ${{ inputs.operation != 'rollback' }}
|
|
48
81
|
runs-on: ubuntu-latest
|
|
49
82
|
environment: ${{ inputs.environment }}
|
|
50
83
|
timeout-minutes: 60
|
|
51
84
|
permissions:
|
|
52
85
|
contents: read
|
|
53
|
-
packages:
|
|
86
|
+
packages: read
|
|
54
87
|
actions: read
|
|
88
|
+
concurrency:
|
|
89
|
+
group: stack-${{ inputs.environment }}
|
|
90
|
+
cancel-in-progress: false
|
|
55
91
|
env:
|
|
56
92
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
57
93
|
steps:{{stackGuard}}
|
|
58
94
|
- name: require release tag
|
|
59
95
|
shell: bash
|
|
60
96
|
run: '[[ "$GITHUB_REF" == refs/tags/v* ]] || exit 1'
|
|
97
|
+
- name: deploy pause
|
|
98
|
+
id: pause
|
|
99
|
+
shell: bash
|
|
100
|
+
env:
|
|
101
|
+
AUTO: ${{ inputs.auto }}
|
|
102
|
+
PAUSED: ${{ vars.STARCI_DEPLOY_PAUSED }}
|
|
103
|
+
run: |
|
|
104
|
+
if [[ "$AUTO" == true && "$PAUSED" == true ]]; then
|
|
105
|
+
echo "paused=true" >> "$GITHUB_OUTPUT"
|
|
106
|
+
echo "::notice::STARCI_DEPLOY_PAUSED is true for this environment: this release was not deployed"
|
|
107
|
+
echo "### Deploy paused" >> "$GITHUB_STEP_SUMMARY"
|
|
108
|
+
echo "STARCI_DEPLOY_PAUSED is true for this environment, so the automatic deploy was skipped. Run this workflow by hand to deploy the release." >> "$GITHUB_STEP_SUMMARY"
|
|
109
|
+
else
|
|
110
|
+
echo "paused=false" >> "$GITHUB_OUTPUT"
|
|
111
|
+
fi
|
|
61
112
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
113
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
62
114
|
- name: release tag matches package version
|
|
115
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
63
116
|
run: node -e "const version=require('./package.json').version;if(process.env.GITHUB_REF_NAME!=='v'+version)process.exit(1)"
|
|
64
117
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
118
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
65
119
|
with:
|
|
66
120
|
node-version: {{nodeMajor}}
|
|
67
121
|
cache: npm
|
|
68
122
|
- run: npm ci --ignore-scripts
|
|
123
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
69
124
|
- name: install SOPS
|
|
125
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
70
126
|
uses: mdgreenwald/mozilla-sops-action@bb2d96a13ef438ad122e5827a57ebd75d6ff118d # v2.1.0
|
|
71
127
|
with:
|
|
72
128
|
version: v3.13.2
|
|
73
|
-
- name: image repositories
|
|
74
|
-
id: names
|
|
75
|
-
shell: bash
|
|
76
|
-
run: |
|
|
77
|
-
owner="${GITHUB_REPOSITORY_OWNER,,}"{{stackNames}}
|
|
78
129
|
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
|
130
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
79
131
|
- uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
|
132
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
80
133
|
with:
|
|
81
134
|
registry: ghcr.io
|
|
82
135
|
username: ${{ github.actor }}
|
|
83
|
-
password: ${{ github.token }}
|
|
136
|
+
password: ${{ github.token }}
|
|
137
|
+
- name: image digests
|
|
138
|
+
id: images
|
|
139
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
140
|
+
shell: bash
|
|
141
|
+
env:
|
|
142
|
+
IMAGES: ${{ inputs.images }}
|
|
143
|
+
run: |
|
|
144
|
+
set -euo pipefail
|
|
145
|
+
owner="${GITHUB_REPOSITORY_OWNER,,}"
|
|
146
|
+
[[ -n "$IMAGES" ]] || IMAGES='{}'
|
|
147
|
+
while read -r service app; do
|
|
148
|
+
ref=$(jq -r --arg service "$service" '.[$service] // empty' <<<"$IMAGES")
|
|
149
|
+
if [[ -z "$ref" ]]; then
|
|
150
|
+
repo="ghcr.io/${owner}/{{project}}-${app}"
|
|
151
|
+
digest=$(docker buildx imagetools inspect "$repo:sha-$GITHUB_SHA" --format '{{json .Manifest}}' | jq -r .digest)
|
|
152
|
+
ref="${repo}@${digest}"
|
|
153
|
+
fi
|
|
154
|
+
[[ "$ref" =~ ^ghcr\.io/[a-z0-9._/-]+@sha256:[0-9a-f]{64}$ ]] || { echo "::error::no immutable image for ${service}"; exit 1; }
|
|
155
|
+
echo "${service}=${ref}" >> "$GITHUB_OUTPUT"
|
|
156
|
+
done <<'LIST'
|
|
157
|
+
{{stackImageList}}
|
|
158
|
+
LIST
|
|
159
|
+
- name: CI run of the commit
|
|
160
|
+
id: ci
|
|
161
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
162
|
+
shell: bash
|
|
163
|
+
env:
|
|
164
|
+
GH_TOKEN: ${{ github.token }}
|
|
165
|
+
CI_RUN: ${{ inputs.ci_run }}
|
|
166
|
+
run: |
|
|
167
|
+
set -euo pipefail
|
|
168
|
+
if [[ -z "$CI_RUN" ]]; then
|
|
169
|
+
CI_RUN=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/ci.yml/runs?head_sha=${GITHUB_SHA}&event=push&status=success&per_page=100" --jq '[.workflow_runs[].id] | first // empty')
|
|
170
|
+
fi
|
|
171
|
+
[[ "$CI_RUN" =~ ^[1-9][0-9]*$ ]] || { echo "::error::no green CI run of this commit: a release deploys only a commit the CI proved"; exit 1; }
|
|
172
|
+
echo "run=$CI_RUN" >> "$GITHUB_OUTPUT"
|
|
84
173
|
- name: connect to the swarm manager
|
|
174
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
85
175
|
env:
|
|
86
176
|
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
87
|
-
|
|
88
|
-
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
89
|
-
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
90
|
-
VPS_USER: ${{ vars.VPS_USER }}
|
|
177
|
+
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
91
178
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
92
179
|
- name: deploy the release
|
|
180
|
+
if: ${{ steps.pause.outputs.paused != 'true' }}
|
|
181
|
+
shell: bash
|
|
93
182
|
env:
|
|
94
183
|
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
95
184
|
GH_TOKEN: ${{ github.token }}
|
|
96
|
-
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
185
|
+
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
186
|
+
OPERATION: ${{ inputs.operation }}
|
|
187
|
+
CI_RUN: ${{ steps.ci.outputs.run }}{{stackImageEnv}}{{stackPassEnv}}
|
|
97
188
|
run: |
|
|
189
|
+
again=()
|
|
190
|
+
[[ "$OPERATION" != redeploy ]] || again=(--redeploy)
|
|
98
191
|
npx --no-install starci app stack deploy --env "$STACK_ENVIRONMENT" \{{stackImageArgs}}
|
|
99
|
-
--sha "$GITHUB_SHA" --execute
|
|
192
|
+
--sha "$GITHUB_SHA" --ci-run "$CI_RUN" "${again[@]}" --execute
|
|
100
193
|
- name: disconnect from the swarm manager
|
|
101
194
|
env:
|
|
102
195
|
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
103
|
-
if: ${{ always() }}
|
|
196
|
+
if: ${{ always() && steps.pause.outputs.paused != 'true' }}
|
|
104
197
|
run: npx --no-install starci app stack disconnect --env "$STACK_ENVIRONMENT" --execute
|
|
105
198
|
|
|
106
199
|
rollback:
|
|
@@ -111,6 +204,9 @@ jobs:
|
|
|
111
204
|
permissions:
|
|
112
205
|
contents: read
|
|
113
206
|
packages: read
|
|
207
|
+
concurrency:
|
|
208
|
+
group: stack-${{ inputs.environment }}
|
|
209
|
+
cancel-in-progress: false
|
|
114
210
|
env:
|
|
115
211
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
116
212
|
steps:
|
|
@@ -137,10 +233,7 @@ jobs:
|
|
|
137
233
|
- name: connect to the swarm manager
|
|
138
234
|
env:
|
|
139
235
|
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
140
|
-
|
|
141
|
-
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
142
|
-
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
143
|
-
VPS_USER: ${{ vars.VPS_USER }}
|
|
236
|
+
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
144
237
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
145
238
|
- name: redeploy the stored release
|
|
146
239
|
env:
|
package/templates/app/gitignore
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
"db:push": "{{appBinary}} db migrate --db-url-env DATABASE_URL --execute",
|
|
8
8
|
"db:plan": "{{appBinary}} db migrate --db-url-env DATABASE_URL",
|
|
9
9
|
"db:dump": "{{appBinary}} db dump --db-url-env DATABASE_URL --out ../{{project}}-db-backups",
|
|
10
|
-
"db:lint": "{{appBinary}} check --
|
|
10
|
+
"db:lint": "{{appBinary}} check --db",
|
|
@@ -6,3 +6,5 @@
|
|
|
6
6
|
*.mjs text eol=lf
|
|
7
7
|
.starcistacks/** text eol=lf
|
|
8
8
|
.starcistacks/**/*.enc binary
|
|
9
|
+
# The committed check cache (starci app check): union-merged JSON Lines, never a conflict; hidden from language statistics and review diffs.
|
|
10
|
+
.starcistacks/cache/** text eol=lf merge=union linguist-generated=true
|
|
@@ -6,3 +6,5 @@
|
|
|
6
6
|
*.mjs text eol=lf
|
|
7
7
|
.starcistacks/** text eol=lf
|
|
8
8
|
.starcistacks/**/*.enc binary
|
|
9
|
+
# The committed check cache (starci app check): union-merged JSON Lines, never a conflict; hidden from language statistics and review diffs.
|
|
10
|
+
.starcistacks/cache/** text eol=lf merge=union linguist-generated=true
|
|
@@ -60,7 +60,8 @@ export class EnvSource {
|
|
|
60
60
|
optionalDomain(key: string): string | undefined {
|
|
61
61
|
const value = this.optional(key)?.toLowerCase()
|
|
62
62
|
if (value === undefined) return undefined
|
|
63
|
-
if (!BARE_DOMAIN_PATTERN.test(value))
|
|
63
|
+
if (!BARE_DOMAIN_PATTERN.test(value))
|
|
64
|
+
throw new ConfigError({ code: ConfigErrorCode.KeyInvalid, params: { key } })
|
|
64
65
|
return value
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
{{header}}
|
|
2
|
-
name: deploy database
|
|
3
|
-
|
|
4
|
-
on:
|
|
5
|
-
workflow_dispatch:
|
|
6
|
-
inputs:
|
|
7
|
-
environment:
|
|
8
|
-
description: Protected environment whose sealed custody under .starcistacks holds DATABASE_URL
|
|
9
|
-
required: true
|
|
10
|
-
type: environment
|
|
11
|
-
backup_receipt:
|
|
12
|
-
description: Tracked backup receipt path verified by the deployment owner before migration
|
|
13
|
-
required: true
|
|
14
|
-
type: string
|
|
15
|
-
|
|
16
|
-
permissions:
|
|
17
|
-
contents: read
|
|
18
|
-
|
|
19
|
-
concurrency:
|
|
20
|
-
group: database-${{ inputs.environment }}
|
|
21
|
-
cancel-in-progress: false
|
|
22
|
-
|
|
23
|
-
jobs:
|
|
24
|
-
deploy:
|
|
25
|
-
timeout-minutes: 30
|
|
26
|
-
runs-on: ubuntu-latest
|
|
27
|
-
environment: ${{ inputs.environment }}
|
|
28
|
-
env:
|
|
29
|
-
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
30
|
-
BACKUP_RECEIPT: ${{ inputs.backup_receipt }}
|
|
31
|
-
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
32
|
-
steps:
|
|
33
|
-
- name: require release tag
|
|
34
|
-
shell: bash
|
|
35
|
-
run: '[[ "$GITHUB_REF" == refs/tags/v* ]] || exit 1'
|
|
36
|
-
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
37
|
-
- name: release tag matches package version
|
|
38
|
-
run: node -e "const version=require('./package.json').version;if(process.env.GITHUB_REF_NAME!=='v'+version)process.exit(1)"
|
|
39
|
-
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
40
|
-
with:
|
|
41
|
-
node-version: {{nodeMajor}}
|
|
42
|
-
cache: npm
|
|
43
|
-
- run: npm ci --ignore-scripts
|
|
44
|
-
- name: install SOPS
|
|
45
|
-
uses: mdgreenwald/mozilla-sops-action@bb2d96a13ef438ad122e5827a57ebd75d6ff118d # v2.1.0
|
|
46
|
-
with:
|
|
47
|
-
version: v3.13.2
|
|
48
|
-
- name: materialize sealed custody and migrate the database
|
|
49
|
-
env:
|
|
50
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
51
|
-
shell: bash
|
|
52
|
-
run: |
|
|
53
|
-
set -euo pipefail
|
|
54
|
-
[[ "$STACK_ENVIRONMENT" =~ ^[a-z][a-z0-9-]*$ ]]
|
|
55
|
-
git ls-files --error-unmatch -- "$BACKUP_RECEIPT" > /dev/null
|
|
56
|
-
test -s "$BACKUP_RECEIPT"
|
|
57
|
-
secret_dir="$XDG_DATA_HOME/StarCi/secrets/{{project}}/$STACK_ENVIRONMENT"
|
|
58
|
-
trap 'rm -rf -- "$secret_dir"' EXIT
|
|
59
|
-
npx --no-install starci app secret materialize --env "$STACK_ENVIRONMENT"
|
|
60
|
-
DATABASE_URL="$(cat "$secret_dir/DATABASE_URL")"
|
|
61
|
-
export DATABASE_URL
|
|
62
|
-
npx --no-install starci app db migrate --db-url-env DATABASE_URL || test "$?" -eq 1
|
|
63
|
-
STARCI_DB_ARMED=1 npx --no-install starci app db migrate --db-url-env DATABASE_URL --execute
|