Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
f961ca3
fix: load Sparkle notarization credentials from Fleet-OPS Infisical
jaywedgeworth22 Oct 18, 2026
220da74
test: verify Sparkle credential wiring and sanitized notarization pre…
jaywedgeworth22 Oct 18, 2026
5f1b265
test: verify Sparkle credential wiring and sanitized notarization pre…
jaywedgeworth22 Oct 18, 2026
96a2773
docs: explain Sparkle credential source and feed recovery gates
jaywedgeworth22 Oct 18, 2026
51629d3
docs: clarify fail-closed ASC credential loading
jaywedgeworth22 Oct 18, 2026
3eee6b8
test: pin secret-free PR guards and always cleanup
jaywedgeworth22 Oct 18, 2026
1f6839f
docs: distinguish missing ASC failure from non-publishing validation
jaywedgeworth22 Oct 18, 2026
523609f
fix: keep project identifiers out of credential failure messages
jaywedgeworth22 Oct 18, 2026
b4a8cc8
test: pin fixed credential error messages without project identifiers
jaywedgeworth22 Oct 18, 2026
87a343f
Merge remote-tracking branch 'origin/main' into jet/fix-sparkle-infis…
jaywedgeworth22 Oct 20, 2026
50b2a6c
fix(release): load the signing key without a hard-coded project id
jaywedgeworth22 Oct 20, 2026
6f99c2f
fix(release): let a manual run verify the credentials without publishing
jaywedgeworth22 Oct 20, 2026
a1711aa
test(release): pin the verify-only dispatch input
jaywedgeworth22 Oct 20, 2026
4e40665
Merge a1711aab9c4827d9ad443e6db293399e0d31431e into 771b1d05296a39c69…
jaywedgeworth22 Oct 20, 2026
7b953bf
autofix: read the Infisical login token without destructuring it
github-actions[bot] Oct 20, 2026
de969bf
fix(release): read the signing key through the approved action, not t…
jaywedgeworth22 Oct 20, 2026
e68ee0f
Merge remote-tracking branch 'origin/jet/fix-sparkle-infisical' into …
jaywedgeworth22 Oct 20, 2026
9a07064
test(release): assert the bearer token on the secrets request
jaywedgeworth22 Oct 20, 2026
da9ed6e
autofix: name ASC_KEY_P8 in the staging error and cover the CLI path
github-actions[bot] Oct 20, 2026
33ce8f6
fix(release): stop a verify-only run installing a toolchain it will n…
jaywedgeworth22 Oct 20, 2026
dd178df
fix(release): run the shared fetch script's test in CI
jaywedgeworth22 Oct 20, 2026
c910816
autofix: state the real ASC key step boundary in the secrets table
github-actions[bot] Oct 20, 2026
8aa3d74
fix(release): isolate the verify-only dispatch and publish only from …
jaywedgeworth22 Oct 20, 2026
8c02162
Merge origin/main into jet/fix-sparkle-infisical
jaywedgeworth22 Oct 21, 2026
9bd96d8
fix(pip): a failed provider is not a default PiP target
Oct 21, 2026
9dd5962
fix(release): keep the ASC private key out of the job environment
jaywedgeworth22 Oct 21, 2026
53ac0d5
fix(pip): do not rank a failed provider by its cached quota
jaywedgeworth22 Oct 21, 2026
b863e1a
fix(release): harden ASC staging and wire APNs tests into ship contract
Oct 21, 2026
92b1cfd
fix(release): resolve the ASC credentials environment-first, from the…
jaywedgeworth22 Oct 21, 2026
ec266b5
Merge remote-tracking branch 'origin/main' into mm/verify-257
jaywedgeworth22 Oct 21, 2026
90daeb4
Merge commit '53ac0d5b537f27030e67857c593e7f460b3856de' into mm/verif…
jaywedgeworth22 Oct 21, 2026
587f8c8
Merge remote-tracking branch 'origin/main' into mm/verify-257
jaywedgeworth22 Oct 21, 2026
866b92c
fix(release): remove the ASC key entry from the environment file
jaywedgeworth22 Oct 21, 2026
053e426
fix(release): resolve the ASC credentials through the fleet reader
jaywedgeworth22 Oct 21, 2026
707dc39
fix(release): keep the pinned reader commit out of the secret scanner
jaywedgeworth22 Oct 21, 2026
544ecc9
ci: allow the pinned reader commit in the secret scanner
jaywedgeworth22 Oct 21, 2026
1599520
fix(release): keep the minted token out of every file
jaywedgeworth22 Oct 21, 2026
4340751
test(release): prove the consumer runs after an installer failure
Oct 21, 2026
179ca58
test(release): mark the synthetic key fixtures as scanner-approved
Oct 21, 2026
06abad3
Prove the fleet reader before the consumer runs
jaywedgeworth22 Oct 21, 2026
10e435c
Merge origin/main into jet/fix-sparkle-infisical
jaywedgeworth22 Oct 21, 2026
c2d96a7
test(release): pin the install-failure state the workflows actually r…
jaywedgeworth22 Oct 21, 2026
ac72809
fix(release): make the reader proof name the real fault
jaywedgeworth22 Oct 21, 2026
535cd74
fix(release): keep a merge from cancelling another merge's compile run
jaywedgeworth22 Oct 21, 2026
8ef6a7e
release: name the credential fault, and mask the credential in the log
jaywedgeworth22 Oct 21, 2026
7dc639b
release: redact a credential that has no hidden middle
Oct 21, 2026
45911de
release: keep a credential out of the log when the shell would expand it
Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/ios-ship-contract.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ on:
- '.github/workflows/ios-ship*.yml'
- 'ios/CodeCapsCompanion/project.yml'
- 'scripts/ios-*'
- 'scripts/infisical-fetch*.mjs'
- 'scripts/stage-asc-key*'
- 'scripts/ios-fleet/**'
- 'scripts/test-ios-stage-asc-key.sh'
push:
Expand All @@ -22,6 +24,8 @@ on:
- '.github/workflows/ios-ship*.yml'
- 'ios/CodeCapsCompanion/project.yml'
- 'scripts/ios-*'
- 'scripts/infisical-fetch*.mjs'
- 'scripts/stage-asc-key*'
- 'scripts/ios-fleet/**'
- 'scripts/test-ios-stage-asc-key.sh'
workflow_dispatch:
Expand All @@ -42,6 +46,6 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Pin the auto-ship wiring
run: |
node --test scripts/ios-ship-workflow.test.mjs
node --test scripts/ios-ship-workflow.test.mjs scripts/stage-asc-key.node-test.mjs scripts/infisical-fetch-expand.node-test.mjs scripts/ios-enable-apns.test.mjs
bash scripts/ios-fleet/test-asc-credentials.sh
node --test scripts/ios-fleet/test-asc-credentials.mjs
104 changes: 32 additions & 72 deletions .github/workflows/ios-ship.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ name: iOS TestFlight ship (GitHub-hosted macOS)
# Usage-Monitor read it. The same-named repository secrets are a stale
# copy that App Store Connect answers with HTTP 401 (CC-163), so they are
# deliberately not read here and there is no fallback to them.
# * The multiline key never enters GITHUB_ENV: scripts/ios-stage-asc-key.sh
# writes it to a mode-600 file and only the path crosses steps.
# * The multiline key never enters the step environment.
# The tooling and scripts/stage-asc-key.mjs run in one step, so the key
# goes from the fleet's reader straight into a mode-600 file, and only
# that file's path and the two identifiers cross a step boundary.
# * IOS_DIST_P12_BASE64 / IOS_DIST_P12_PASSWORD (Apple Distribution identity)
# stay repository secrets.
# * SENTRY_DSN and SENTRY_AUTH_TOKEN are best-effort: an inert Sentry beats a
Expand Down Expand Up @@ -74,6 +76,8 @@ on:
- '.github/workflows/ios-ship.yml'
- '.github/actions/infisical-secrets/**'
- 'scripts/infisical-fetch.mjs'
- 'scripts/install-release-secrets-tooling.sh'
- 'scripts/stage-asc-key*'
- 'scripts/ios-fleet/**'
- '!scripts/ios-fleet/test-*.sh'
- 'scripts/ios-ship-testflight.sh'
Expand Down Expand Up @@ -212,87 +216,43 @@ jobs:
# ASC key from Fleet-OPS prod /asc. ASC_KEY_ID and ASC_ISSUER_ID are
# single-line and go to GITHUB_ENV; the multiline private key is staged
# to a mode-600 file and only ASC_KEY_PATH is exported.
- name: Load ASC credentials (Fleet-OPS prod /asc)
#
# The tooling and the staging script run in ONE step on purpose. The
# tooling installs the Infisical CLI and the fleet's reader onto the
# runner, mints the access token they use, and runs the staging script
# in the same process tree, so the token never touches a file. The
# staging script is what resolves the three ASC values, and it writes
# the private key to a mode-600 file: the key is never an environment
# variable of a step, and only that file's path and the two identifiers
# cross a step boundary.
#
# The staging script runs even when the install fails, because it is
# what removes any key-bearing entry from the job's environment file,
# and the step reports the status of the command that actually failed.
- name: Load and stage the ASC credentials (Fleet-OPS prod /asc)
env:
ASC_INFISICAL_PROJECT_ID: 8dae6d03-8f12-48b2-adf3-e5c1b881c8c5
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID }}
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET }}
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_CLIENT_ID }}
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_FLEET_OPS_PROJECT_ID }}
INFISICAL_CLIENT_ID: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID || secrets.INFISICAL_CLIENT_ID }}
INFISICAL_CLIENT_SECRET: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET || secrets.INFISICAL_CLIENT_SECRET }}
run: |
set +o xtrace
set -euo pipefail
export INFISICAL_DISABLE_UPDATE_CHECK=true

