Skip to content

Adopt a8c-secrets in WordPress iOS#25772

Open
mokagio wants to merge 16 commits into
trunkfrom
ainfra-1538-adopt-the-solution-in-wordpress-ios
Open

Adopt a8c-secrets in WordPress iOS#25772
mokagio wants to merge 16 commits into
trunkfrom
ainfra-1538-adopt-the-solution-in-wordpress-ios

Conversation

@mokagio

@mokagio mokagio commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Description

Migrate the WordPress/Jetpack iOS secrets store off .configure/mobile-secrets onto a8c-secrets (AINFRA-1538), part of the fleet-wide rollout. wpios is outside-only, so this is a decrypt-mechanism swap — no app-code changes.

The branch opens with a tidy (Extract secret install into shared script) that centralised the ~17 configure_apply call sites into .buildkite/commands/install-secrets.sh, so the mechanism swap here touches that one file instead of every pipeline. The build phase now reads the three Swift secrets from ~/.a8c-secrets/<repo-id>/ (decrypted from the committed *.age blobs), and a new configure_secrets fastlane lane wraps a8c-secrets decrypt behind a tool preflight.

Follows the woocommerce-ios (AINFRA-1534) and pocket-casts-ios (AINFRA-1541) adoptions, carrying over the pcios refinements: FastlaneCore::CommandExecutor.which, the is_ci graceful-skip, and a before_all decrypt.

Validated in CI

Build #33110 is green (26/26). The build-for-testing log confirms the full path on real agents: install a8c-secretsa8c-secrets decrypt writes the three secrets to ~/.a8c-secrets/wordpress-ios@github.com@wordpress-mobile/ → the build reads them and compiles. A8C_SECRETS_IDENTITY is already provisioned on the agents (the decrypt succeeded), so there is no outstanding provisioning work.

