> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions

> Federate GitHub Actions OIDC tokens into short-lived TrueFoundry access tokens for CI.

Every GitHub Actions job can request a signed OIDC JWT from `https://token.actions.githubusercontent.com`. With Workload Identity Federation, the job exchanges that JWT for a short-lived TrueFoundry access token — no long-lived Virtual Account token stored as a repository secret.

TrueFoundry requires a `repository` claim match on the Virtual Account **Claims** (or Agent **Subject**) mapping.

For concepts and the shared exchange API, see [Workload Identity Federation](https://www.truefoundry.com/docs/platform/identity-providers/workload-identity-federation/overview.md).

## Prerequisites

* A GitHub repository where you can edit workflows and grant `id-token: write`.
* A [Virtual Account](https://www.truefoundry.com/docs/platform/virtual-account-management.md) or Agent with the permissions the job needs.

## Configure the workflow

GitHub only issues an identity token when the job requests it:

```yaml theme={"dark"}
permissions:
  id-token: write
  contents: read
```

Fetch a token with the audience you will register on TrueFoundry (for example `truefoundry`):

```yaml theme={"dark"}
- name: Fetch GitHub OIDC token
  run: |
    curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
      "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=truefoundry" \
      | jq -r .value > "$RUNNER_TEMP/gha-jwt"
```

Or with `actions/github-script`:

```yaml theme={"dark"}
- name: Fetch GitHub OIDC token
  uses: actions/github-script@v7
  with:
    script: |
      const fs = require('fs');
      const token = await core.getIDToken('truefoundry');
      fs.writeFileSync(`${process.env.RUNNER_TEMP}/gha-jwt`, token);
```

Typical claims on the JWT:

```json theme={"dark"}
{
  "iss": "https://token.actions.githubusercontent.com",
  "aud": "truefoundry",
  "sub": "repo:your-org/your-repo:ref:refs/heads/main",
  "repository": "your-org/your-repo",
  "repository_owner": "your-org",
  "ref": "refs/heads/main"
}
```

## Configure TrueFoundry

1. **Settings > Security & Access > Identity Providers** → add provider type **GitHub**.
2. Set:

| Field | Value |
| - | - |
| Issuer URL | `https://token.actions.githubusercontent.com` |
| Allowed Audiences | Same audience you requested (for example `truefoundry`) |
| JWKS URI | `https://token.actions.githubusercontent.com/.well-known/jwks` |

3. Map the Virtual Account (or Agent):

**Virtual Account — Claims**

```yaml theme={"dark"}
identity_provider_mapping:
  - identity_provider: github-actions
    claims:
      repository: your-org/your-repo
```

**Agent — Subject** (YAML key is still `claims`)

```yaml theme={"dark"}
identity:
  type: identity-provider-backed
  identity_provider_mapping:
    - identity_provider: github-actions
      claims:
        repository: your-org/your-repo
```

Required key for `github`: `repository`. You may add further claim matches (for example `ref`) when your token includes them and you want to pin them.

## Exchange and call TrueFoundry

```yaml theme={"dark"}
- name: Exchange for TrueFoundry token
  env:
    # Issuer origin; exchange path is /{tenant}/oauth2/v1/token (no /api/svc)
    TFY_CONTROL_PLANE: https://<tenant-host-origin>
    TFY_TENANT: <tenant>
  run: |
    WORKLOAD_JWT=$(cat "$RUNNER_TEMP/gha-jwt")
    curl -sS "$TFY_CONTROL_PLANE/$TFY_TENANT/oauth2/v1/token" \
      -H 'Content-Type: application/json' \
      -d "{
        \"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\",
        \"subject_token\": \"$WORKLOAD_JWT\",
        \"subject_token_type\": \"urn:ietf:params:oauth:token-type:jwt\",
        \"tfy_subject\": \"virtual_account:<virtual-account-name>\"
      }" > "$RUNNER_TEMP/tfy-token.json"
    echo "TFY_ACCESS_TOKEN=$(jq -r .access_token "$RUNNER_TEMP/tfy-token.json")" >> "$GITHUB_ENV"
```

Use `TFY_ACCESS_TOKEN` as `Authorization: Bearer` against the [AI Gateway](https://www.truefoundry.com/docs/ai-gateway/authentication.md) or APIs. For Agents, set `tfy_subject` to `agent:<agent-name>`. Full exchange details: [Workload Identity Federation](https://www.truefoundry.com/docs/platform/identity-providers/workload-identity-federation/overview.md#exchange-the-platform-jwt).

## Scope the mapping

* Prefer `repository: your-org/your-repo` over a broad org-wide pattern.
* Add optional claim matches (for example a protected branch `ref`) when only specific workflows should authenticate.
* Do not store a long-lived VAT in GitHub Secrets when federation is available.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.