⚠️ Important: Starting from version 2.x, a custom container is required. The Dockerfile can be found in.github/images/aio-mesh-runner/Dockerfile. If you prefer to use a standard GitHub runner without a custom container, please use version 1.x of this template.
This repository is a lightweight starting point for teams that want a repeatable GitHub Actions pipeline for provisioning and updating Adobe API Mesh configurations. Fork it, drop in your mesh definition files, wire up the required Adobe Developer Console credentials, and you will have a push-button deployment path for staging and production meshes.
- Workflow automation –
.github/workflows/deploy.yamlhandles checkout, authentication via the Adobe I/O CLI, mesh creation (or update), and post-deploy validation. - Environment awareness – pushes to
stagingorproductionautomatically pull the corresponding credential set and workspace identifiers. - Manual control – trigger the workflow with
workflow_dispatchwhenever you need an ad-hoc deployment. - Extensibility – add new environments, steps, linters, or notifications by extending the single workflow file.
- Dynamic
.envinjection – GitHub repository variables (ENV_STAGE,ENV_PROD) can store full.envpayloads, and the workflow materializes them into a runtime.envbefore invoking the API Mesh CLI. - Secret materialization – branch-specific secrets can include encrypted mesh credentials (
MESH_SECRETS_*) that the workflow writes tosecrets.yamlon the fly and passes through--secretsso sensitive resolvers stay out of Git history. - Auto-flag builder – the workflow inspects the repo for
.envandsecrets.yamland automatically appends the correctaio api-mesh:*flags, helping you wire runtime configuration consistently. - Provisioning watchdog – mesh deployments poll
aio api-mesh:statusfor up to 10 minutes with friendly logging, failing early if provisioning stalls or ends unexpectedly. - Reusable testing workflow –
.github/workflows/tests.yamldefines a Newman-based regression suite that runs after deployment (via thetestsjob indeploy.yaml) and selects the right Postman environment per branch.
Repository layout (expected):
.
├── .github/workflows/deploy.yaml # Main CI/CD pipeline
├── .github/workflows/tests.yaml # Reusable Newman regression tests
├── mesh.json # API Mesh definition (commit your own)
├── .env # Optional runtime variables used by mesh.json
└── README.md # This documentation
Tip: keep secrets out of
mesh.jsonand.env. Use GitHub Encrypted Secrets wherever possible.
- Adobe Developer Console access with permissions to the target organization, project, and workspaces that host your meshes.
- Mesh definition files (
mesh.jsonplus any schema/resolver files) committed to the repository. - GitHub repository admin rights to configure Actions secrets and branch protection rules.
- Node.js 20.x compatibility for any local development or custom steps (the workflow pins Node 20 via the matrix but can be adjusted).
- Adobe I/O CLI knowledge (
aio) in case you want to run the same commands locally for troubleshooting.
Configure the following secrets under Settings → Secrets and variables → Actions in your fork. Stage/prod secrets allow the workflow to decide which credentials to use based on the branch being deployed.
| Secret Name | When Used | Description |
|---|---|---|
CLIENTID_STAGE, CLIENTSECRET_STAGE, TECHNICALACCID_STAGE, TECHNICALACCEMAIL_STAGE, WORKSPACEID_STAGE |
Pushes to staging |
OAuth client + technical account bound to your staging workspace. Workspace project > workspace > id from workspace.json |
CLIENTID_PROD, CLIENTSECRET_PROD, TECHNICALACCID_PROD, TECHNICALACCEMAIL_PROD, WORKSPACEID_PROD |
Pushes to production |
Production equivalents of the above credentials. Workspace: project > workspace > id from workspace.json |
IMSORGID |
Both | ims_org_id from workspace.json |
ORGID |
Both | project > org > id from workspace.json |
PROJECTID |
Both | project > id from workspace.json |
Add any extra secrets referenced by your mesh (for custom resolvers, HTTP headers, etc.) and load them via environment variables or additional steps in the workflow.
| Variable Name | When Used | Description |
|---|---|---|
ENV_STAGE |
Pushes to staging |
Full contents of the .env file you want the staging deployment to consume (multi-line values supported). |
ENV_PROD |
Pushes to production |
Production .env payload, typically mirroring secure resolver configuration for production meshes. |
If these variables are present, the workflow writes them to .env before running aio api-mesh:*. If they are empty, the pipeline falls back to any .env file committed in the repository or skips the flag entirely.
This template is designed to run the deploy workflow inside a lightweight Docker image that already contains Node.js 20.x and the Adobe AIO CLI, but does not bake in the API Mesh plugin. The plugin is installed on each run inside the GitHub Actions job so that it is always available under the correct $HOME and CLI config scope.
Dockerfile used by the workflow:
FROM node:20-bullseye-slim
RUN apt-get update && apt-get install -y \
git \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN npm install -g @adobe/aio-cli && \
npm cache clean --force && \
rm -rf /root/.npm /tmp/*
WORKDIR /workspace
Build and push the AMD64 image:
docker buildx build \
--platform linux/amd64 \
-t ghcr.io/<org-or-user>/aio-mesh-runner:latest \
--push \
-f .github/images/aio-mesh-runner/Dockerfile .
Reference it in deploy.yaml:
jobs:
deploy:
runs-on: ${{ matrix.os }}
container:
image: ghcr.io/<org-or-user>/aio-mesh-runner:latest
strategy:
matrix:
node-version: ["20"]
os: [ubuntu-latest]
# ...
The API Mesh plugin (@adobe/aio-cli-plugin-api-mesh) is not installed in the Docker image. Instead, the workflow installs it inside the job, for example:
- name: Install API Mesh plugin
run: aio plugins:install @adobe/aio-cli-plugin-api-mesh
This is required because:
- AIO plugins are resolved per user via the CLI config directory under
$HOME(for example~/.config/@adobe/aio), not from a global shared path. - In GitHub container jobs, the runner forcibly sets
HOME=/github/home, which is different from theHOMEused at image build time (typically/root). - If the plugin is only installed during
docker build, it ends up wired to the build-time home and config; when the job runs withHOME=/github/home,aiodoes not see those plugins andaio api-mesh:*commands fail.
By installing @adobe/aio-cli-plugin-api-mesh inside the GitHub Actions job (with the final $HOME already set by the runner), the CLI always discovers the plugin correctly, regardless of how the container image was built.
If you do not have such a runner image, use the 1.x version of this template, where:
- The job runs directly on
ubuntu-latest(nocontainer: stanza). aioand the API Mesh plugin are installed inside the workflow steps (for example usingadobe/aio-cli-setup-actionplus an explicitaio plugins:install @adobe/aio-cli-plugin-api-mesh).
In short:
- 2.x template – requires a prebuilt runner image with
aio; no CLI installation steps in the workflow. - 1.x template – no custom image required; CLI and plugin are installed at runtime in the job, which is slower but does not depend on Docker image management.
- Fork this repo or use it as a template inside your organization.
- Add your mesh files:
- Place the primary mesh definition in
mesh.json. - Commit any supporting schemas/resolvers alongside it.
- Provide runtime configuration via Git-tracked
.envfiles or populate theENV_STAGE/ENV_PRODGitHub variables with the exact.envcontent you want injected per environment.
- Place the primary mesh definition in
- Populate GitHub Secrets with the values listed above.
- Adopt the branch convention:
- Push or merge to
stagingfor deploying to staging Adobe workspaces. - Push or merge to
productionfor production deployments.
- Push or merge to
- Run the pipeline:
- Commit changes and push to the target branch.
- Or open the Actions tab, select Deploy Mesh, and click Run workflow (specify the target branch).
Once the workflow succeeds, your Adobe API Mesh instance will be created (if missing) or updated using the latest mesh.json contents, then described and queried for status to confirm a healthy deployment.
- Checkout & Node setup – pulls repository code and provisions Node 20 on
ubuntu-latest. - Branch-aware env mapping – resolves GitHub secrets to runtime variables (
TARGET_ENV,CLIENTID, etc.). Onlystagingandproductionare allowed to prevent accidental deployments from other branches. - Secret validation – fails fast if any required value is missing.
- Adobe I/O CLI bootstrap – installs
aioplus the API Mesh plugin (@adobe/aio-cli-plugin-api-mesh). - Authentication & targeting – performs
oauth_sts, selects the right org/project/workspace, and prints the CLI config for traceability. - Mesh lifecycle – runs
aio api-mesh:get; if no mesh exists it callsapi-mesh:create, otherwiseapi-mesh:update, then waits briefly, describes the mesh, and fetches status.
Extend or reorder steps as needed (e.g., run linting/tests before deployment, send Slack notifications after success, etc.).
- Additional environments – duplicate the branch/secrets mapping block and add new branches like
qaordevwith their own credential sets. - Matrix changes – adjust
matrix.node-versionorosif you need different runtimes. - Multiple meshes – add extra steps to iterate over multiple
mesh.jsonfiles or parameterize the mesh name via.envvalues. - Observability – append steps that push deployment metadata to your logging/monitoring stack.
When editing deploy.yaml, keep the secret-validation step up to date so failures happen quickly.
If you mirror the GitHub secrets as local environment variables you can run the same commands for smoke tests:
npm install -g @adobe/aio-cli
aio plugins:install @adobe/aio-cli-plugin-api-mesh
aio console:org:select <ORGID>
aio console:project:select <PROJECTID>
aio console:workspace:select <WORKSPACEID>
aio api-mesh:update -c mesh.json --env .envThis makes it easier to debug mesh misconfigurations before committing.
- Unsupported branch error – ensure you are pushing to
stagingorproduction, or extend the branch mapping block for additional environments. - Secret validation failure – confirm every secret listed earlier is present; GitHub scope is repository-level by default.
- CLI auth issues – verify the OAuth client has
oauth_stspermissions and the scopes defined in the workflow. - Mesh update fails – inspect the workflow logs around
aio api-mesh:updatefor schema/validation errors; run the same command locally with--verbosefor more detail.
- Protect the
productionbranch to require PR reviews before deployment. - Wire Slack/Teams notifications by adding an extra step after
Get Mesh Status. - Version your mesh definitions (e.g., tag releases) so you can roll back quickly if needed.
Happy shipping!