if ! command -v infisical >/dev/null 2>&1; then
NONINTERACTIVE=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install infisical/get-cli/infisical
fi
command -v infisical >/dev/null 2>&1 || {
echo "::error::Infisical CLI is not installed."
exit 1
}

CLIENT_ID="${INFISICAL_UNIVERSAL_AUTH_CLIENT_ID}"
CLIENT_SECRET="${INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET}"
if [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then
CLIENT_ID="${INFISICAL_CLIENT_ID}"
CLIENT_SECRET="${INFISICAL_CLIENT_SECRET}"
fi
if [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then
echo "::error::Missing Infisical machine identity. Set INFISICAL_UNIVERSAL_AUTH_CLIENT_ID/SECRET (fallback INFISICAL_CLIENT_ID/SECRET) on the org or repo."
exit 1
fi

TOKEN="$(
env -u INFISICAL_CLIENT_ID -u INFISICAL_CLIENT_SECRET -u INFISICAL_TOKEN \
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID="$CLIENT_ID" \
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET="$CLIENT_SECRET" \
infisical login --method=universal-auth --silent --plain --telemetry=false 2>/dev/null || true
)"
if [ -z "$TOKEN" ]; then
echo "::error::Infisical universal-auth login failed."
exit 1
fi
if [[ "$TOKEN" == *$'\n'* || "$TOKEN" == *$'\r'* ]]; then
echo '::error::Infisical returned a multiline token.' >&2
exit 1
fi
printf '::add-mask::%s\n' "${TOKEN//'%'/'%25'}"
bash scripts/install-release-secrets-tooling.sh

- name: Check the ASC credentials arrived
run: |
set +o xtrace
set -euo pipefail
for name in ASC_KEY_ID ASC_ISSUER_ID; do
val="$(
INFISICAL_TOKEN="$TOKEN" infisical secrets get "$name" \
--plain --silent --telemetry=false --expand=false \
--projectId="$ASC_INFISICAL_PROJECT_ID" --env=prod --path=/asc \
2>/dev/null || true
)"
if [ -z "$val" ]; then
echo "::error::Missing $name in Fleet-OPS prod /asc; verify the CI identity has read access to project ${ASC_INFISICAL_PROJECT_ID} path /asc." >&2
if [ -z "${!name:-}" ]; then
echo "::error::Missing $name in Fleet-OPS prod /asc; verify the CI identity has read access to Fleet-OPS prod /asc." >&2
exit 1
fi
if [[ "$val" == *$'\n'* || "$val" == *$'\r'* ]]; then
echo "::error::Signing field $name must be single-line; correct Infisical formatting." >&2
exit 1
fi
printf '::add-mask::%s\n' "${val//'%'/'%25'}"
printf '%s=%s\n' "$name" "$val" >> "$GITHUB_ENV"
done

