In Codemagic, what are environment variable groups, and how should a codemagic.yaml workflow receive secrets such as a Google Play service-account key?
answer
- named sets imported together
- team-level versus application-level
- Secret checkbox encrypts
- binary files need base64
- same names, different groups
basics
~20 sCodemagic environment variable groups are named sets of variables defined in team or application settings, marked Secret to encrypt them, and imported by name under environment.groups. Binary files are base64-encoded before storing and decoded during the build.
solid answer
~50 sSecrets never go in the committed file. You add a variable in the Codemagic UI, give it a **group** name and tick **Secret**, which encrypts it and hides the value in the UI. The workflow imports the whole group with `environment.groups: [google_credentials]` and scripts read `$GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS`. Groups live either in **team settings** (global, usable by every app unless limited through Application access) or in an **application's** settings. Variables defined in the UI must belong to a group. Because two groups can hold the same names, a `staging` and a `production` group let identical scripts run with different values depending on which group a workflow imports. Text secrets such as the service-account JSON or a `.p8` key are pasted as-is; binary files such as a keystore or `.p12` must be base64-encoded first and decoded in a script. `environment.vars` is only for public values.
code
yaml · 17 linesworkflows:
android-release:
name: Scooter Android release
environment:
groups:
- google_credentials
- production
vars:
PACKAGE_NAME: "com.example.scooter"
scripts:
- name: Restore Firebase config
script: |
echo $ANDROID_FIREBASE_SECRET | base64 --decode > $CM_BUILD_DIR/android/app/google-services.json
publishing:
google_play:
credentials: $GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS
track: internalgo deeper
Remember that secrets go into Secret variables in the Codemagic UI and a workflow imports them through environment.groups.
Explain team versus application groups, base64 for binary files, and how same-named variables in two groups switch environments.
Lay out groups so production credentials reach only release workflows and apps that need them, and prefer code signing identities for signing files.
Decide how credentials are owned, scoped and rotated across many apps and teams sharing one Codemagic account.
## Why groups exist A Codemagic workflow needs credentials: a Google Play service account, App Store Connect API values, Firebase files, a token for a private Git dependency. Committing them to `codemagic.yaml` would expose them to everyone with repository access. Codemagic stores them in its UI instead, organised into **environment variable groups**, and the file references groups only by name. A **group** tags a set of related variables so they can be imported in one step. Codemagic's docs state that environment variables defined in the app settings must belong to a group. ## Where groups are defined | Level | Defined in | Visible to | |---|---|---| | Team (global) | Team settings, Global variables and secrets | Every app of the team, unless limited under Application access | | Application | The app's Environment variables tab | Every `codemagic.yaml` workflow of that app | | Workflow | `environment.vars` in the file | That workflow only; public values only | A credential shared by all of a team's apps, such as an App Store Connect key, fits a global group; a Play service account for one app fits that app's group. ## Importing a group ```yaml environment: groups: - google_credentials - scooter_production vars: PACKAGE_NAME: "com.example.scooter" ``` Every variable in the listed groups becomes an environment variable for the build, so a script or a publishing field reads `$GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS`. Built-in read-only variables sit alongside them: `CI` is `true`, `BUILD_NUMBER` counts builds of this workflow, `PROJECT_BUILD_NUMBER` counts builds of the project, and `CM_BUILD_DIR` is the clone directory. ## Secret values and binary files - Ticking **Secret** encrypts the value and obfuscates it in the UI. - **Text** secrets, like a service-account JSON or the contents of an App Store Connect `.p8` key, are pasted as they are, including their begin and end lines. - **Binary** files, like an Android keystore, a `.p12` certificate or a `.mobileprovision` profile, must be **base64-encoded** locally before pasting and decoded in a script with `echo $VAR | base64 --decode > /path/file`. For signing files there is now a better home than a base64 variable: the team's **Code signing identities**, referenced through `android_signing` and `ios_signing`. Base64 variables remain the manual fallback. ## The documented variable names Codemagic's samples and CLI tools expect certain names, and sticking to them saves wiring: | Variable | Holds | Typical group | |---|---|---| | `GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS` | Service-account JSON for Play publishing | `google_credentials` | | `APP_STORE_CONNECT_ISSUER_ID` | Issuer ID of the API key | `appstore_credentials` | | `APP_STORE_CONNECT_KEY_IDENTIFIER` | Key ID of the API key | `appstore_credentials` | | `APP_STORE_CONNECT_PRIVATE_KEY` | Contents of the `.p8` file | `appstore_credentials` | | `CERTIFICATE_PRIVATE_KEY` | Private key for CLI-based automatic signing | `appstore_credentials` | | `CM_KEYSTORE`, `CM_KEYSTORE_PASSWORD`, `CM_KEY_ALIAS`, `CM_KEY_PASSWORD` | Manual Android signing values | `keystore_credentials` | Storing related variables in the same group means one line under `groups` brings the whole set. When the Apple Developer Portal **integration** is used instead, the App Store Connect variables are not needed at all: the workflow names the key under `integrations`. ## One script, several environments Groups can reuse variable names. A `staging` group and a `production` group can both define `API_BASE_URL` and `FLEET_API_TOKEN`; which one a build sees depends only on the group its workflow imports. That keeps scripts identical across a staging workflow and a production workflow of the scooter app. ## Traps 1. Putting a password under `environment.vars` commits it to Git. 2. Forgetting to import the group: the variable exists in the UI but is empty in the build. 3. In a workflow's `when.condition`, variables are read as `env.NAME`; shell syntax `$NAME` is not supported there. 4. Pasting a binary keystore without base64 corrupts it. Groups are Codemagic's answer to secret handling; general secret-management principles belong to CI concepts, but these keys and their rules are what an interviewer checks.
- How do you limit a Codemagic team-level variable group to certain apps?Global groups defined in team settings are usable by every app of the team by default. Editing the group's **Application access** restricts it to the applications you pick, which keeps one app's production credentials out of another app's builds.
- Why might a Codemagic build see an empty value for a variable you added in the UI?The workflow must import the variable's group under `environment.groups`; UI variables are not injected otherwise. Also check the group name's spelling and, for a global group, that Application access includes this app.
Variable groups work like labelled key rings at a front desk. A staging ring and a production ring carry keys with the same labels that open different doors; a workflow signs out a ring by name, and the ring it takes decides which doors its scripts can open.
saying these in an interview costs you the question
- Secrets can live under environment.vars because the repository is private
- A keystore can be pasted into a secret variable without encoding
- UI variables reach every workflow without importing their group
- Two variable groups cannot define a variable with the same name
- A when condition reads variables with shell syntax like $NAME