Skip to content

Commit

Docs: job summaries, re-runs and attempts, debug logging, cancelling, logs, badges

The Actions guide documents each, with the API routes; PLAN.md lists the run parity built and what is not yet.

syntaqxcommitted Parentdf1e7bcBrowse files
2 files+168−60/2 viewed
+133−6
4040 | Composite actions | The same. |
4141 | Reusable workflows in the repository (`jobs.<id>.uses: ./.g1t/workflows/build.yml`) | The same: `with:` inputs, `on.workflow_call` outputs, and nesting up to four deep. `./.github/workflows/…` finds the workflow under `.g1t/` after the move. Their jobs read the repository's secrets and variables. |
4242 | `actions/checkout` | Checks out from g1t, with `ref`, `fetch-depth`, `path`, `repository`, `token` and `submodules`. |
43−| `GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STATE`, `GITHUB_STEP_SUMMARY` | The same. |
43+| `GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STATE`, `GITHUB_STEP_SUMMARY` | The same. Step summaries show on the run's page; see [job summaries](#job-summaries). |
4444 | `::error::`, `::warning::`, `::notice::`, `::group::`, `::add-mask::` | The same: errors and warnings become annotations on the run, and [masked](#masking-secrets) values stay hidden. |
4545 | `secrets.*`, `vars.*`, `secrets.GITHUB_TOKEN` | The same. `secrets.G1T_TOKEN` is [the job's own token](#the-jobs-token); `GITHUB_TOKEN` is its alias. |
4646 | `environment:` on a job | The job waits for the environment's [protection rules](#environments), then reads each key's row for that environment, as environment secrets work, and the run records a [deployment](/guides/deployments-api/#deployments-from-g1t-actions) to it. `url` gives the deployment its address; `deployment: false` reads the environment's values without making one. The name may be an expression. |
621621
622622 A run's page shows its jobs, each job's steps, and their logs as they are
623623 written. Groups fold, errors and warnings are marked, and secrets are
624−replaced with `***`. **Cancel**, **Re-run all jobs** and **Re-run failed
625−jobs** do what they say.
624+replaced with `***`.
626625
627626 The start of each job's log lists what its [token](#the-jobs-token) may do.
628627
628+### Job summaries
629+
630+Markdown a step appends to the file in `$GITHUB_STEP_SUMMARY` shows at
631+the top of the run's page, a card per job, in the order its steps wrote
632+it:
633+
634+```yaml
635+- name: Report the tests
636+ if: always()
637+ run: |
638+ echo "### Test results" >> "$GITHUB_STEP_SUMMARY"
639+ echo "| Suite | Passed | Failed |" >> "$GITHUB_STEP_SUMMARY"
640+ echo "| --- | ---: | ---: |" >> "$GITHUB_STEP_SUMMARY"
641+ echo "| unit | 41 | 0 |" >> "$GITHUB_STEP_SUMMARY"
642+```
643+
644+| What | How it works |
645+| --- | --- |
646+| Formatting | GitHub-flavoured Markdown: tables, task lists, alerts such as `> [!WARNING]`, code blocks, and the HTML GitHub allows. Scripts, styles and event handlers are removed. |
647+| Secrets | Masked like the log, before the summary leaves the runner. |
648+| Size | Up to 1 MiB a step. A larger summary is refused with an error in the step's log, as on GitHub. |
649+| Steps | Up to 20 steps of a job keep a summary; later ones are dropped. |
650+| Actions | A JavaScript action's `core.summary` writes to the same file, so it works unchanged. |
651+
652+Summaries belong to their attempt: an earlier attempt keeps its own.
653+
654+### Re-running
655+
656+When a run has finished, someone with the Write role can run it again:
657+
658+| Button | Runs again |
659+| --- | --- |
660+| **Re-run all jobs** | Every job. |
661+| **Re-run failed jobs** | Jobs that did not succeed (failed, cancelled or skipped), and every job that needs one of them. |
662+| The re-run button beside a job's name | That job, and every job that needs it. A job of a matrix runs again with the rest of its matrix; a job of a reusable workflow runs again with the job that calls it. |
663+
664+Jobs that are not run again keep how they ended, and their outputs reach
665+the jobs that need them.
666+
667+Each re-run is a new **attempt**. The run keeps its number, `github.run_attempt`
668+goes up by one, and the attempt before is kept as it ended: its jobs,
669+their steps, logs and summaries. Pick one from **Attempt #** at the top of
670+the page to read it. Its jobs have ids of their own, so a link to an
671+earlier attempt's job keeps showing that job's log.
672+
673+#### Debug logging
674+
675+Each re-run asks whether to **Enable debug logging**. The new attempt's
676+jobs then run with:
677+
678+| Set | Effect |
679+| --- | --- |
680+| `RUNNER_DEBUG=1`, and `runner.debug` is `1` | Actions that check it, such as the toolkit's `core.isDebug()`, log more. |
681+| `ACTIONS_STEP_DEBUG=true` | `::debug::` lines are shown in the log. |
682+| `ACTIONS_RUNNER_DEBUG=true` | Set for actions that read it. |
683+
684+With debug logging, each step's log also says how its `if:` read:
685+`Evaluating condition for step`, the expression, and the result. Setting a
686+secret or variable named `ACTIONS_STEP_DEBUG` to `true` shows `::debug::`
687+lines on every run instead. The attempt picker marks attempts that ran
688+with debug logging.
689+
690+### Cancelling
691+
692+**Cancel run** cancels jobs that have not started at once. A job that is
693+running is stopped the way GitHub stops one:
694+
695+1. The step it is on gets `SIGINT`, then `SIGTERM` 7.5 seconds later, and
696+ is killed 2.5 seconds after that. Signals reach the processes the step
697+ started too; in a [job container](#job-containers) they reach only the
698+ `docker exec` that runs the step. The step ends **cancelled**.
699+2. Its remaining steps run only if they ask to: `if: always()` or
700+ `if: cancelled()`. Steps without an `if:`, or with `success()` or
701+ `failure()`, are skipped.
702+3. Post steps (an action's `post`, saving the cache) run, as their
703+ `post-if` is `always()` unless the action says otherwise.
704+4. The job ends **cancelled**, whatever those steps came to.
705+
706+While that happens the run says **Cancelling**. A job still going 5
707+minutes after it was cancelled is stopped outright. **Force cancel**
708+(shown while a run is cancelling) stops every job at once, without
709+waiting for its cleanup steps.
710+
711+A step learns of a cancellation within about 10 seconds, even when it
712+prints nothing. A job on a [self-hosted runner](/guides/self-hosted-runners/)
713+is stopped the same way.
714+
715+### Searching and downloading logs
716+
717+The **Search logs** box above a job's steps shows only the lines that hold
718+what you type, in any case, with each match marked and every step that has
719+one opened. Lines inside folded groups are searched too.
720+
721+| Download | Where |
722+| --- | --- |
723+| One job's whole log, as text | The download button beside the job's name. |
724+| Every job's log of an attempt, as a zip | **Download logs** at the top of the run. The zip holds `1_<job>.txt` with each job's whole log, and a `<job>/` folder with `<step>_<step name>.txt` for each step. |
725+
726+A zip holds up to 24 MiB of logs; jobs past that are listed with a note
727+to download them on their own. Each job keeps up to 4 MB of log.
728+
729+### Status badges
730+
731+A badge shows how a workflow's latest finished run went: **passing**,
732+**failing**, **cancelled**, or **no status** before it has finished one.
733+
734+1. Open the repository's **Actions** page and pick the workflow.
735+2. Click **Create status badge**.
736+3. Choose a branch and an event, if you want them, and copy the Markdown.
737+
738+```markdown
739+[![CI](https://g1t.sh/acme/web/actions/workflows/ci.yml/badge.svg)](https://g1t.sh/acme/web/actions?workflow=ci.yml)
740+```
741+
742+The address is `https://g1t.sh/{workspace}/{repo}/actions/workflows/{file}/badge.svg`,
743+where `{file}` is the workflow's file name in `.g1t/workflows/`. It takes:
744+
745+| Parameter | Shows |
746+| --- | --- |
747+| `branch` | Runs on that branch. Without it, the default branch's runs, or any branch's when the default branch has none. |
748+| `event` | Runs started by that event, such as `push` or `pull_request`. |
749+
750+A public repository's badge loads for anyone and is cached for a minute.
751+A private repository's loads only for someone who can see the repository,
752+so it does not show in a README read anywhere else.
753+
629754 ### Masking secrets
630755
631756 Every secret's value is replaced with `***` wherever a job prints it, and
10001125 | `list` | `GET /repos/{owner}/{repo}/actions/workflows` |
10011126 | `list_runs` | `GET /repos/{owner}/{repo}/actions/runs`, with `workflow`, `branch`, `event`, `pull`, `head_sha` |
10021127 | `get_run` | `GET /repos/{owner}/{repo}/actions/runs/{id}` |
1003−| `job_logs` | `GET /repos/{owner}/{repo}/actions/jobs/{job}/logs?after=` |
1128+| `job_logs` | `GET /repos/{owner}/{repo}/actions/jobs/{job}/logs?after=`, or `?format=text` for the whole log as plain text |
1129+| `get_run` with `attempt` | `GET /repos/{owner}/{repo}/actions/runs/{id}/attempts/{attempt}` |
1130+| No tool: a download | `GET /repos/{owner}/{repo}/actions/runs/{id}/logs`, or `…/attempts/{attempt}/logs`: every job's log as a zip |
10041131 | `dispatch` | `POST /repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches` with `ref` and `inputs` |
1005−| `cancel` | `POST /repos/{owner}/{repo}/actions/runs/{id}/cancel` |
1006−| `rerun` | `POST …/runs/{id}/rerun`, or `…/rerun-failed-jobs` |
1132+| `cancel` | `POST /repos/{owner}/{repo}/actions/runs/{id}/cancel`; `…/force-cancel`, or `force`, to stop running jobs without their cleanup steps |
1133+| `rerun` | `POST …/runs/{id}/rerun`, or `…/rerun-failed-jobs`; one job and those that need it with `POST /repos/{owner}/{repo}/actions/jobs/{job}/rerun`. Each takes `enable_debug_logging` (or `debug`) |
10071134 | `update` | `PUT …/workflows/{workflow}/enable` and `…/disable` |
10081135 | `approve_run` | `POST /repos/{owner}/{repo}/actions/runs/{id}/approve` |
10091136 | `pending_deployments` | `GET /repos/{owner}/{repo}/actions/runs/{id}/pending_deployments` |
+35−0
743743 inside other actions), downloads from other repositories, and npm
744744 trusted publishing, which depends on npm accepting g1t's issuer.
745745
746+### Runs: summaries, attempts, cancelling, logs and badges (built 2026-10-08)
747+
748+GitHub Actions parity on the run itself:
749+
750+- [x] **Job summaries.** The runner sends each step's
751+ `$GITHUB_STEP_SUMMARY`, masked, as a `summary` report (1 MiB a step,
752+ 20 steps a job, kept in `job_summaries`, actions/0008); the run's page
753+ renders them as sanitised Markdown, a card per job.
754+- [x] **Attempts and re-runs.** A re-run is a new attempt that keeps the
755+ one before (`run_attempts`, `job_attempts`; a re-run job's logs and
756+ summary move to `{job}.{attempt}`, which is its id when that attempt is
757+ viewed). Re-run all, failed, or one job (`POST …/jobs/{job}/rerun`) with
758+ the jobs that need it; a matrix or a called workflow runs again whole.
759+ Debug re-runs set `RUNNER_DEBUG=1`, `ACTIONS_STEP_DEBUG`,
760+ `ACTIONS_RUNNER_DEBUG` and `runner.debug`; the runner then shows
761+ `::debug::` lines and how each step's `if:` read. An attempt picker on
762+ the run's page, `attempt` on `get_workflow_run` and
763+ `…/runs/{id}/attempts/{n}`.
764+- [x] **Graceful cancel.** A running job gets `cancel_requested_at`,
765+ told in the answer to its next report (a quiet step pings every 10 s):
766+ the step's process group gets SIGINT, SIGTERM at 7.5 s, SIGKILL at 10 s;
767+ then only `always()`/`cancelled()` steps and post steps run, and the job
768+ ends `cancelled`. Hard-stopped after 5 minutes; cancelling again or
769+ `…/force-cancel` stops at once.
770+- [x] **Logs.** Search on the run's page (matching lines, groups opened);
771+ one job's log as text (`…/jobs/{job}/log.txt`, API
772+ `…/jobs/{job}/logs?format=text`) and an attempt's as a zip laid out as
773+ GitHub's (`…/runs/{id}/logs.zip`, API `…/runs/{id}/logs`), up to 24 MiB.
774+- [x] **Status badges** at `/{ws}/{repo}/actions/workflows/{file}/badge.svg`
775+ with `branch` and `event`; public repositories' for anyone (cached a
776+ minute), private ones' only for viewers who can see them. "Create status
777+ badge" on the workflow's page gives the Markdown.
778+- Not yet: re-running one combination of a matrix alone; signals into a
779+ job container's processes on cancel (they reach `docker exec` only).
780+
746781 ## A repository that maintains itself
747782
748783 > **2026-10-04:** the user asked for Dependabot, GitHub Advanced Security and