Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

151 linesCodeBlameRaw
1---
2title: Secrets and variables
3description: One list of keys and values for workflows and deployments. Each row says which environments it applies to and who reads it.
4---
5
6A [project](/guides/projects/) and a workspace each have one list of
7secrets and variables.
8Workflows and deployments both read from it; each row says whether one,
9the other or both do, and which environments it applies to.
10
11| Where | Page | Who sees and changes it |
12| --- | --- | --- |
13| A project | **Settings → Secrets and variables**, `g1t.sh/<workspace>/<project>/settings/secrets` | People with the Admin [role](/guides/access-and-roles/) on its repository |
14| A workspace | **Settings → Secrets and variables**, `g1t.sh/<workspace>/-/secrets` | Owners |
15
16Seeing the list needs the same as changing it: a project's rows, config
17values included, are for Admins of its repository, and the page is not
18shown to anyone else.
19
20## A row
21
22| Field | |
23| --- | --- |
24| **Type** | **Secret**: sealed when saved and never shown again, hidden in logs. For passwords, API keys and tokens. **Config**: readable by whoever may see the list. For values that are not sensitive. Config can be changed to a secret; a secret can never become config. |
25| **Key** | Letters, digits and underscores, not starting with a digit, upper-cased: `STRIPE_KEY`. Keys starting with `G1T_` or `GITHUB_` are g1t's own. |
26| **Value** | Up to 48 KB. |
27| **Note** | Optional: where to rotate it, or who to ask. |
28| **Environments** | **All environments**, or only some: **Production**, **Preview**, or any name a workflow job uses in `environment:`, such as `staging`. |
29| **Available to** | **Workflows**, **Deployments**, or both (the default). |
30| **Projects** | A workspace's row only: every project, or the ones you choose. |
31
32### A value per environment
33
34A key can have one row per environment, so production and previews use
35different values. For example, Stripe's live key in production and its
36test key everywhere else:
37
38| Key | Type | Environments | Value |
39| --- | --- | --- | --- |
40| `STRIPE_KEY` | Secret | Production | `sk_live_…` |
41| `STRIPE_KEY` | Secret | Preview | `sk_test_…` |
42
43Two rows of the same key and type cannot apply to the same environment.
44A key can also have a row for all environments alongside rows for some:
45the rows for some win where they apply.
46
47### Adding many at once
48
49Paste the contents of a `.env` file into **Key** when adding. Each
50`KEY=value` line becomes a row with the type, environments and readers you
51choose; blank lines and `#` comments are skipped.
52
53## Who reads what
54
55| Reader | Reads | Environment it asks for |
56| --- | --- | --- |
57| A workflow job | Rows available to Workflows: secrets as `${{ secrets.KEY }}`, config as `${{ vars.KEY }}` | The job's `environment:`, if it has one |
58| A deploy build | Rows available to Deployments, as environment variables | `production` or `preview` |
59| A running app | The same rows, as bindings: `env.KEY` (a secret as a secret binding) | `production` or `preview` |
60| An agent, the merge queue's builds | Nothing | |
61
62For each key, a reader gets the row for its environment if there is one,
63else the row for all environments. A row only for other environments gives
64it nothing.
65
66A project's row overrides its workspace's of the same key. The project's
67list shows the workspace's rows that reach it, marked
68**Workspace**, until it sets the key itself.
69
70A running app's rows are bound by g1t when it puts the app up; they never
71pass through the build's sandbox. A row of a Workers project's own
72`vars` with the same name is replaced.
73
74## Who gets secrets
75
76Secrets go only to trusted runs:
77
78- pushes, schedules, manual runs and the merge queue;
79- pull requests whose author has the Write [role](/guides/access-and-roles/)
80 or higher on the repository, a member or an
81 [outside collaborator](/guides/access-and-roles/#outside-collaborators).
82 For one g1t made, that is whoever asked for it;
83- pull requests g1t opened on its own, such as a security update.
84
85Anyone else's pull request, such as one from a fork or by someone with
86Read or Triage (who may open one on a private repository too), runs its
87workflows, and builds its preview, with config only: no secrets, and a
88`G1T_TOKEN` that can only read. Its runs may first wait for someone with
89Write to [approve them](/guides/actions/#pull-requests-from-outside).
90
91A job that names an environment gets that environment's secrets only once
92the environment's [protection rules](/guides/actions/#environments) let it
93through: required reviewers, a wait timer, and which branches may deploy.
94
95## G1T_TOKEN
96
97Every workflow job gets `${{ secrets.G1T_TOKEN }}`: a token for that job
98alone, which reaches its repository only, can do what the job's
99`permissions:` say, and stops working when the job ends.
100`${{ secrets.GITHUB_TOKEN }}` and `${{ github.token }}` are the same token,
101so workflows written for GitHub work unchanged. See
102[the job's token](/guides/actions/#the-jobs-token).
103
104```yaml
105# On the job: permissions: { issues: write }
106- name: Open an issue when the nightly build fails
107 if: failure()
108 run: |
109 curl -X POST https://api.g1t.sh/repos/${{ github.repository }}/issues \
110 -H "Authorization: Bearer ${{ secrets.G1T_TOKEN }}" \
111 -d '{"title":"Nightly build failed"}'
112```
113
114`G1T_TOKEN` can neither list nor change secrets or variables, so a
115workflow cannot read or rewrite what it runs with. No workspace access
116token can change them either: use a person's token, or the site.
117
118## From the API
119
120The routes are GitHub's, and calls written for GitHub work unchanged: a
121key named without an `id` or `environments` is the key's row for all
122environments.
123
124| MCP (`secret` tool) | Route |
125| --- | --- |
126| `list_secrets` | `GET /repos/{owner}/{repo}/actions/secrets` |
127| `set_secret` | `PUT /repos/{owner}/{repo}/actions/secrets/{key}` |
128| `delete_secret` | `DELETE /repos/{owner}/{repo}/actions/secrets/{key}` |
129| `list_variables` | `GET /repos/{owner}/{repo}/actions/variables` |
130| `set_variable` | `POST /repos/{owner}/{repo}/actions/variables`, `PATCH …/variables/{key}` |
131| `delete_variable` | `DELETE /repos/{owner}/{repo}/actions/variables/{key}` |
132
133A workspace's are under `/workspaces/{workspace}/actions/secrets` and
134`…/variables`. Beyond GitHub's fields, a row takes:
135
136| Field | |
137| --- | --- |
138| `id` | The row to change or remove, from a list. |
139| `available_to` | `["workflows"]`, `["deployments"]` or both. `availableTo` works too. |
140| `environments` | `["production"]`, `["preview", "staging"]`; `[]` for all. |
141| `projects` | A workspace's row: project names; `[]` for every one. (`repositories` is read the same way.) |
142| `note` | Where to rotate it, or who to ask. |
143
144```sh
145curl -X PUT https://api.g1t.sh/repos/acme/web/actions/secrets/STRIPE_KEY \
146 -H "Authorization: Bearer $YOUR_TOKEN" \
147 -d '{"value":"sk_live_…","environments":["production"],"available_to":["deployments"]}'
148```
149
150A secret is sent as plain `value` over HTTPS, not encrypted to a public
151key first.