Skip to content

Commit

The Deployments guide has a section on deploying from a workflow: a whole example with g1t/deploy@v1, what each kind of run builds, the action's inputs and outputs, how the build is opened and masked, which runs build without the project's secrets, that the build's time is the job's Actions time, that g1t's own builds still run beside it, and g1t/detect; its costs table and troubleshooting say so too. The GitHub Actions guide lists g1t's own actions, g1t/deploy and g1t/detect.

Claude-Session:
https://claude.ai/code/session_01PnwTRSNaC7vEHTAuBzjhrn
Claudeagent and Claudeagentcommitted Parent6a4dc3fBrowse files
2 files+133−10/2 viewed
+14−0
147147 `PUT /repos/{owner}/{repo}/actions/permissions/access` with
148148 `{"access_level": "organization"}` (`none` to stop).
149149
150+### g1t's own actions
151+
152+The `g1t` workspace on g1t.sh holds g1t's own actions, public, with a
153+`v1` tag that moves with each compatible release:
154+
155+| Action | What it does |
156+| --- | --- |
157+| [`g1t/deploy@v1`](https://g1t.sh/g1t/deploy) | Builds the checkout and puts it on [g1t.page](/guides/deployments/): production from the project's production branch, a preview from a pull request or another branch. The job needs `deployments: write`. See [deploying from a workflow](/guides/deployments/#deploying-from-a-workflow). |
158+| [`g1t/detect@v1`](https://g1t.sh/g1t/detect) | Says what that build would find (`kind`, `install`, `build`, `output-dir`) without building anything. |
159+
160+Both are composite actions around `g1t-runner`, which g1t's machines
161+have; on a [self-hosted runner](/guides/self-hosted-runners/) they use
162+the one on `PATH` or download the newest release.
163+
150164 ### Secrets for a called workflow
151165
152166 A called workflow gets only the secrets its caller passes, plus
+119−1
189189 The [checklist on the overview](/guides/projects/#get-to-production) also
190190 tracks the first production deploy, a custom domain and a first preview.
191191
192+## Deploying from a workflow
193+
194+A [workflow](/guides/actions/) job can build and deploy the project
195+itself, with g1t's own action, `g1t/deploy`. Use it when the build needs
196+steps of yours first (generated code, a test that must pass, a tool the
197+default build lacks), or to deploy from a branch without a pull request.
198+The app, its address, its checks and its custom domains are the same as
199+for the builds g1t starts by itself.
200+
201+```yaml
202+# .g1t/workflows/deploy.yml
203+name: Deploy
204+
205+on:
206+ push:
207+ branches: [main]
208+ pull_request:
209+
210+permissions:
211+ contents: read
212+ deployments: write
213+
214+jobs:
215+ deploy:
216+ runs-on: ubuntu-latest
217+ steps:
218+ - uses: actions/checkout@v5
219+ - uses: actions/setup-node@v4
220+ with:
221+ node-version: 24
222+ - run: npm ci
223+ - run: npm test
224+ - id: deploy
225+ uses: g1t/deploy@v1
226+ with:
227+ build-command: npm run build
228+ - run: echo "Live at ${{ steps.deploy.outputs.url }}"
229+```
230+
231+1. Turn Deployments on for the project, as in
232+ [Turn on deployments](#turn-on-deployments).
233+2. Add a workflow like the one above. The job needs `deployments: write`
234+ (or `pages: write`) in its `permissions:`.
235+3. Push. The run on `main` deploys production; a pull request's run
236+ deploys its preview.
237+
238+What the run builds:
239+
240+| The run | Builds |
241+| --- | --- |
242+| On the project's production branch (a push, `workflow_dispatch` or `schedule` there) | Production |
243+| For a pull request (`pull_request`, `pull_request_target`) | That pull request's preview, at its branch's address, or `pr-<number>` for one from a fork |
244+| On another branch | That branch's preview |
245+| For a tag | Nothing: the step fails and says to run the workflow on a branch |
246+
247+`g1t/deploy` takes these inputs:
248+
249+| Input | Default | |
250+| --- | --- | --- |
251+| `project` | The repository's one project with Deployments on | The project's slug. Needed when the repository has several. |
252+| `root-dir` | The project's **Root directory** | Where the project is in the checkout. |
253+| `build-command` | The project's **Build command**, else what the build finds | What builds it, run after the install. |
254+| `output-dir` | The project's **Output directory**, else the first folder found | The folder a static build writes. |
255+| `sha` | The run's commit | The commit the `g1t / deploy` check goes on. |
256+| `token` | `${{ github.token }}` | The job's own token. No other token can open a build. |
257+
258+Its outputs are `url` (the app's address), `deployment-id` (`dpl_…`) and
259+`kind` (`production` or `preview`).
260+
261+The action calls
262+[`POST /repos/{owner}/{repo}/deployments/builds`](/reference/api/deployments/start-deployment-build/),
263+which checks the plan and the spend limit as any build does, sets the
264+commit's `g1t / deploy` check to pending, and answers with a token for
265+that build alone and the project's
266+[variables and secrets](#secrets-and-variables) for production or
267+previews. The action masks the token and every secret in the log, then
268+runs `g1t-runner deploy` in the checkout, which installs, builds and
269+uploads exactly as [What deploys](#what-deploys) says; its output is in
270+the step's log and on the deployment's page. When the build fails, or
271+g1t does not take what it built, the step fails and the deployment says
272+why.
273+
274+- **Secrets.** A pull request from a fork or from someone without the
275+ Write role, and a run that had to be
276+ [approved](/guides/actions/#pull-requests), build without
277+ the project's secrets, as previews of them always have. Their token is
278+ read-only, so they cannot open a build at all unless the workflow runs
279+ on `pull_request_target`.
280+- **Cost.** The build runs in the job, so its time is the job's
281+ [Actions time](/guides/usage-and-billing/), free on a
282+ [self-hosted runner](/guides/self-hosted-runners/), and is not charged
283+ again as build seconds. Requests, CPU time and custom domains are
284+ charged as for any app.
285+- **g1t's own builds still run.** A push to the production branch and a
286+ pull request's push still start g1t's build too. Whichever starts
287+ later replaces the other, so the app ends up at the newest commit
288+ either way.
289+- **On your own machines**, the action uses the `g1t-runner` on `PATH`, or
290+ downloads the newest release and checks it against its `SHA256SUMS`. It
291+ runs on Linux and macOS, with `curl` and `jq` or `python3`.
292+
293+`g1t/detect` says what a build of the checkout would find, without
294+building anything: its outputs are `kind` (`workers`, `static`, `html` or
295+`none`), `install`, `build` and `output-dir`. Use them to cache, or to
296+fail early:
297+
298+```yaml
299+- id: detect
300+ uses: g1t/detect@v1
301+- if: steps.detect.outputs.kind == 'none'
302+ run: |
303+ echo "::error::Nothing here would be served: add an index.html or a build script."
304+ exit 1
305+```
306+
192307 ## Custom domains
193308
194309 Production can be served at a domain of your own, such as `example.com` or
350465 | | Costs g1t | You pay |
351466 | --- | --- | --- |
352467 | Projects, previews and the apps behind them | Next to nothing | Not charged |
353−| Builds, by the second, whether they succeed or fail | About $0.001 a minute | About $0.0012 a minute |
468+| Builds g1t runs, by the second, whether they succeed or fail (a [workflow's build](#deploying-from-a-workflow) is its job's Actions time instead) | About $0.001 a minute | About $0.0012 a minute |
354469 | Requests, to all of the workspace's apps | $0.30 a million | $0.36 a million |
355470 | CPU time your code spends computing (waiting on the network is not counted) | $0.02 a million ms | $0.024 a million ms |
356471 | Custom domains, with their certificates (a www/apex pair is two) | $0.10 a month | $0.12 a month, by the most the workspace had at once that month |
448563 | A domain stays at **Waiting for DNS** | Check the record against the one listed, remove other `A`/`AAAA` records for the same name, then choose **Check now**. |
449564 | A domain says "This domain is not set up" | It points at g1t, but no project has added it. Add it under **Settings → Domains**. |
450565 | "This pull request's commit no longer exists" | The pull request's head was force-pushed over, or its branch deleted, after the build was asked for. Push to the pull request again, or close it. g1t does not try that commit again. |
566+| g1t/deploy says "The job's token needs `deployments: write`" | Add `deployments: write` to the workflow's or the job's `permissions:`. A pull request's run from outside gets a read-only token and cannot deploy. |
567+| g1t/deploy says "Name the project to build" | The repository has several projects with Deployments on: give `project:`. |
568+| g1t/deploy says "g1t.page deploys branches and pull requests" | The run is for a tag. Run the workflow on a branch, such as on a push to `main`. |
451569 | "The build did not finish in 45 minutes" | The build stopped reporting: a build stops at 30 minutes, and one not heard from after 45 is failed. Make the build faster, or build less for previews with **Build command**. |
452570
453571 ## Running your own g1t