@starci/hfs 4.4.1 → 4.5.1
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 +8 -0
- package/ci/cli.mjs +64 -0
- package/ci/github.mjs +41 -0
- package/ci/secret.mjs +28 -0
- package/ci/vars.mjs +33 -0
- package/ci/verify.mjs +36 -0
- package/db/backup-receipt.mjs +129 -0
- package/db/dump.mjs +66 -0
- package/db/migrate.mjs +4 -1
- package/db/reset.mjs +125 -0
- package/emit/db-types.mjs +98 -5
- package/lint/run.mjs +28 -6
- package/package.json +2 -1
- package/release/ci-red.mjs +70 -0
- package/release/gate.mjs +98 -27
- package/release/index.mjs +6 -4
- package/release/push.mjs +1 -1
- package/runtime/knowledge/hfs/canon-pins.yaml +5 -5
- package/runtime/knowledge/hfs/rules.yaml +95 -4
- package/runtime/modules/kernel/failure-codes.yaml +60 -0
- package/runtime/modules/schemas/application-stacks.schema.yaml +134 -1
- package/runtime/packages/cli/src/catalog.generated.mjs +243 -20
- package/runtime/scripts/hfs/ci-declaration.mjs +102 -0
- package/runtime/scripts/hfs/rules/a15-findings.mjs +9 -0
- package/runtime/scripts/hfs/rules/app-workflow-findings.mjs +10 -0
- package/runtime/scripts/hfs/rules/ci-custody.mjs +104 -0
- package/runtime/scripts/hfs/rules/deploy-workflow.mjs +6 -19
- package/runtime/scripts/hfs/rules/fe-build-args.mjs +142 -0
- package/runtime/scripts/hfs/rules/supply-chain.mjs +40 -3
- package/runtime/scripts/hfs/rules/workflow-contexts.mjs +103 -0
- package/runtime/scripts/lib/secret-patterns.mjs +2 -2
- package/src/main.mjs +17 -6
- package/stack/context.mjs +13 -1
- package/stack/docker-transport.mjs +93 -15
- package/stack/release-store.mjs +12 -7
- package/stack/remote.mjs +14 -6
- package/stack/ssh-session.mjs +178 -0
- package/sync/ci-commands.mjs +205 -1
- package/sync/index.mjs +42 -16
- package/sync/quality-services.mjs +61 -0
- package/sync/readme-badges.mjs +44 -0
- package/sync/stack-images.mjs +29 -3
- package/templates/app/ci-workflows/github/workflows/ci.yml +33 -25
- package/templates/app/ci-workflows/github/workflows/e2e.yml +1 -0
- package/templates/app/ci-workflows/github/workflows/images.yml +25 -2
- package/templates/app/ci-workflows/github/workflows/stack-deploy.yml +8 -2
- package/templates/app/ci-workflows/install-steps.yml +23 -0
- package/templates/app/ci-workflows/jest-cache.yml +8 -0
- package/templates/app/ci-workflows/lint-base.yml +16 -0
- package/templates/app/ci-workflows/sonar-steps.yml +3 -9
- package/templates/app/ci-workflows-lite/github/workflows/ci.yml +36 -36
- package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +3 -1
- package/templates/app/ci-workflows-lite/github/workflows/images.yml +25 -2
- package/templates/app/ci-workflows-lite/github/workflows/stack-deploy.yml +8 -2
- package/templates/app/gitignore +2 -0
- package/templates/app/gitignore-lite +2 -0
- package/templates/app/quality-config/codecov.yml +6 -6
- package/templates/app/quality-config/sonar-project.properties +1 -0
- package/templates/app/readme-badges/README.md +1 -0
- package/templates/app/skeleton/.github/dependabot.yml +1 -14
- package/templates/app/skeleton/.starcistacks/application-stacks.yaml +62 -3
- package/templates/app/skeleton/README.md +6 -0
- package/templates/app/skeleton-lite/.github/dependabot.yml +1 -14
- package/templates/app/skeleton-lite/.starcistacks/application-stacks.yaml +58 -3
- package/templates/app/skeleton-lite/README.md +6 -0
- package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +53 -1
|
@@ -17,21 +17,44 @@ concurrency:
|
|
|
17
17
|
|
|
18
18
|
jobs:
|
|
19
19
|
image:
|
|
20
|
-
|
|
20
|
+
timeout-minutes: 30
|
|
21
|
+
runs-on: ubuntu-latest{{imageJobEnvironment}}
|
|
22
|
+
env:
|
|
23
|
+
STACK_ENVIRONMENT: {{imageEnvironment}}
|
|
21
24
|
strategy:
|
|
22
25
|
fail-fast: false
|
|
23
26
|
matrix:
|
|
24
27
|
include:
|
|
25
28
|
{{imageMatrix}}
|
|
26
|
-
steps:
|
|
29
|
+
steps:{{imageEnvironmentGuard}}
|
|
27
30
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
28
31
|
- name: release tag matches package version
|
|
29
32
|
run: node -e "const version=require('./package.json').version;if(process.env.GITHUB_REF_NAME!=='v'+version)process.exit(1)"
|
|
33
|
+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
34
|
+
if: {{imageBuildArgsIf}}
|
|
35
|
+
with:
|
|
36
|
+
node-version: {{nodeMajor}}
|
|
37
|
+
cache: npm
|
|
38
|
+
- run: npm ci --ignore-scripts
|
|
39
|
+
if: {{imageBuildArgsIf}}
|
|
40
|
+
- name: install SOPS
|
|
41
|
+
if: {{imageBuildArgsIf}}
|
|
42
|
+
uses: mdgreenwald/mozilla-sops-action@bb2d96a13ef438ad122e5827a57ebd75d6ff118d # v2.1.0
|
|
43
|
+
with:
|
|
44
|
+
version: v3.13.2
|
|
45
|
+
- name: public build values
|
|
46
|
+
id: args
|
|
47
|
+
if: {{imageBuildArgsIf}}
|
|
48
|
+
env:
|
|
49
|
+
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
50
|
+
IMAGE_APP: ${{ matrix.name }}
|
|
51
|
+
run: npx --no-install starci app stack build-args --env "$STACK_ENVIRONMENT" --app "$IMAGE_APP"
|
|
30
52
|
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
|
31
53
|
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
|
32
54
|
with:
|
|
33
55
|
context: .
|
|
34
56
|
file: ${{ matrix.file }}
|
|
57
|
+
build-args: ${{ steps.args.outputs.args }}
|
|
35
58
|
push: false
|
|
36
59
|
tags: {{imageProject}}/${{ matrix.name }}:${{ github.ref_name }}
|
|
37
60
|
# OCI keeps the SBOM and provenance attestations without publishing to a registry.
|
|
@@ -50,7 +50,6 @@ jobs:
|
|
|
50
50
|
packages: write
|
|
51
51
|
env:
|
|
52
52
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
53
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
54
53
|
steps:{{stackGuard}}
|
|
55
54
|
- name: require release tag
|
|
56
55
|
shell: bash
|
|
@@ -80,6 +79,7 @@ jobs:
|
|
|
80
79
|
password: ${{ github.token }}{{stackImageSteps}}
|
|
81
80
|
- name: connect to the swarm manager
|
|
82
81
|
env:
|
|
82
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
83
83
|
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
|
84
84
|
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
85
85
|
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
@@ -87,11 +87,14 @@ jobs:
|
|
|
87
87
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
88
88
|
- name: deploy the release
|
|
89
89
|
env:
|
|
90
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
90
91
|
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}{{stackImageEnv}}{{stackPassEnv}}
|
|
91
92
|
run: |
|
|
92
93
|
npx --no-install starci app stack deploy --env "$STACK_ENVIRONMENT" \{{stackImageArgs}}
|
|
93
94
|
--source-sha "$GITHUB_SHA" --execute
|
|
94
95
|
- name: disconnect from the swarm manager
|
|
96
|
+
env:
|
|
97
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
95
98
|
if: ${{ always() }}
|
|
96
99
|
run: npx --no-install starci app stack disconnect --env "$STACK_ENVIRONMENT" --execute
|
|
97
100
|
|
|
@@ -105,7 +108,6 @@ jobs:
|
|
|
105
108
|
packages: read
|
|
106
109
|
env:
|
|
107
110
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
108
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
109
111
|
steps:
|
|
110
112
|
- name: require release tag
|
|
111
113
|
shell: bash
|
|
@@ -129,6 +131,7 @@ jobs:
|
|
|
129
131
|
password: ${{ github.token }}
|
|
130
132
|
- name: connect to the swarm manager
|
|
131
133
|
env:
|
|
134
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
132
135
|
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
|
133
136
|
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
134
137
|
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
@@ -136,6 +139,7 @@ jobs:
|
|
|
136
139
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
137
140
|
- name: redeploy the stored release
|
|
138
141
|
env:
|
|
142
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
139
143
|
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
140
144
|
RELEASE: ${{ inputs.release }}
|
|
141
145
|
shell: bash
|
|
@@ -144,5 +148,7 @@ jobs:
|
|
|
144
148
|
[ -z "$RELEASE" ] || release=(--release "$RELEASE")
|
|
145
149
|
npx --no-install starci app stack rollback --env "$STACK_ENVIRONMENT" "${release[@]}" --execute
|
|
146
150
|
- name: disconnect from the swarm manager
|
|
151
|
+
env:
|
|
152
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
147
153
|
if: ${{ always() }}
|
|
148
154
|
run: npx --no-install starci app stack disconnect --env "$STACK_ENVIRONMENT" --execute
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
2
|
+
with:
|
|
3
|
+
fetch-depth: 0
|
|
4
|
+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
5
|
+
with:
|
|
6
|
+
node-version: {{nodeMajor}}
|
|
7
|
+
cache: npm
|
|
8
|
+
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
9
|
+
id: deps
|
|
10
|
+
with:
|
|
11
|
+
path: node_modules
|
|
12
|
+
key: ${{ runner.os }}-node{{nodeMajor}}-modules-${{ hashFiles('package-lock.json') }}
|
|
13
|
+
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
14
|
+
with:
|
|
15
|
+
path: |
|
|
16
|
+
.turbo
|
|
17
|
+
fe/apps/*/.next/cache
|
|
18
|
+
key: ${{ runner.os }}-node{{nodeMajor}}-build-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
|
|
19
|
+
restore-keys: |
|
|
20
|
+
${{ runner.os }}-node{{nodeMajor}}-build-${{ hashFiles('package-lock.json') }}-
|
|
21
|
+
${{ runner.os }}-node{{nodeMajor}}-build-
|
|
22
|
+
- run: npm ci --ignore-scripts
|
|
23
|
+
if: steps.deps.outputs.cache-hit != 'true'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
- name: Jest cache
|
|
2
|
+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
3
|
+
with:
|
|
4
|
+
path: .jest-cache
|
|
5
|
+
key: ${{ runner.os }}-node{{nodeMajor}}-jest-${{ hashFiles('package-lock.json') }}-${{ github.sha }}
|
|
6
|
+
restore-keys: |
|
|
7
|
+
${{ runner.os }}-node{{nodeMajor}}-jest-${{ hashFiles('package-lock.json') }}-
|
|
8
|
+
${{ runner.os }}-node{{nodeMajor}}-jest-
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
- name: lint baseline
|
|
2
|
+
shell: bash
|
|
3
|
+
env:
|
|
4
|
+
BASE_BRANCH: ${{ github.base_ref }}
|
|
5
|
+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
6
|
+
BEFORE: ${{ github.event.before }}
|
|
7
|
+
run: |
|
|
8
|
+
base="origin/$DEFAULT_BRANCH"
|
|
9
|
+
if [[ "$GITHUB_EVENT_NAME" == pull_request ]]; then
|
|
10
|
+
base="origin/$BASE_BRANCH"
|
|
11
|
+
elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
|
|
12
|
+
base=$(git describe --tags --abbrev=0 "$GITHUB_REF^" 2>/dev/null) || base="origin/$DEFAULT_BRANCH"
|
|
13
|
+
elif [[ "$GITHUB_EVENT_NAME" == push && -n "$BEFORE" && ! "$BEFORE" =~ ^0+$ ]]; then
|
|
14
|
+
base="$BEFORE"
|
|
15
|
+
fi
|
|
16
|
+
echo "STARCI_BASE_REF=$base" >> "$GITHUB_ENV"
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}
|
|
5
|
-
- uses: SonarSource/sonarqube-quality-gate-action@7a5fffe8e523c40e0c740b6bc2712ab503e52efa # v1.2.1
|
|
6
|
-
if: ${{ !cancelled() && startsWith(github.ref, 'refs/tags/v') && env.SONAR_TOKEN != '' }}
|
|
7
|
-
timeout-minutes: 10
|
|
8
|
-
env:
|
|
9
|
-
SONAR_HOST_URL: ${{ vars.SONAR_HOST_URL }}
|
|
1
|
+
{{sonarJobHeader}}
|
|
2
|
+
{{> app/ci-workflows/install-steps.yml}}
|
|
3
|
+
{{sonarJobSteps}}
|
|
@@ -9,68 +9,68 @@ on:
|
|
|
9
9
|
permissions:
|
|
10
10
|
contents: read
|
|
11
11
|
|
|
12
|
-
# One run per ref.
|
|
12
|
+
# One run per ref: a release tag is never cancelled by another run.
|
|
13
13
|
concurrency:
|
|
14
14
|
group: ci-${{ github.ref }}
|
|
15
15
|
cancel-in-progress: false
|
|
16
16
|
|
|
17
17
|
jobs:
|
|
18
|
-
|
|
18
|
+
fast:
|
|
19
|
+
timeout-minutes: 20
|
|
19
20
|
runs-on: ubuntu-latest
|
|
20
|
-
|
|
21
|
-
permissions:
|
|
22
|
-
contents: read
|
|
23
|
-
id-token: write
|
|
24
|
-
env:
|
|
25
|
-
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
21
|
+
{{sonarEnv}}
|
|
26
22
|
steps:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
with:
|
|
30
|
-
node-version: {{nodeMajor}}
|
|
31
|
-
cache: npm
|
|
32
|
-
- run: npm ci --ignore-scripts
|
|
23
|
+
{{> app/ci-workflows/install-steps.yml}}
|
|
24
|
+
{{> app/ci-workflows/lint-base.yml}}
|
|
33
25
|
- name: production dependency audit
|
|
34
|
-
run:
|
|
35
|
-
|
|
36
|
-
if: env.SONAR_TOKEN == ''
|
|
37
|
-
run: {{ciLint}}
|
|
38
|
-
- name: lint with Sonar import
|
|
39
|
-
if: env.SONAR_TOKEN != ''
|
|
40
|
-
run: {{ciLintSonar}}
|
|
26
|
+
run: {{auditCommand}}
|
|
27
|
+
{{ciLintSteps}}
|
|
41
28
|
- name: format
|
|
42
29
|
run: npm run format:check
|
|
43
30
|
- name: typecheck
|
|
44
31
|
run: npm run typecheck
|
|
32
|
+
|
|
33
|
+
test:
|
|
34
|
+
timeout-minutes: 45
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
# Codecov OIDC authentication requires a job-scoped identity token.
|
|
37
|
+
permissions:
|
|
38
|
+
contents: read
|
|
39
|
+
id-token: write
|
|
40
|
+
steps:
|
|
41
|
+
{{> app/ci-workflows/install-steps.yml}}
|
|
42
|
+
{{> app/ci-workflows/jest-cache.yml}}
|
|
45
43
|
- name: unit
|
|
46
|
-
run: npm test -- --ci
|
|
44
|
+
run: npm test -- --ci --forceExit --cacheDirectory .jest-cache
|
|
47
45
|
- name: coverage proof
|
|
48
46
|
run: {{ciCoverageProof}}
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
if: ${{ !cancelled() && startsWith(github.ref, 'refs/tags/v') }}
|
|
47
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
48
|
+
if: always() && hashFiles('{{lcovReport}}') != ''
|
|
52
49
|
with:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
name: {{lcovArtifact}}
|
|
51
|
+
path: {{lcovReport}}
|
|
52
|
+
{{codecovSteps}}
|
|
53
|
+
|
|
54
|
+
build:
|
|
55
|
+
timeout-minutes: 30
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
{{> app/ci-workflows/install-steps.yml}}
|
|
57
59
|
- name: build be
|
|
58
60
|
run: npm run build:be
|
|
59
61
|
- name: build fe
|
|
60
62
|
run: npm run build:fe
|
|
63
|
+
{{ciBuildEnv}}
|
|
61
64
|
- name: database migration checks
|
|
62
65
|
run: {{ciDatabaseLint}}
|
|
63
|
-
|
|
66
|
+
|
|
67
|
+
{{sonarJob}}
|
|
64
68
|
|
|
65
69
|
db-types:
|
|
70
|
+
timeout-minutes: 30
|
|
66
71
|
runs-on: ubuntu-latest
|
|
67
72
|
steps:
|
|
68
|
-
|
|
69
|
-
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
70
|
-
with:
|
|
71
|
-
node-version: {{nodeMajor}}
|
|
72
|
-
cache: npm
|
|
73
|
-
- run: npm ci --ignore-scripts
|
|
73
|
+
{{> app/ci-workflows/install-steps.yml}}
|
|
74
74
|
- name: start Supabase
|
|
75
75
|
run: npm run db:start
|
|
76
76
|
- name: apply migrations
|
|
@@ -22,13 +22,13 @@ concurrency:
|
|
|
22
22
|
|
|
23
23
|
jobs:
|
|
24
24
|
deploy:
|
|
25
|
+
timeout-minutes: 30
|
|
25
26
|
runs-on: ubuntu-latest
|
|
26
27
|
environment: ${{ inputs.environment }}
|
|
27
28
|
env:
|
|
28
29
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
29
30
|
BACKUP_RECEIPT: ${{ inputs.backup_receipt }}
|
|
30
31
|
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
31
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
32
32
|
steps:
|
|
33
33
|
- name: require release tag
|
|
34
34
|
shell: bash
|
|
@@ -46,6 +46,8 @@ jobs:
|
|
|
46
46
|
with:
|
|
47
47
|
version: v3.13.2
|
|
48
48
|
- name: materialize sealed custody and push migrations
|
|
49
|
+
env:
|
|
50
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
49
51
|
shell: bash
|
|
50
52
|
run: |
|
|
51
53
|
set -euo pipefail
|
|
@@ -17,21 +17,44 @@ concurrency:
|
|
|
17
17
|
|
|
18
18
|
jobs:
|
|
19
19
|
image:
|
|
20
|
-
|
|
20
|
+
timeout-minutes: 30
|
|
21
|
+
runs-on: ubuntu-latest{{imageJobEnvironment}}
|
|
22
|
+
env:
|
|
23
|
+
STACK_ENVIRONMENT: {{imageEnvironment}}
|
|
21
24
|
strategy:
|
|
22
25
|
fail-fast: false
|
|
23
26
|
matrix:
|
|
24
27
|
include:
|
|
25
28
|
{{imageMatrix}}
|
|
26
|
-
steps:
|
|
29
|
+
steps:{{imageEnvironmentGuard}}
|
|
27
30
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
|
28
31
|
- name: release tag matches package version
|
|
29
32
|
run: node -e "const version=require('./package.json').version;if(process.env.GITHUB_REF_NAME!=='v'+version)process.exit(1)"
|
|
33
|
+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
34
|
+
if: {{imageBuildArgsIf}}
|
|
35
|
+
with:
|
|
36
|
+
node-version: {{nodeMajor}}
|
|
37
|
+
cache: npm
|
|
38
|
+
- run: npm ci --ignore-scripts
|
|
39
|
+
if: {{imageBuildArgsIf}}
|
|
40
|
+
- name: install SOPS
|
|
41
|
+
if: {{imageBuildArgsIf}}
|
|
42
|
+
uses: mdgreenwald/mozilla-sops-action@bb2d96a13ef438ad122e5827a57ebd75d6ff118d # v2.1.0
|
|
43
|
+
with:
|
|
44
|
+
version: v3.13.2
|
|
45
|
+
- name: public build values
|
|
46
|
+
id: args
|
|
47
|
+
if: {{imageBuildArgsIf}}
|
|
48
|
+
env:
|
|
49
|
+
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
50
|
+
IMAGE_APP: ${{ matrix.name }}
|
|
51
|
+
run: npx --no-install starci app stack build-args --env "$STACK_ENVIRONMENT" --app "$IMAGE_APP"
|
|
30
52
|
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
|
31
53
|
- uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
|
32
54
|
with:
|
|
33
55
|
context: .
|
|
34
56
|
file: ${{ matrix.file }}
|
|
57
|
+
build-args: ${{ steps.args.outputs.args }}
|
|
35
58
|
push: false
|
|
36
59
|
tags: {{imageProject}}/${{ matrix.name }}:${{ github.ref_name }}
|
|
37
60
|
# OCI keeps the SBOM and provenance attestations without publishing to a registry.
|
|
@@ -50,7 +50,6 @@ jobs:
|
|
|
50
50
|
packages: write
|
|
51
51
|
env:
|
|
52
52
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
53
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
54
53
|
steps:{{stackGuard}}
|
|
55
54
|
- name: require release tag
|
|
56
55
|
shell: bash
|
|
@@ -80,6 +79,7 @@ jobs:
|
|
|
80
79
|
password: ${{ github.token }}{{stackImageSteps}}
|
|
81
80
|
- name: connect to the swarm manager
|
|
82
81
|
env:
|
|
82
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
83
83
|
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
|
84
84
|
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
85
85
|
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
@@ -87,11 +87,14 @@ jobs:
|
|
|
87
87
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
88
88
|
- name: deploy the release
|
|
89
89
|
env:
|
|
90
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
90
91
|
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}{{stackImageEnv}}{{stackPassEnv}}
|
|
91
92
|
run: |
|
|
92
93
|
npx --no-install starci app stack deploy --env "$STACK_ENVIRONMENT" \{{stackImageArgs}}
|
|
93
94
|
--source-sha "$GITHUB_SHA" --execute
|
|
94
95
|
- name: disconnect from the swarm manager
|
|
96
|
+
env:
|
|
97
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
95
98
|
if: ${{ always() }}
|
|
96
99
|
run: npx --no-install starci app stack disconnect --env "$STACK_ENVIRONMENT" --execute
|
|
97
100
|
|
|
@@ -105,7 +108,6 @@ jobs:
|
|
|
105
108
|
packages: read
|
|
106
109
|
env:
|
|
107
110
|
STACK_ENVIRONMENT: ${{ inputs.environment }}
|
|
108
|
-
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
109
111
|
steps:
|
|
110
112
|
- name: require release tag
|
|
111
113
|
shell: bash
|
|
@@ -129,6 +131,7 @@ jobs:
|
|
|
129
131
|
password: ${{ github.token }}
|
|
130
132
|
- name: connect to the swarm manager
|
|
131
133
|
env:
|
|
134
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
132
135
|
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
|
|
133
136
|
VPS_KNOWN_HOSTS: ${{ secrets.VPS_KNOWN_HOSTS }}
|
|
134
137
|
VPS_HOST: ${{ vars.VPS_HOST }}
|
|
@@ -136,6 +139,7 @@ jobs:
|
|
|
136
139
|
run: npx --no-install starci app stack connect --env "$STACK_ENVIRONMENT" --execute
|
|
137
140
|
- name: redeploy the stored release
|
|
138
141
|
env:
|
|
142
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
139
143
|
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
|
|
140
144
|
RELEASE: ${{ inputs.release }}
|
|
141
145
|
shell: bash
|
|
@@ -144,5 +148,7 @@ jobs:
|
|
|
144
148
|
[ -z "$RELEASE" ] || release=(--release "$RELEASE")
|
|
145
149
|
npx --no-install starci app stack rollback --env "$STACK_ENVIRONMENT" "${release[@]}" --execute
|
|
146
150
|
- name: disconnect from the swarm manager
|
|
151
|
+
env:
|
|
152
|
+
XDG_DATA_HOME: ${{ runner.temp }}/starci-data
|
|
147
153
|
if: ${{ always() }}
|
|
148
154
|
run: npx --no-install starci app stack disconnect --env "$STACK_ENVIRONMENT" --execute
|
package/templates/app/gitignore
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{{header}}
|
|
2
2
|
# The be unit run's lcov ({{lcovReport}}), uploaded by the managed CI workflow. Coverage is the logic of be/src/modules/**: the status
|
|
3
3
|
# paths are the measured roots of the one coverage scope (derived from the slot manifest's `coverage` field; its complement is rendered into
|
|
4
|
-
# sonar.coverage.exclusions and its roots into be/jest.config.js), held at
|
|
5
|
-
# service app, plus platform) is held at
|
|
4
|
+
# sonar.coverage.exclusions and its roots into be/jest.config.js), held at {{codecovTarget}} on the project and on the patch, and each component (one per
|
|
5
|
+
# service app, plus platform) is held at {{codecovTarget}} too. fe/ and be/src/features are outside coverage (features are thin by rule; a front end has no tests).
|
|
6
6
|
codecov:
|
|
7
7
|
require_ci_to_pass: true
|
|
8
8
|
coverage:
|
|
9
9
|
status:
|
|
10
10
|
project:
|
|
11
11
|
default:
|
|
12
|
-
target:
|
|
12
|
+
target: {{codecovTarget}}%
|
|
13
13
|
threshold: 0%
|
|
14
14
|
paths:
|
|
15
15
|
{{codecovPaths}}
|
|
16
16
|
patch:
|
|
17
17
|
default:
|
|
18
|
-
target:
|
|
18
|
+
target: {{codecovTarget}}%
|
|
19
19
|
threshold: 0%
|
|
20
20
|
paths:
|
|
21
21
|
{{codecovPaths}}
|
|
@@ -23,10 +23,10 @@ component_management:
|
|
|
23
23
|
default_rules:
|
|
24
24
|
statuses:
|
|
25
25
|
- type: project
|
|
26
|
-
target:
|
|
26
|
+
target: {{codecovTarget}}%
|
|
27
27
|
threshold: 0%
|
|
28
28
|
- type: patch
|
|
29
|
-
target:
|
|
29
|
+
target: {{codecovTarget}}%
|
|
30
30
|
threshold: 0%
|
|
31
31
|
individual_components:
|
|
32
32
|
{{codecovComponents}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{readmeBadges}}
|
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
{{header}}
|
|
2
2
|
version: 2
|
|
3
3
|
updates:
|
|
4
|
-
|
|
5
|
-
directory: /
|
|
6
|
-
schedule:
|
|
7
|
-
interval: weekly
|
|
8
|
-
- package-ecosystem: github-actions
|
|
9
|
-
directory: /
|
|
10
|
-
schedule:
|
|
11
|
-
interval: weekly
|
|
12
|
-
- package-ecosystem: docker
|
|
13
|
-
directories:
|
|
14
|
-
- /be/apps/*
|
|
15
|
-
- /fe/apps/*
|
|
16
|
-
schedule:
|
|
17
|
-
interval: weekly
|
|
4
|
+
{{dependabotUpdates}}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# The app declares its topology before any owner provisions a deployment.
|
|
2
2
|
# All-zero application digests are illustrative and must be replaced by verified release digests.
|
|
3
3
|
schema: starci/application-stacks@1
|
|
4
|
+
# To render README badges, declare ci.github: {repository: owner/repo, defaultBranch: main}.
|
|
5
|
+
# A GitHub package.json repository URL also enables the managed block.
|
|
4
6
|
sources:
|
|
5
7
|
- repository: "{{project}}"
|
|
6
8
|
backing:
|
|
@@ -104,8 +106,15 @@ environments:
|
|
|
104
106
|
app: core
|
|
105
107
|
app:
|
|
106
108
|
app: app
|
|
109
|
+
# Public browser configuration; replace the placeholder origin before deployment.
|
|
110
|
+
buildArgs:
|
|
111
|
+
values:
|
|
112
|
+
NEXT_PUBLIC_SITE_URL: "https://{{project}}.example.invalid"
|
|
107
113
|
landing:
|
|
108
114
|
app: landing
|
|
115
|
+
buildArgs:
|
|
116
|
+
values:
|
|
117
|
+
NEXT_PUBLIC_APP_URL: "https://{{project}}.example.invalid"
|
|
109
118
|
volumes:
|
|
110
119
|
- {{project}}-production-ingress-data
|
|
111
120
|
- {{project}}-production-ingress-config-data
|
|
@@ -126,19 +135,69 @@ environments:
|
|
|
126
135
|
k8s:
|
|
127
136
|
status: deferred
|
|
128
137
|
reason: This starter declares Docker Swarm production; no Kubernetes environment is provisioned.
|
|
138
|
+
ci:
|
|
139
|
+
secrets:
|
|
140
|
+
- {name: SONAR_TOKEN, scope: repository, purpose: Sonar analysis token provisioned for this app, optional: true}
|
|
141
|
+
- {name: SOPS_AGE_KEY, scope: environment, environment: production, purpose: Decrypt app members during deployment, optional: true}
|
|
142
|
+
- {name: VPS_SSH_KEY, scope: environment, environment: production, purpose: Deployment SSH key, optional: true}
|
|
143
|
+
- {name: VPS_KNOWN_HOSTS, scope: environment, environment: production, purpose: Pinned deployment SSH host keys, optional: true}
|
|
144
|
+
vars:
|
|
145
|
+
- {name: SONAR_HOST_URL, scope: repository, value: "https://sonar.{{project}}.example.invalid", purpose: Documentation endpoint to replace with this app's public Sonar host, optional: true}
|
|
146
|
+
- {name: VPS_HOST, scope: environment, environment: production, value: 203.0.113.10, purpose: Documentation deployment address to replace before use, optional: true}
|
|
147
|
+
- {name: VPS_USER, scope: environment, environment: production, value: deploy, purpose: Documentation deployment user to replace before use, optional: true}
|
|
129
148
|
services:
|
|
130
149
|
sonar:
|
|
131
150
|
provider: sonarqube
|
|
151
|
+
optional: true
|
|
132
152
|
mode: local
|
|
133
153
|
qualityGate: {{sonarGate}}
|
|
134
|
-
host: {
|
|
154
|
+
host: {local: http://127.0.0.1:9000, public: "https://sonar.{{project}}.example.invalid"}
|
|
135
155
|
stack:
|
|
136
156
|
owner: host
|
|
137
157
|
root: .claude/ext/sonar
|
|
138
158
|
environment: dev
|
|
139
159
|
compose: compose.yaml
|
|
140
160
|
auth: token
|
|
141
|
-
|
|
161
|
+
credentials: []
|
|
162
|
+
projects: [{repository: "{{project}}", key: "{{project}}"}]
|
|
163
|
+
ci: {wiring: optional-follow-up, workflow: .github/workflows/ci.yml, token: SONAR_TOKEN, hostVar: SONAR_HOST_URL}
|
|
142
164
|
ownerAction:
|
|
143
|
-
needed: Provision
|
|
165
|
+
needed: Provision this app's Sonar host and project, then set SONAR_TOKEN with starci app ci secret set and sync SONAR_HOST_URL.
|
|
144
166
|
reason: A fresh app declares its quality service without fabricating credentials or a successful analysis.
|
|
167
|
+
codecov:
|
|
168
|
+
provider: codecov
|
|
169
|
+
mode: hosted
|
|
170
|
+
purpose: Report application coverage through GitHub OIDC.
|
|
171
|
+
auth: oidc
|
|
172
|
+
target: 100
|
|
173
|
+
components: auto
|
|
174
|
+
required: true
|
|
175
|
+
ci: {wiring: optional-follow-up, workflow: .github/workflows/ci.yml}
|
|
176
|
+
ownerAction: none
|
|
177
|
+
dependabot:
|
|
178
|
+
provider: github
|
|
179
|
+
mode: hosted
|
|
180
|
+
purpose: Keep application dependencies and workflow actions current.
|
|
181
|
+
ecosystems: [npm, docker, github-actions]
|
|
182
|
+
schedule: {interval: weekly}
|
|
183
|
+
groups: {minorPatch: grouped, major: per-package}
|
|
184
|
+
ignore: ['@starci/*']
|
|
185
|
+
security: immediate
|
|
186
|
+
ownerAction: none
|
|
187
|
+
audit:
|
|
188
|
+
provider: npm
|
|
189
|
+
mode: local
|
|
190
|
+
purpose: Refuse high severity production dependency vulnerabilities.
|
|
191
|
+
level: high
|
|
192
|
+
omitDev: true
|
|
193
|
+
in: [release-gate, ci]
|
|
194
|
+
ownerAction: none
|
|
195
|
+
container-registry:
|
|
196
|
+
provider: ghcr
|
|
197
|
+
mode: hosted
|
|
198
|
+
purpose: Publish this app's deployment images with the workflow GitHub token.
|
|
199
|
+
host: {public: https://ghcr.io}
|
|
200
|
+
auth: github-token
|
|
201
|
+
projects: [{repository: "{{project}}", key: "{{project}}"}]
|
|
202
|
+
ci: {wiring: optional-follow-up}
|
|
203
|
+
ownerAction: none
|
|
@@ -16,6 +16,10 @@ TypeScript everywhere; NestJS in `be/`, Next.js with next-intl in `fe/`; npm wit
|
|
|
16
16
|
- `fe/`: the front end, one Next app per `fe/apps/<app>` and the shared workspace packages under `fe/packages/` (the ui drawings and the next-intl stack both apps call).
|
|
17
17
|
- `scripts/`: the app's operational scripts; `hfs.json` declares both sides.
|
|
18
18
|
|
|
19
|
+
## Status badges
|
|
20
|
+
|
|
21
|
+
Declare `ci.github.repository` and `ci.github.defaultBranch` in `.starcistacks/application-stacks.yaml` (or set the GitHub `repository` URL in `package.json`), then run `npx starci app sync --write`. Sync inserts a managed badge block after the title; `npx starci app sync --check` verifies it.
|
|
22
|
+
|
|
19
23
|
## Development
|
|
20
24
|
|
|
21
25
|
```sh
|
|
@@ -33,6 +37,8 @@ requests) and `PRIMARY_DB_URL` at boot; every door is closed until it is marked
|
|
|
33
37
|
`npm run cli -- seed run` runs the dev seeds of `.starcistacks/dev/seeds` (run both from the app root). The product app reads
|
|
34
38
|
`NEXT_PUBLIC_SITE_URL` and `NEXT_PUBLIC_GRAPHQL_URL` (the back end it calls through `fe/apps/app/src/modules/api`, read once the first GraphQL operation exists), the landing `NEXT_PUBLIC_APP_URL` (the product app it hands the reader over to). A missing key stops the process with an error that names it.
|
|
35
39
|
|
|
40
|
+
Production browser build values live in `.starcistacks/application-stacks.yaml` under `environments.production.deploy.images.*.buildArgs.values`. Replace the placeholder origins for the product's `NEXT_PUBLIC_SITE_URL` and the landing's `NEXT_PUBLIC_APP_URL` with your product app's public origin before building deployment images.
|
|
41
|
+
|
|
36
42
|
## Work
|
|
37
43
|
|
|
38
44
|
The product's Work records live in `.starciwork`.
|
|
@@ -1,17 +1,4 @@
|
|
|
1
1
|
{{header}}
|
|
2
2
|
version: 2
|
|
3
3
|
updates:
|
|
4
|
-
|
|
5
|
-
directory: /
|
|
6
|
-
schedule:
|
|
7
|
-
interval: weekly
|
|
8
|
-
- package-ecosystem: github-actions
|
|
9
|
-
directory: /
|
|
10
|
-
schedule:
|
|
11
|
-
interval: weekly
|
|
12
|
-
- package-ecosystem: docker
|
|
13
|
-
directories:
|
|
14
|
-
- /be/apps/*
|
|
15
|
-
- /fe/apps/*
|
|
16
|
-
schedule:
|
|
17
|
-
interval: weekly
|
|
4
|
+
{{dependabotUpdates}}
|