detached 33a243c

workflows.md RawHistoryFolder

Workflow features

Job containers and service containers

container: and services: work as on GitHub-hosted Linux runners. The containers are created in the sandbox's own dockerd, so nothing reaches the host.

  • Initialize containers runs after "Set up job":
    • checks the Docker API version (1.35 or newer);
    • removes labelled leftovers;
    • creates the network github_network_<32 hex>;
    • pulls (3 tries) and starts each container;
    • waits for service health checks.
  • Registry credentials: go to a private docker --config directory under RUNNER_TEMP. The password goes through stdin and is masked. The directory is removed after the pull.
  • Stop containers is a post step (always()). It prints service logs and removes containers and the network. It runs after a failure, a cancellation and a timeout.
  • run: steps and node actions in the job container go through docker exec. Values are passed in the environment of the docker process, never on the command line.
  • Node actions in a job container use the externals mounted at /__e. node<N>_alpine is used when /etc/*release says alpine.
  • Docker actions run as siblings on the job network.
  • Contexts job.container.{id,network} and job.services.<alias>.{id,network,ports} are set.
  • Not supported: container hooks (ACTIONS_RUNNER_CONTAINER_HOOKS) and the "already running in a container" refusal.

Security notes:

  • options: is split into arguments and passed to docker create as an argument vector, never through a shell. A workflow cannot inject a second command.
  • A workflow can still pass any docker create flag (--privileged, --pid host, --device) and bind volumes, as on a self-hosted GitHub runner.
  • The sandbox contains this, not the runner. Host paths in volumes: and options: are paths of the sandbox.
  • The runner warns about a volume that mounts /.

Cancellation

  • The host sends a cancel request to the executor.
  • The executor signals the script's process group like the official runner: SIGINT at once, SIGTERM after 7.5 s, SIGKILL 2.5 s later.
  • Background children that keep the output pipes open are killed when the shell exits.
  • Init forwards SIGTERM and SIGINT to the executor.
  • Step timeout-minutes is enforced.

Annotations, summaries and masks

  • ::notice, ::warning and ::error become annotations, with title, file, line, endLine, col and endColumn.
  • Problem matchers are supported (add-matcher, remove-matcher). Each has a 1 s timeout (GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT) and is removed after 3 timeouts.
  • Every ##[error] the runner writes becomes an annotation.
  • Limits: 10 annotations per level per step, messages cut at 4096 characters.
  • GITHUB_STEP_SUMMARY is read after each step, up to 1 MiB.
  • ::add-mask:: masks values at run time.
  • Annotations and summaries are sent only when the server lists ci.annotations and ci.summaries.

Attribution for the ported code: THIRD_PARTY.md.

source
1# Workflow features
2
3## Job containers and service containers
4
5`container:` and `services:` work as on GitHub-hosted Linux runners. The containers are created in the **sandbox's own `dockerd`**, so nothing reaches the host.
6
7- **Initialize containers** runs after "Set up job":
8  - checks the Docker API version (1.35 or newer);
9  - removes labelled leftovers;
10  - creates the network `github_network_<32 hex>`;
11  - pulls (3 tries) and starts each container;
12  - waits for service health checks.
13- Registry `credentials:` go to a private `docker --config` directory under `RUNNER_TEMP`. The password goes through stdin and is masked. The directory is removed after the pull.
14- **Stop containers** is a post step (`always()`). It prints service logs and removes containers and the network. It runs after a failure, a cancellation and a timeout.
15- `run:` steps and node actions in the job container go through `docker exec`. Values are passed in the environment of the docker process, never on the command line.
16- Node actions in a job container use the externals mounted at `/__e`. `node<N>_alpine` is used when `/etc/*release` says alpine.
17- Docker actions run as siblings on the job network.
18- Contexts `job.container.{id,network}` and `job.services.<alias>.{id,network,ports}` are set.
19- Not supported: container hooks (`ACTIONS_RUNNER_CONTAINER_HOOKS`) and the "already running in a container" refusal.
20
21Security notes:
22
23- `options:` is split into arguments and passed to `docker create` as an argument vector, never through a shell. A workflow cannot inject a second command.
24- A workflow can still pass any `docker create` flag (`--privileged`, `--pid host`, `--device`) and bind volumes, as on a self-hosted GitHub runner.
25- The sandbox contains this, not the runner. **Host paths in `volumes:` and `options:` are paths of the sandbox.**
26- The runner warns about a volume that mounts `/`.
27
28## Cancellation
29
30- The host sends a cancel request to the executor.
31- The executor signals the script's process group like the official runner: SIGINT at once, SIGTERM after 7.5 s, SIGKILL 2.5 s later.
32- Background children that keep the output pipes open are killed when the shell exits.
33- Init forwards SIGTERM and SIGINT to the executor.
34- Step `timeout-minutes` is enforced.
35
36## Annotations, summaries and masks
37
38- `::notice`, `::warning` and `::error` become annotations, with `title`, `file`, `line`, `endLine`, `col` and `endColumn`.
39- Problem matchers are supported (`add-matcher`, `remove-matcher`). Each has a 1 s timeout (`GITHUB_ACTIONS_RUNNER_ISSUE_MATCHER_TIMEOUT`) and is removed after 3 timeouts.
40- Every `##[error]` the runner writes becomes an annotation.
41- Limits: 10 annotations per level per step, messages cut at 4096 characters.
42- `GITHUB_STEP_SUMMARY` is read after each step, up to 1 MiB.
43- `::add-mask::` masks values at run time.
44- Annotations and summaries are sent only when the server lists `ci.annotations` and `ci.summaries`.
45
46Attribution for the ported code: [THIRD_PARTY.md](../THIRD_PARTY.md).

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 4

Tags 11

↑↓ moveenter openesc close