Gotchas

  • Stacked on ainfra-2643-... — merge that first; this PR targets it, not trunk.
  • The before_all decrypt must skip in CI: install-secrets.sh exports a8c-secrets onto PATH in its own process, which does not reach the later fastlane build_* process, so an unguarded decrypt hard-fails every CI build (pcios probe My Profile Network logic #4732). The is_ci branch handles this — confirmed firing in #33110 with the AINFRA-2681 message, the secrets already on disk from install-secrets.sh.

How to test

bundle exec fastlane configure_secrets locally (with the dev age identity imported) decrypts the three files into ~/.a8c-secrets/wordpress-ios@github.com@wordpress-mobile/. CI exercises the CI path end-to-end (see build #33110).

mokagio and others added 7 commits July 12, 2026 15:41
Wraps `Xcodeproj::Config` with the error handling its raw API lacks: a
missing file, a missing key, and a key set to an empty value all raise
rather than silently yielding `nil`.

Uses `to_hash` rather than `attributes`, since the latter only sees the
settings assigned in the file itself, not those it pulls in via
`#include`.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`INT_EXPORT_TEAM_ID` duplicated a value the project already declares:
enterprise and prototype builds use the `Release-Alpha` configuration,
whose `DEVELOPMENT_TEAM` is set in `config/Common.alpha.xcconfig`.
Reading it from there removes one secret from the environment the
tooling needs to be handed.

Note the value also lives in `project.env` in the `mobile-secrets`
repository, where it now has no consumer.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Same reasoning as the internal team ID in the previous commit:
`EXT_EXPORT_TEAM_ID` duplicated the `DEVELOPMENT_TEAM` that
`config/Common.release.xcconfig` already declares for the App Store
builds, which use the `Release` configuration.

With both gone, `project.env` no longer has to carry either team ID.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both call sites authenticate with `api_key`, and pilot only ever reads
`team_id` on the username/password Spaceship path — see
`pilot/lib/pilot/manager.rb:36`, the sole reader of `config[:team_id]` in
the whole of `pilot/lib`, which sits in the `else` branch that an API
token skips.

An App Store Connect API key is issued by a single team, so there is no
team left to disambiguate. `woocommerce-ios` has shipped its TestFlight
uploads without the parameter for this reason.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every key it carried is now unused: the two export team IDs come from
`xcconfig`, `FASTLANE_ITC_TEAM_ID` was inert alongside an `api_key`, the
Sentry slugs are hardcoded constants in `build.rb`, and the two HockeyApp
IDs outlived the service.

With nothing reading the file, the `before_all` guard demanding it had no
purpose either — which is what the three CI scripts were copying the
example file to satisfy. `configure_apply` creates its destination
directory itself, so nothing else needed that block.

The file still exists in `mobile-secrets`, where it can now be deleted.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Centralize the `configure_apply` invocation, duplicated across 12 command
scripts and 5 release pipelines, into `install-secrets.sh`.
The upcoming move to a8c-secrets then swaps a single call site instead of
seventeen.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 12, 2026 05:49
@mokagio
mokagio requested a review from a team as a code owner July 12, 2026 05:49
@mokagio mokagio self-assigned this Jul 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR deduplicates the Buildkite “install CI secrets” step by extracting the repeated bundle exec fastlane run configure_apply invocation into a shared script, so the upcoming secrets migration can be done by updating a single file.

Changes:

  • Introduces .buildkite/commands/install-secrets.sh to centralize secrets installation.
  • Updates Buildkite command scripts and release pipelines to call the shared script instead of inlining the Fastlane step.
  • Unifies pipeline log labeling around “Installing Secrets”.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.buildkite/release-pipelines/update-app-store-strings.yml Swaps inline secrets install for shared script call in the pipeline command block.
.buildkite/release-pipelines/publish-release.yml Swaps inline secrets install for shared script call in the pipeline command block.
.buildkite/release-pipelines/new-hotfix.yml Swaps inline secrets install for shared script call in the pipeline command block.
.buildkite/release-pipelines/new-beta-release.yml Swaps inline secrets install for shared script call in the pipeline command block.
.buildkite/release-pipelines/code-freeze.yml Swaps inline secrets install for shared script call in the pipeline command block.
.buildkite/commands/release-build-wordpress.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/release-build-jetpack.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/prototype-build-wordpress.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/prototype-build-jetpack.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/promote-nightly.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/promote-build-to-public.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/install-secrets.sh New shared script that performs the secrets install via Fastlane with a consistent log label.
.buildkite/commands/gather-testflight-candidates.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/finalize-release.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/finalize-hotfix.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/complete-code-freeze.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/build-for-testing.sh Replaces duplicated secrets install lines with shared script invocation.
.buildkite/commands/build-and-upload-testflight.sh Replaces duplicated secrets install lines with shared script invocation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .buildkite/release-pipelines/update-app-store-strings.yml Outdated
@wpmobilebot

wpmobilebot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor
App Icon📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack
ConfigurationRelease-Alpha
Build Number33224
VersionPR #25772
Bundle IDcom.jetpack.alpha
Commit4346fee
Installation URL6ir6hdabtu0mo
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

wpmobilebot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor
App Icon📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress
ConfigurationRelease-Alpha
Build Number33224
VersionPR #25772
Bundle IDorg.wordpress.alpha
Commit4346fee
Installation URL22r9n69977s5o
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

mokagio and others added 5 commits July 12, 2026 16:31
Swap the secrets store from `.configure`/`.configure-files` to `.a8c-secrets`,
tracking the encrypted `*.age` blobs alongside the already-committed repo id
and public keys, and updating the `.gitignore` allowlist, `.gitattributes`,
and `CODEOWNERS` to match.

Part of AINFRA-1538.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Read the three secrets from the a8c-secrets decrypt location
(`~/.a8c-secrets/<repo-id>/`) instead of `~/.configure/`, and point the
fallback message at the new `configure_secrets` lane.

Part of AINFRA-1538.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Decrypt secrets via `a8c-secrets` behind a preflight that points at the
installer when the tool is missing, and call it from `before_all` so every
lane can rely on the secrets being present.

In CI the binary isn't on the lane process's PATH — install-secrets.sh
decrypts in its own process — so the preflight detects CI and skips rather
than failing the build.

Part of AINFRA-1538.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point the shared `install-secrets.sh` helper and the `credentials:apply`
Rake task at `a8c-secrets`: the helper installs the tool and runs
`configure_secrets` in one process so the PATH export reaches the decrypt,
and the Rake task guards on the tool being installed so open-source builds
fall back to templated credentials.

The Buildkite command scripts and release pipelines already route through
`install-secrets.sh`, so no call sites change here.

Part of AINFRA-1538.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mokagio mokagio changed the title Extract CI secret install into a shared script Adopt a8c-secrets in WordPress iOS Jul 12, 2026
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment thread .a8c-secrets/keys.pub
# dev
age1srcq3hl92ym9jk3ezj5prwhche3w8szc0cssy8t7afrkjmtkxu2qkjsdfn
# ci
age1a7xcr6qzwnzgcxq95sq33p58xdzsmful8w7mp2zktvuy5434yuss9rmv8f

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI public key validated by using age-keygen -y on the private key stored in our CI secrets 👍

Comment on lines +6 to +8
curl -fsSL https://raw.githubusercontent.com/Automattic/a8c-secrets/main/install.sh | bash
# The installer puts the binary in ~/.local/bin, which isn't on the agent's PATH.
export PATH="$HOME/.local/bin:$PATH"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that in the future we plan to have a8c-secrets pre-installed and provisionned on all of our CI agents.
We're not there yet so for the iterative migration we might still need this curl and export PATH calls indeed, but that's good to keep in mind and track in some Linear issue to remember to follow-up on this later.

Alternatively, maybe we could start deploying the a8c-secrets (and PATH addition) to our CI agents first, so that PRs that will start to adopt it don't have to do that curl themselves already?

Comment on lines -3 to +5
${HOME}/.configure/wordpress-ios/secrets/WordPress-Secrets.swift
${HOME}/.configure/wordpress-ios/secrets/WordPress-Secrets-Internal.swift
${HOME}/.configure/wordpress-ios/secrets/WordPress-Secrets-Alpha.swift
${HOME}/.configure/wordpress-ios/secrets/Jetpack-Secrets.swift
${HOME}/.configure/wordpress-ios/secrets/Reader-Secrets.swift
${HOME}/.a8c-secrets/wordpress-ios@github.com@wordpress-mobile/WordPress-Secrets.swift
${HOME}/.a8c-secrets/wordpress-ios@github.com@wordpress-mobile/Jetpack-Secrets.swift
${HOME}/.a8c-secrets/wordpress-ios@github.com@wordpress-mobile/Reader-Secrets.swift

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that the 3 .swift files that were previously split per configuration (Secrets/Secrets-Internal/Secrets-Alpha) for the WordPress target are now unified into a single one, not making the distinction anymore?

I looked at the current 3 files in our ~/.mobile-secrets (the ones used by configure_apply currently) and their content seem to be distinct for all 3:

  • Mostly the same between Secrets.swift and Secrets-Alpha.swift… except a different SentryDSN
  • Different SentryDSN but also different ClientID for Internal

So in practice this migration to have a single WordPress-Secrets.swift file for all 3 Xcode configurations of the WordPress target changes this behavior. Just wanted to check if this was intentional and had been discussed with the team (e.g. we wouldn't want crashes from Internal and Alpha to be reported in the same Sentry project as prod)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok reading the current content of the GenerateCredentials.sh script file I see that maybe the Secrets-Internal and Secrets-Alpha files were in practice never used (never copied by the script in the first place)? Or am I missing something? Or maybe this has been the case for ages and we never cleaned things up?
(I couldn't find a mention of this important gotcha in the PR description, so asking here so we can confirm a common understanding to be sure)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need any of the differentiated secrets files – everything can use the same credentials.

Base automatically changed from ainfra-2643-remove-unused-env-vars-from-wordpress-ios-tooling to trunk July 18, 2026 02:53
Resolve secrets-install conflicts in favor of the `a8c-secrets`
migration: `build-for-testing.sh` keeps `install-secrets.sh`,
`Fastfile` keeps the `configure_secrets` lane, and `.configure`
stays deleted.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dangermattic

dangermattic commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator
1 Warning
⚠️ This PR is assigned to the milestone 27.1. This milestone is due in less than 4 days.
Please make sure to get it merged by then or assign it to a milestone with a later deadline.

Generated by 🚫 Danger

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants