gowalk-cicd 1.0.29 → 1.0.30
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/CLAUDE.md +4 -0
- package/action/.daemux-version +1 -1
- package/android-action/.daemux-version +1 -1
- package/backend-action/.daemux-version +1 -1
- package/package.json +1 -1
- package/src/install.mjs +13 -14
- package/templates/deploy.yml +46 -19
package/CLAUDE.md
CHANGED
|
@@ -92,6 +92,10 @@ node /path/to/gowalk-cicd/bin/cli.mjs
|
|
|
92
92
|
Detect and warn, tell the user to remove lines manually.
|
|
93
93
|
- Store API calls belong in GitHub Actions. Local tests may build/sign but must
|
|
94
94
|
never connect to App Store Connect or Google Play.
|
|
95
|
+
- Signing material should use encrypted Actions secrets. `deploy.yml`
|
|
96
|
+
materializes `ASC_KEY_P8` + its ID/issuer and the Android keystore,
|
|
97
|
+
properties and Play service account into an ephemeral runner checkout.
|
|
98
|
+
Tracked `creds/` files remain a backward-compatible fallback.
|
|
95
99
|
- The Android action serves two build systems. `android_config.project_kind()`
|
|
96
100
|
is the only place that decides which; every downstream step branches on the
|
|
97
101
|
`project_kind` output rather than re-sniffing the repo. Flutter wins the tie
|
package/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.30
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.30
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.30
|
package/package.json
CHANGED
package/src/install.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
statSync,
|
|
17
17
|
writeFileSync,
|
|
18
18
|
} from 'node:fs';
|
|
19
|
-
import { join,
|
|
19
|
+
import { join, resolve } from 'node:path';
|
|
20
20
|
import { fileURLToPath } from 'node:url';
|
|
21
21
|
import { dirname } from 'node:path';
|
|
22
22
|
|
|
@@ -182,29 +182,28 @@ function checkGitignore(repoRoot) {
|
|
|
182
182
|
function printGitignoreWarning(result) {
|
|
183
183
|
if (!result.exists || result.offenders.length === 0) return;
|
|
184
184
|
console.log('');
|
|
185
|
-
console.log('
|
|
185
|
+
console.log('NOTICE: .gitignore excludes checkout credentials.');
|
|
186
186
|
console.log(` File: ${result.path}`);
|
|
187
187
|
for (const { lineNumber, text } of result.offenders) {
|
|
188
188
|
console.log(` Line ${lineNumber}: ${text}`);
|
|
189
189
|
}
|
|
190
190
|
console.log('');
|
|
191
|
-
console.log('
|
|
192
|
-
console.log('
|
|
193
|
-
console.log(' (Your repo MUST be private — never do this in a public repo.)');
|
|
191
|
+
console.log(' Keep the ignore when using encrypted Actions secrets (recommended).');
|
|
192
|
+
console.log(' Otherwise the actions still support credentials already tracked in creds/.');
|
|
194
193
|
}
|
|
195
194
|
|
|
196
|
-
function printSummary(
|
|
195
|
+
function printSummary() {
|
|
197
196
|
console.log('');
|
|
198
197
|
console.log('Done.');
|
|
199
198
|
console.log('');
|
|
200
199
|
console.log('Next steps:');
|
|
201
|
-
console.log(
|
|
202
|
-
console.log(
|
|
203
|
-
console.log(
|
|
204
|
-
console.log(
|
|
205
|
-
console.log(
|
|
206
|
-
console.log(
|
|
207
|
-
console.log(
|
|
200
|
+
console.log(' Recommended: configure encrypted Actions secrets:');
|
|
201
|
+
console.log(' ASC_KEY_P8, ASC_KEY_ID, ASC_ISSUER_ID');
|
|
202
|
+
console.log(' ANDROID_UPLOAD_KEY_BASE64, ANDROID_SIGNING_PROPERTIES');
|
|
203
|
+
console.log(' GOOGLE_PLAY_SERVICE_ACCOUNT_JSON');
|
|
204
|
+
console.log(' The workflow materializes them with mode 0600 only on its ephemeral runner.');
|
|
205
|
+
console.log(' Existing checkout credentials remain a backward-compatible fallback.');
|
|
206
|
+
console.log(' Push to main after configuring the secrets; GitHub Actions builds both platforms.');
|
|
208
207
|
console.log('');
|
|
209
208
|
console.log('Re-run this installer anytime to update the vendored action:');
|
|
210
209
|
console.log(' npx --yes gowalk-cicd');
|
|
@@ -242,5 +241,5 @@ export async function runInstall({ dryRun = false } = {}) {
|
|
|
242
241
|
return;
|
|
243
242
|
}
|
|
244
243
|
|
|
245
|
-
printSummary(
|
|
244
|
+
printSummary();
|
|
246
245
|
}
|
package/templates/deploy.yml
CHANGED
|
@@ -35,6 +35,19 @@ jobs:
|
|
|
35
35
|
with:
|
|
36
36
|
fetch-depth: 0
|
|
37
37
|
persist-credentials: true
|
|
38
|
+
- name: Materialize encrypted iOS credentials
|
|
39
|
+
shell: bash
|
|
40
|
+
env:
|
|
41
|
+
CI_ASC_KEY_P8: ${{ secrets.ASC_KEY_P8 }}
|
|
42
|
+
CI_ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
|
|
43
|
+
CI_ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
|
|
44
|
+
run: |
|
|
45
|
+
[ -n "${CI_ASC_KEY_P8:-}" ] || exit 0
|
|
46
|
+
: "${CI_ASC_KEY_ID:?ASC_KEY_ID secret is required with ASC_KEY_P8}"
|
|
47
|
+
: "${CI_ASC_ISSUER_ID:?ASC_ISSUER_ID secret is required with ASC_KEY_P8}"
|
|
48
|
+
umask 077
|
|
49
|
+
mkdir -p creds
|
|
50
|
+
printf '%s' "$CI_ASC_KEY_P8" > "creds/AuthKey_${CI_ASC_KEY_ID}_Issuer_${CI_ASC_ISSUER_ID}.p8"
|
|
38
51
|
- name: Detect Flutter
|
|
39
52
|
id: flutter
|
|
40
53
|
shell: bash
|
|
@@ -74,7 +87,8 @@ jobs:
|
|
|
74
87
|
exit 0
|
|
75
88
|
fi
|
|
76
89
|
echo "::add-mask::$GIT_PRIVATE_TOKEN"
|
|
77
|
-
git config --global
|
|
90
|
+
git config --global \
|
|
91
|
+
url."https://x-access-token:${GIT_PRIVATE_TOKEN}@github.com/".insteadOf "https://github.com/"
|
|
78
92
|
echo "Configured authenticated github.com remotes for pub."
|
|
79
93
|
- name: Prepare Flutter iOS project
|
|
80
94
|
if: ${{ steps.flutter.outputs.enabled == 'true' }}
|
|
@@ -107,6 +121,22 @@ jobs:
|
|
|
107
121
|
timeout-minutes: 45
|
|
108
122
|
steps:
|
|
109
123
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
124
|
+
- name: Materialize encrypted Android credentials
|
|
125
|
+
shell: bash
|
|
126
|
+
env:
|
|
127
|
+
CI_ANDROID_KEYSTORE: ${{ secrets.ANDROID_UPLOAD_KEY_BASE64 }}
|
|
128
|
+
CI_ANDROID_PROPERTIES: ${{ secrets.ANDROID_SIGNING_PROPERTIES }}
|
|
129
|
+
CI_PLAY_ACCOUNT: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
|
|
130
|
+
run: |
|
|
131
|
+
[ -n "${CI_ANDROID_KEYSTORE:-}${CI_ANDROID_PROPERTIES:-}${CI_PLAY_ACCOUNT:-}" ] || exit 0
|
|
132
|
+
: "${CI_ANDROID_KEYSTORE:?ANDROID_UPLOAD_KEY_BASE64 secret is required}"
|
|
133
|
+
: "${CI_ANDROID_PROPERTIES:?ANDROID_SIGNING_PROPERTIES secret is required}"
|
|
134
|
+
: "${CI_PLAY_ACCOUNT:?GOOGLE_PLAY_SERVICE_ACCOUNT_JSON secret is required}"
|
|
135
|
+
umask 077
|
|
136
|
+
mkdir -p creds
|
|
137
|
+
printf '%s' "$CI_ANDROID_KEYSTORE" | base64 --decode > creds/android-upload-key.jks
|
|
138
|
+
printf '%s' "$CI_ANDROID_PROPERTIES" > creds/android-signing.properties
|
|
139
|
+
printf '%s' "$CI_PLAY_ACCOUNT" > creds/play-service-account.json
|
|
110
140
|
# Two Android delivery modes:
|
|
111
141
|
# * bitrise — the upload key + Play service account live in Bitrise,
|
|
112
142
|
# not the repo, so the GitHub runner cannot sign. Drop a
|
|
@@ -119,8 +149,9 @@ jobs:
|
|
|
119
149
|
id: mode
|
|
120
150
|
shell: bash
|
|
121
151
|
run: |
|
|
122
|
-
|
|
123
|
-
|
|
152
|
+
bitrise_enabled=$(python3 -c \
|
|
153
|
+
"import json;print(json.load(open('creds/bitrise.json')).get('enabled',False))" 2>/dev/null || true)
|
|
154
|
+
if [ -f creds/bitrise.json ] && [ "$bitrise_enabled" = "True" ]; then
|
|
124
155
|
echo "mode=bitrise" >> "$GITHUB_OUTPUT"
|
|
125
156
|
else
|
|
126
157
|
echo "mode=local" >> "$GITHUB_OUTPUT"
|
|
@@ -225,7 +256,8 @@ jobs:
|
|
|
225
256
|
exit 0
|
|
226
257
|
fi
|
|
227
258
|
echo "::add-mask::$GIT_PRIVATE_TOKEN"
|
|
228
|
-
git config --global
|
|
259
|
+
git config --global \
|
|
260
|
+
url."https://x-access-token:${GIT_PRIVATE_TOKEN}@github.com/".insteadOf "https://github.com/"
|
|
229
261
|
echo "Configured authenticated github.com remotes for pub."
|
|
230
262
|
# A Gradle daemon sized for a workstation does not fit a CI runner. Asking
|
|
231
263
|
# for -Xmx8G with a 4G metaspace reserves 12 GB before the Kotlin compile
|
|
@@ -322,13 +354,8 @@ jobs:
|
|
|
322
354
|
releaseFiles: ${{ steps.android.outputs.bundle-path }}
|
|
323
355
|
tracks: ${{ vars.GOOGLE_PLAY_TRACK || 'internal' }}
|
|
324
356
|
status: ${{ vars.GOOGLE_PLAY_STATUS || 'completed' }}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
# alongside status 'completed' is an error rather than a no-op.
|
|
328
|
-
userFraction: ${{ vars.GOOGLE_PLAY_STATUS == 'inProgress' && (vars.GOOGLE_PLAY_USER_FRACTION || '0.2') || '' }}
|
|
329
|
-
# Localized release notes: commit distribution/whatsnew/whatsnew-<bcp47>
|
|
330
|
-
# files (e.g. whatsnew-en-US, whatsnew-de-DE) and they ship with every
|
|
331
|
-
# release. Empty when the directory is absent — the action skips it.
|
|
357
|
+
userFraction: >-
|
|
358
|
+
${{ vars.GOOGLE_PLAY_STATUS == 'inProgress' && (vars.GOOGLE_PLAY_USER_FRACTION || '0.2') || '' }}
|
|
332
359
|
whatsNewDirectory: ${{ hashFiles('distribution/whatsnew/**') != '' && 'distribution/whatsnew' || '' }}
|
|
333
360
|
|
|
334
361
|
# The retry serves two different failures, and both need a fresh edit:
|
|
@@ -338,14 +365,12 @@ jobs:
|
|
|
338
365
|
# this once an app has changes a human must submit — after a policy
|
|
339
366
|
# rejection, for instance — and it fails the whole upload, so the built
|
|
340
367
|
# bundle never lands at all.
|
|
341
|
-
# Retrying with changesNotSentForReview gets the bundle onto Play either way.
|
|
342
|
-
# In the ordinary case the first attempt already submitted it and this is
|
|
343
|
-
# skipped; in the refused case the bundle is uploaded and waits for someone to
|
|
344
|
-
# press "Send changes for review" in Play Console, which is the only thing
|
|
345
|
-
# Google will not let a tool do.
|
|
346
368
|
- name: Retry Google Play upload without auto-submit
|
|
347
369
|
id: play-upload-retry
|
|
348
|
-
if:
|
|
370
|
+
if: >-
|
|
371
|
+
${{ steps.mode.outputs.mode == 'local'
|
|
372
|
+
&& steps.play.outputs.ready == 'true'
|
|
373
|
+
&& steps.play-upload.outcome == 'failure' }}
|
|
349
374
|
uses: r0adkll/upload-google-play@e738b9dd8f2476ea806d921b64aacd24f34515a5 # v1.1.5
|
|
350
375
|
with:
|
|
351
376
|
serviceAccountJson: ${{ steps.android.outputs.play-service-account }}
|
|
@@ -353,8 +378,10 @@ jobs:
|
|
|
353
378
|
releaseFiles: ${{ steps.android.outputs.bundle-path }}
|
|
354
379
|
tracks: ${{ vars.GOOGLE_PLAY_TRACK || 'internal' }}
|
|
355
380
|
status: ${{ vars.GOOGLE_PLAY_STATUS || 'completed' }}
|
|
356
|
-
userFraction:
|
|
357
|
-
|
|
381
|
+
userFraction: >-
|
|
382
|
+
${{ vars.GOOGLE_PLAY_STATUS == 'inProgress' && (vars.GOOGLE_PLAY_USER_FRACTION || '0.2') || '' }}
|
|
383
|
+
whatsNewDirectory: >-
|
|
384
|
+
${{ hashFiles('distribution/whatsnew/**') != '' && 'distribution/whatsnew' || '' }}
|
|
358
385
|
changesNotSentForReview: true
|
|
359
386
|
|
|
360
387
|
- name: Say what still needs a human
|