Skip to main content

GitHub Actions

Beta

Being rolled out. The interface described here is the one of the next release: it may still change, and may not be enabled on your tenant yet.

Same principle as for GitLab: the job obtains an OIDC token from GitHub, the CLI exchanges it for a tenant session. No secret in the repository secrets.

Prerequisites​

sng tenant oidc create github-deploy \
--github-repo acme/infra --ref main \
--claim repository_id=123456789
sng tenant policy attach readwrite --oidc-trust github-deploy

sng tenant oidc create github-review --github-repo acme/infra --ref '*' --claim repository_id=123456789
sng tenant policy attach readonly --oidc-trust github-review

The repository ID can be read with gh api repos/acme/infra --jq .id.

Pull requests

The sub of a token issued for a pull request is repo:acme/infra:pull_request, not a branch. To validate PRs, add a trust with --subject 'repo:acme/infra:pull_request' or use --ref '*' and accept that PRs share the review trust.

Install the CLI in the workflow​

Since binaries are not published yet, the workflow builds the CLI from source. The sng-cli repository is private: you need a read access token for the repository, stored as a GitHub secret (SNG_CLI_TOKEN). It is the only secret of the workflow, and it grants no rights on your tenant.

.github/workflows/deploy.yml
name: deploy
on:
push:
branches: [main]
pull_request:

permissions:
id-token: write # the job can request an OIDC token
contents: read

env:
STNG_TENANT: acme
STNG_OIDC_AUDIENCE: https://api.dev.stackngo.fr

jobs:
sng:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.27"
- name: Build sng
run: |
git clone --depth 1 "https://oauth2:${{ secrets.SNG_CLI_TOKEN }}@gitlab.com/stackngo/sng-cli.git" /tmp/sng-cli
make -C /tmp/sng-cli build
sudo install /tmp/sng-cli/bin/sng /usr/local/bin/sng
sng config create

- name: Validate
run: |
sng validate infra/
sng plan infra/

- name: Deploy
if: github.ref == 'refs/heads/main'
env:
STNG_OIDC_TRUST: github-deploy
run: |
sng apply infra/
sng app describe api

Under GitHub Actions, the CLI reads ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN, provided by the runner when permissions: id-token: write is present, and itself requests a token with audience STNG_OIDC_AUDIENCE each time it opens a session.

Wait for convergence​

- name: Wait for Ready
if: github.ref == 'refs/heads/main'
run: |
for i in $(seq 1 30); do
if sng app describe api --json | jq -e '.ready' >/dev/null; then exit 0; fi
sleep 10
done
sng app describe api; exit 1

Useful variables​

VariableRole
STNG_TENANTTarget tenant (required)
STNG_OIDC_AUDIENCEAudience of the token requested from GitHub (default: the API URL)
STNG_OIDC_TRUSTDisambiguates if several trusts match
STNG_CLUSTERAlternative to sng config use-cluster

Troubleshooting​

  • no CI OIDC token: permissions: id-token: write is missing from the workflow or the job.
  • 401 invalid identity token: the sub (repo:acme/infra:ref:refs/heads/feature-x, repo:acme/infra:pull_request) matches no trust. sng tenant oidc get shows the expected pattern.
  • 403 forbidden on apply: STNG_OIDC_TRUST points to the readonly trust.
  • A fork does not receive an OIDC token for PRs: this is a GitHub protection, not a StackNGO one.

See also​