Problem
The GitHub emulator implements Actions secrets, but not Actions variables. Tools that configure a repository often write both. Code that reads configuration from variables, such as an allowlist stored in an organization variable, receives 404 from the emulator. Verified on main at b75beb7 with npx emulate@0.13.0.
Reproduction
Seed octocat/hello-world, an organization my-org with octocat as an admin member, a repository my-org/org-repo, and a repro_token for octocat. Start the GitHub service:
npx emulate@0.13.0 start --service github --port 4001 --seed emulate.config.yamlcurl -s -i -X POST http://localhost:4001/repos/octocat/hello-world/actions/variables \
-H 'Authorization: Bearer repro_token' -H 'Content-Type: application/json' \
-d '{"name":"MY_VAR","value":"one"}'
curl -s -i http://localhost:4001/repos/octocat/hello-world/actions/variables -H 'Authorization: Bearer repro_token'
curl -s -i http://localhost:4001/orgs/my-org/actions/variables -H 'Authorization: Bearer repro_token'
curl -s -i http://localhost:4001/repos/my-org/org-repo/actions/organization-variables -H 'Authorization: Bearer repro_token'Each request returns:
HTTP/1.1 404 Not Found
{"message":"Not Found","documentation_url":"https://emulate.dev/github"}Secrets endpoints on the same repository succeed. The failure is specific to variables.
GitHub behavior
Repository variables:
| Method and path | Result |
|---|---|
GET /repos/{owner}/{repo}/actions/variables | 200 with { total_count, variables: [{ name, value, created_at, updated_at }] }, paginated with per_page (max 30) and page |
POST /repos/{owner}/{repo}/actions/variables | 201 |
GET /repos/{owner}/{repo}/actions/variables/{name} | 200 with the variable, 404 if absent |
PATCH /repos/{owner}/{repo}/actions/variables/{name} | 204; accepts name (rename) and value |
DELETE /repos/{owner}/{repo}/actions/variables/{name} | 204 |
GET /repos/{owner}/{repo}/actions/organization-variables | 200 with the organization variables this repository can use |
Organization variables use the corresponding paths under /orgs/{org}/actions/variables. Payloads accept visibility (all, private, or selected) and selected_repository_ids. Organization variables also provide selection endpoints: GET and PUT /orgs/{org}/actions/variables/{name}/repositories, and PUT and DELETE /orgs/{org}/actions/variables/{name}/repositories/{repository_id}. The selection endpoints return 409 when variable visibility is not selected. Organization variable responses include visibility and selected_repositories_url.
Unlike secrets, the API returns variable values in plain text.
Access requirements: the API requires collaborator access to the repository. Personal access tokens (classic) require the repo scope for repository variables and admin:org for organization variables. GitHub App installation tokens require the actions_variables permission for repository variables and organization_actions_variables for organization variables.
Docs: https://docs.github.com/en/rest/actions/variables
Proposed scope
- Repository variables: list, create, get, update, and delete. Return
404on a missing name forGETorPATCH, which clients use to decide between update and create. - Organization variables: the same operations, plus
visibility,selected_repository_ids, and the selected repository endpoints. GET /repos/{owner}/{repo}/actions/organization-variables, filtered by visibility and repository selection.- GitHub App permission checks for
actions_variablesandorganization_actions_variables, matching existing installation token checks forsecrets. - Optional: seed variables from the configuration file under a repository or organization.
- Out of scope for the initial implementation: environment variables (
/repos/{owner}/{repo}/environments/{environment_name}/variables).
Proposed implementation
The secrets routes in actions.ts already model this repository and organization split. They use a GitHubSecret entity carrying repo_id, org_id, name, and visibility, with GitHub App permission checks via assertRepoPermission(..., "secrets"):
Variables can follow the same pattern: introduce a GitHubVariable entity that also stores value, and verify the actions_variables permission key instead of secrets.
Activity
0No activity yet.