# Keep the multiline PEM out of GITHUB_ENV and every later step
# environment. Only its mode-600 file path crosses the step boundary.
key_material="$(
INFISICAL_TOKEN="$TOKEN" infisical secrets get ASC_KEY_P8 \
--plain --silent --telemetry=false --expand=false \
--projectId="$ASC_INFISICAL_PROJECT_ID" --env=prod --path=/asc \
2>/dev/null || true
)"
if [ -z "$key_material" ]; then
echo "::error::Missing ASC key material in Fleet-OPS prod /asc; verify the CI identity has read access to project ${ASC_INFISICAL_PROJECT_ID} path /asc." >&2
if [ -z "${ASC_KEY_PATH:-}" ] || [ ! -s "${ASC_KEY_PATH:-}" ]; then
echo '::error::Missing ASC key material in Fleet-OPS prod /asc; verify the CI identity has read access to Fleet-OPS prod /asc.' >&2
exit 1
fi
printf '%s\n' "$key_material" | bash "$GITHUB_WORKSPACE/scripts/ios-stage-asc-key.sh"
unset key_material TOKEN CLIENT_ID CLIENT_SECRET val

- name: Import signing identity
env:
IOS_DIST_P12_BASE64: ${{ secrets.IOS_DIST_P12_BASE64 }}
Expand Down
Loading
Loading