diff --git a/_images/user/actions/action-approve.png b/_images/user/actions/action-approve.png new file mode 100644 index 00000000..1441f2b0 Binary files /dev/null and b/_images/user/actions/action-approve.png differ diff --git a/_images/user/actions/action-blocked.png b/_images/user/actions/action-blocked.png new file mode 100644 index 00000000..0bc1c410 Binary files /dev/null and b/_images/user/actions/action-blocked.png differ diff --git a/_images/user/actions/actions-detail.png b/_images/user/actions/actions-detail.png new file mode 100644 index 00000000..78e7e4bd Binary files /dev/null and b/_images/user/actions/actions-detail.png differ diff --git a/_images/user/actions/actions-list.png b/_images/user/actions/actions-list.png new file mode 100644 index 00000000..e7c9f232 Binary files /dev/null and b/_images/user/actions/actions-list.png differ diff --git a/_images/user/actions/runner-tasks.png b/_images/user/actions/runner-tasks.png new file mode 100644 index 00000000..ea336fbe Binary files /dev/null and b/_images/user/actions/runner-tasks.png differ diff --git a/_images/user/actions/runners-add.png b/_images/user/actions/runners-add.png new file mode 100644 index 00000000..3cbb841d Binary files /dev/null and b/_images/user/actions/runners-add.png differ diff --git a/admin/actions.md b/admin/actions.md index d86f8984..8394dc34 100644 --- a/admin/actions.md +++ b/admin/actions.md @@ -4,7 +4,7 @@ title: 'Forgejo Actions administrator guide' license: 'CC-BY-SA-4.0' --- -`Forgejo Actions` provides continuous integration driven from the files in the `.forgejo/workflows` directory of a repository. It is still experimental and disabled by default. It can be activated by adding the following to `app.ini`: +`Forgejo Actions` provides continuous integration driven from the files in the `.forgejo/workflows` directory of a repository. It is still in beta and disabled by default. It can be activated by adding the following to `app.ini`: ```yaml [actions] @@ -15,7 +15,8 @@ ENABLED = true # Default Actions URL -When `uses:` does not specify an absolution URL for the `Action`, the value of `DEFAULT_ACTIONS_URL` is prepended to it. +When `uses:` does not specify an absolution URL for the `Action`, the +value of `DEFAULT_ACTIONS_URL` is prepended to it. ```yaml [actions] @@ -23,11 +24,22 @@ ENABLED = true DEFAULT_ACTIONS_URL = https://code.forgejo.org ``` -The [actions organization](https://code.forgejo.org/actions) contains a set of actions that are: +The actions found at https://code.forgejo.org are: - known to work with Forgejo Actions - published under a Free Software license +They can be found in the following organizations: + +- [General purpose actions](https://code.forgejo.org/actions) +- [Docker actions](https://code.forgejo.org/docker) + +When setting `DEFAULT_ACTIONS_URL` to a Forgejo instance with an open +registration, **care must be taken to avoid name conflicts**. For +instance if an action has `uses: foo/bar@main` it will clone and try +to run the action found at `DEFAULT_ACTIONS_URL/foo/bar` if it exists, +even if it provides something different than what is expected. + # Forgejo runner ## Installation @@ -35,9 +47,9 @@ The [actions organization](https://code.forgejo.org/actions) contains a set of a Download the latest [binary release](https://code.forgejo.org/forgejo/runner/releases) and verify their signature: ```shell -$ wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v2.0.3/forgejo-runner-amd64 +$ wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v2.1.0/forgejo-runner-amd64 $ chmod +x forgejo-runner -$ wget -O forgejo-runner.asc https://code.forgejo.org/forgejo/runner/releases/download/v2.0.3/forgejo-runner-amd64.asc +$ wget -O forgejo-runner.asc https://code.forgejo.org/forgejo/runner/releases/download/v2.1.0/forgejo-runner-amd64.asc $ gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710 $ gpg --verify forgejo-runner.asc forgejo-runner Good signature from "Forgejo " @@ -54,8 +66,10 @@ For jobs to run in LXC containers, the `Forgejo runner` needs passwordless sudo ```shell $ git clone https://code.forgejo.org/forgejo/lxc-helpers -$ ./lxc-helpers/lxc-helpers.sh lxc_container_create myrunner -$ ./lxc-helpers/lxc-helpers.sh lxc_container_start myrunner +$ sudo cp -a lxc-helpers/lxc-helpers{,-lib}.sh /usr/local/bin +$ lxc-helpers.sh lxc_container_create myrunner +$ lxc-helpers.sh lxc_container_start myrunner +$ lxc-helpers.sh lxc_container_user_install forgejo-runners 1000 debian ``` > **NOTE:** Multiarch [Go](https://go.dev/) builds and [binfmt](https://github.com/tonistiigi/binfmt) need `bookworm` to produce and test binaries on a single machine for people who do not have access to dedicated hardware. If this is not needed, installing the `Forgejo runner` on `bullseye` will also work. @@ -63,13 +77,13 @@ $ ./lxc-helpers/lxc-helpers.sh lxc_container_start myrunner The `Forgejo runner` can then be installed and run within the `myrunner` container. ```shell -$ ./lxc-helpers/lxc-helpers.sh lxc_container_run bash -# apt-get install docker.io wget gnupg2 -# wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v2.0.3/forgejo-runner-amd64 +$ lxc-helpers.sh lxc_container_run forgejo-runners -- sudo --user debian bash +$ sudo apt-get install docker.io wget gnupg2 +$ wget -O forgejo-runner https://code.forgejo.org/forgejo/runner/releases/download/v2.1.0/forgejo-runner-amd64 ... ``` -**Warning:** LXC containers do not provide a level of security that makes them safe for potentially malicious users to run jobs. They provide an excellent isolation for jobs that may accidentally damage the system they run on. +> **Warning:** LXC containers do not provide a level of security that makes them safe for potentially malicious users to run jobs. They provide an excellent isolation for jobs that may accidentally damage the system they run on. ## Registration @@ -80,13 +94,13 @@ The `Forgejo runner` needs to connect to a `Forgejo` instance and must register - in `/user/settings/actions/runners` to gain access to all repositories of the logged in user - in `/{owner}/{repository}/settings/actions/runners` to gain access to a single repository. +![add a runner](../../../../images/v1.20/user/actions/runners-add.png) + For instance, using a token obtained for a test repository from `next.forgejo.org`: ```shell forgejo-runner register --no-interactive --token {TOKEN} --name runner --instance https://next.forgejo.org --labels docker:docker://node:16-bullseye,self-hosted -INFO Registering runner, arch=amd64, os=linux, version=2.0.3. -WARN Runner in user-mode. -DEBU Successfully pinged the Forgejo instance server +INFO Registering runner, arch=amd64, os=linux, version=2.1.0. INFO Runner registered successfully. ``` @@ -104,7 +118,114 @@ It will create a `.runner` file that looks like: } ``` -## Running +## Configuration + +The default configuration for the runner can be +displayed with `forgejo-runner generate-config`, stored in a +`config.yml` file, modified and used instead of the default with the +`--config` flag. + +```yaml +$ forgejo-runner generate-config > config.yml +# Example configuration file, it's safe to copy this as the default config file without any modification. + +log: + # The level of logging, can be trace, debug, info, warn, error, fatal + level: info + +runner: + # Where to store the registration result. + file: .runner + # Execute how many tasks concurrently at the same time. + capacity: 1 + # Extra environment variables to run jobs. + envs: + A_TEST_ENV_NAME_1: a_test_env_value_1 + A_TEST_ENV_NAME_2: a_test_env_value_2 + # Extra environment variables to run jobs from a file. + # It will be ignored if it's empty or the file doesn't exist. + env_file: .env + # The timeout for a job to be finished. + # Please note that the Forgejo instance also has a timeout (3h by default) for the job. + # So the job could be stopped by the Forgejo instance if it's timeout is shorter than this. + timeout: 3h + # Whether skip verifying the TLS certificate of the Forgejo instance. + insecure: false + # The timeout for fetching the job from the Forgejo instance. + fetch_timeout: 5s + # The interval for fetching the job from the Forgejo instance. + fetch_interval: 2s + # The labels of a runner are used to determine which jobs the runner can run, and how to run them. + # Like: ["macos-arm64:host", "ubuntu-latest:docker://node:16-bullseye", "ubuntu-22.04:docker://node:16-bullseye"] + # If it's empty when registering, it will ask for inputting labels. + # If it's empty when execute `deamon`, will use labels in `.runner` file. + labels: [] + +cache: + # Enable cache server to use actions/cache. + enabled: true + # The directory to store the cache data. + # If it's empty, the cache data will be stored in $HOME/.cache/actcache. + dir: "" + # The host of the cache server. + # It's not for the address to listen, but the address to connect from job containers. + # So 0.0.0.0 is a bad choice, leave it empty to detect automatically. + host: "" + # The port of the cache server. + # 0 means to use a random available port. + port: 0 + +container: + # Specifies the network to which the container will connect. + # Could be host, bridge or the name of a custom network. + # If it's empty, create a network automatically. + network: "" + # Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker). + privileged: false + # And other options to be used when the container is started (eg, --add-host=my.forgejo.url:host-gateway). + options: + # The parent directory of a job's working directory. + # If it's empty, /workspace will be used. + workdir_parent: + # Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob + # You can specify multiple volumes. If the sequence is empty, no volumes can be mounted. + # For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to: + # valid_volumes: + # - data + # - /src/*.json + # If you want to allow any volume, please use the following configuration: + # valid_volumes: + # - '**' + valid_volumes: [] + # overrides the docker client host with the specified one. + # If it's empty, act_runner will find an available docker host automatically. + # If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers. + # If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work. + docker_host: "" + +host: + # The parent directory of a job's working directory. + # If it's empty, $HOME/.cache/act/ will be used. + workdir_parent: +``` + +## Cache configuration + +Some actions such as https://code.forgejo.org/actions/cache or +https://code.forgejo.org/actions/setup-go can communicate with the +`Forgejo runner` to save and restore commonly used files such as +compilation dependencies. They are stored as compressed tar archives, +fetched when a job starts and saved when it completes. + +If the machine has a fast disk, uploading the cache when the job +starts may significantly reduce the bandwidth required to download +and rebuild dependencies. + +If the machine on which the `Forgejo runner` is running has a slow +disk and plenty of CPU and bandwidth, it may be better to not activate +the cache as it can slow down the execution time. + +## Running the daemon Once the `Forgejo runner` is successfully registered, it can be run from the directory in which the `.runner` file is found with: @@ -113,6 +234,14 @@ $ forgejo-runner daemon INFO[0000] Starting runner daemon ``` +To verify it is actually available for the targeted repository, go to `/{owner}/{repository}/settings/actions/runners`. It will show the runners: + +- dedicated to the repository with the **repo** type +- available to all repositories within an organization or a user +- available to all repositories, with the **Global** type + +![list the runners](../../../../images/v1.20/user/actions/list-of-runners.png) + Adding the `.forgejo/workflows/demo.yaml` file to the test repository: ```yaml @@ -139,19 +268,19 @@ It will also show a similar output in the `Actions` tab of the repository. If no `Forgejo runner` is available, `Forgejo` will wait for one to connect and submit the job as soon as it is available. -## Job environment +## Labels and `runs-on` -The jobs defined in the files found in `.forgejo/workflows` specify the environment they need to run with `runs-on`. Each `Forgejo runner` declares, with the `--labels` option, which one they support so `Forgejo` knows to submit jobs accordingly. For instance if a job has: +The workflows / tasks defined in the files found in `.forgejo/workflows` must specify the environment they need to run with `runs-on`. Each `Forgejo runner` declares with **labels** which one they support so `Forgejo` knows sends them tasks accordingly. For instance if a job within a workflow has: ```yaml runs-on: docker ``` -the job will be submitted to a runner that registered with `--labels docker:docker://node:16-bullseye`. +it will be submitted to a runner that registered with a `docker` label (for instance with `--labels docker:docker://node:16-bullseye`). ### Docker -If `runs-on` is matched to a label that contains `docker://`, the rest of it is interpreted as a container image. The runner will execute all the steps, as root, within a container created from that image by default. +If `runs-on` is matched to a label that contains `docker://`, the rest of it is interpreted as the default container image to use if no other is specified. The runner will execute all the steps, as root, within a container created from that image. ### LXC @@ -163,7 +292,7 @@ Certain hosts may require specific configurations for runners to work smoothly. ### NixOS -The gitea-actions-runner recipe was released in NixOS 23.05. It can be configured via `services.gitea-actions-runner`. +The `gitea-actions-runner` recipe was released in NixOS 23.05. It can be configured via `services.gitea-actions-runner`. Please note that the `services.gitea-actions-runner.instances..labels` key may be set to `[]` (an empty list) to use the packaged Forgejo instance list. One of `virtualisation.docker.enable` or `virtualisation.podman.enable` will need to be set. The default Forgejo image list is populated with docker images. diff --git a/user/actions.md b/user/actions.md index b72f19bb..1bf37545 100644 --- a/user/actions.md +++ b/user/actions.md @@ -5,13 +5,13 @@ license: 'CC-BY-SA-4.0' similar: 'https://github.com/go-gitea/gitea/blob/main/docs/content/doc/usage/actions/faq.en-us.md https://docs.github.com/en/actions' --- -`Forgejo Actions` provides continuous integration driven from the files in the `.forgejo/workflows` directory of a repository. The syntax and semantic of the `workflow` files will be familiar to people used to [GitHub Actions](https://docs.github.com/en/actions) but **they are not and will never be identical**. +`Forgejo Actions` provides Continuous Integration driven from the files in the `.forgejo/workflows` directory of a repository, with a web interface to show the results. The syntax and semantic of the `workflow` files will be familiar to people used to [GitHub Actions](https://docs.github.com/en/actions) but **they are not and will never be identical**. The following guide explains key **concepts** to help understand how `workflows` are interpreted, with a set of **examples** that can be copy/pasted and modified to fit particular use cases. # Quick start -- Verify that `Enable Repository Actions` is checked in the `Repository` tab of the `/{owner}/{repository}/settings` page. +- Verify that `Enable Repository Actions` is checked in the `Repository` tab of the `/{owner}/{repository}/settings` page. If the checkbox does not show it means the administrator of the Forgejo instance did not activate the feature. ![enable actions](../../../../images/v1.20/user/actions/enable-repository.png) - Add the following to the `.forgejo/workflows/demo.yaml` file in the repository. ```yaml @@ -28,6 +28,121 @@ The following guide explains key **concepts** to help understand how `workflows` - Click on the workflow link to see the details and the job execution logs. ![actions results](../../../../images/v1.20/user/actions/workflow-demo.png) +# Concepts + +## Forgejo runner + +`Forgejo` itself does not run the `jobs`, it relies on the [Forgejo runner](https://code.forgejo.org/forgejo/runner) to do so. See the [Forgejo Actions administrator guide](../../admin/actions) for more information. + +## Actions + +An `Action` is a repository that contains the equivalent of a function in any programming language, with inputs and outputs as desccribed in the `action.yml` file at the root of the repository (see [this example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/action.yml)). + +One of the most commonly used action is [checkout](https://code.forgejo.org/actions/checkout#usage) which clones the repository that triggered a `workflow`. Another one is [setup-go](https://code.forgejo.org/actions/setup-go#usage) that will install Go. + +Just as any other program of function, an `Action` has pre-requisites to successfully be installed and run. When looking at re-using an existing `Action`, this is an important consideration. For instance [setup-go](https://code.forgejo.org/actions/setup-go) depends on NodeJS during installation. + +## Expressions + +In a `workflow` file strings that look like `${{ ... }}` are evaluated by the `Forgejo runner` and are called expressions. As a shortcut, `if: ${{ ... }}` is equivalent to `if: ...`, i.e the `${{ }}` surrounding the expression is implicit and can be stripped. [Checkout the example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-expression/.forgejo/workflows/test.yml) that illustrates expressions. + +### Literals + +- boolean: true or false +- null: null +- number: any number format supported by JSON +- string: enclosed in single quotes. Two single quotes + +### Logical operators + +| Operator | Description | +| -------- | --------------------- | +| `( )` | Logical grouping | +| `[ ]` | Index | +| `.` | Property de-reference | +| `!` | Not | +| `<` | Less than | +| `<=` | Less than or equal | +| `>` | Greater than | +| `>=` | Greater than or equal | +| `==` | Equal | +| `!=` | Not equal | +| `&&` | And | +| `\|\|` | Or | + +> **NOTE:** String comparisons are case insensitive. + +### Functions + +- `contains( search, item )`. Returns `true` if `search` contains `item`. If `search` is an array, this function returns `true` if the `item` is an element in the array. If `search` is a string, this function returns `true` if the `item` is a substring of `search`. This function is not case sensitive. Casts values to a string. +- `startsWith( searchString, searchValue )`. Returns `true` when `searchString` starts with `searchValue`. This function is not case sensitive. Casts values to a string. +- `endsWith( searchString, searchValue )`. Returns `true` if `searchString` ends with `searchValue`. This function is not case sensitive. Casts values to a string. +- `format( string, replaceValue0, replaceValue1, ..., replaceValueN)`. Replaces values in the `string`, with the variable `replaceValueN`. Variables in the `string` are specified using the `{N}` syntax, where `N` is an integer. You must specify at least one `replaceValue` and `string`. Escape curly braces using double braces. +- `join( array, optionalSeparator )`. The value for `array` can be an array or a string. All values in `array` are concatenated into a string. If you provide `optionalSeparator`, it is inserted between the concatenated values. Otherwise, the default separator `,` is used. Casts values to a string. +- `toJSON(value)`. Returns a pretty-print JSON representation of `value`. +- `fromJSON(value)`. Returns a JSON object or JSON data type for `value`. You can use this function to provide a JSON object as an evaluated expression or to convert environment variables from a string. +- `hashFiles(path)`. Returns a single hash for the set of files that matches the `path` pattern. You can provide a single `path` pattern or multiple `path` patterns separated by commas. The `path` is relative to the `GITHUB_WORKSPACE` directory and can only include files inside of the `GITHUB_WORKSPACE`. This function calculates an individual SHA-256 hash for each matched file, and then uses those hashes to calculate a final SHA-256 hash for the set of files. If the `path` pattern does not match any files, this returns an empty string. For more information about SHA-256, see "[SHA-2](https://en.wikipedia.org/wiki/SHA-2).". You shell globs to match file names. + +## Caching commonly used files + +When a `job` starts, it can communicate with the `Forgejo runner` to +fetch commonly used files that were saved by previous runs. For +instance the https://code.forgejo.org/actions/setup-go action will do +that by default to save downloading and compiling packages found in +`go.mod`. + +It is also possible to explicitly control what is cached and when +using the https://code.forgejo.org/actions/cache action. + +## Services + +PostgreSQL, redis and other services can conveniently be run from container images with something similar to (see the [full example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-service/.forgejo/workflows/test.yml)): + +```yaml +services: + pgsql: + image: postgres:15 + env: + POSTGRES_DB: test + POSTGRES_PASSWORD: postgres + ports: + - '5432:5432' +``` + +A container with the specified `image:` is run before the `job` starts and is terminated when it completes. The job can address the service using its name, in this case `pgsql`. + +# The list of runners and their tasks + +A `Forgejo runner` listens on a `Forgejo` instance, waiting for jobs. To figure out if a runner is available for a given repository, go to `/{owner}/{repository}/settings/actions/runners`. If there are none, you can run one for yourself on your laptop. + +![list of runners](../../../../images/v1.20/user/actions/list-of-runners.png) + +Some runners are **Global** and are available for every repository, others are only available for the repositories within a given user or organization. And there can even be runners dedicated to a single repository. The `Forgejo` administrator is the only one able to launch a **Global** runner. But the user who owns an organization can launch a runner without requiring any special permission. All they need to do is to get a runner registration token and install the runner on their own laptop or on a server of their choosing (see the [Forgejo Actions administrator guide](../../admin/actions) for more information). + +Clicking on the pencil icon next to a runner shows the list of tasks it executed, with the status and a link to display the details of the execution. + +![show the runners tasks](../../../../images/v1.20/user/actions/runner-tasks.png) + +# The list of tasks in a repository + +From the `Actions` tab in a repository, the list of ongoing and past tasks triggered by this repository is displayed with their status. + +![the list of actions in a repository](../../../../images/v1.20/user/actions/actions-list.png) + +Following the link on a task displays the logs and the `Re-run all jobs` button. It is also possible to re-run a specific job by hovering on it and clicking on the arrows. + +![the details of an action](../../../../images/v1.20/user/actions/actions-detail.png) + +# Tasks run from pull requests + +The first time a user proposes a pull request, the task is blocked to reduce the security risks. + +![blocked action](../../../../images/v1.20/user/actions/action-blocked.png) + +It can be **Approve**d by a maintainer of the project and there will be no need to unblocker future pull requests. + +![button to approve an action](../../../../images/v1.20/user/actions/action-approve.png) + # Secrets A repository, a user or an organization can hold secrets, a set of key/value pairs that are stored encrypted in the `Forgejo` database and revealed to the `workflows` as `${{ secrets.KEY }}`. They can be defined from the web interface: @@ -83,6 +198,21 @@ on: Not everything from https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows is implemented yet. Please refer to the [forgejo/actions package source code](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/modules/actions/workflows.go) and the [list of webhook event names](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/modules/webhook/type.go) to find out about supported triggers. +## env + +Set environment variables that are available in the workflow in the `env` `context` and as regular environment variables. + +```yaml +env: + KEY1: value1 + KEY2: value2 +``` + +- The expression `${{ env.KEY1 }}` will be evaluated to `value1` +- The environment variable `KEY1` will be set to `value1` + +[Checkout the example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-expression/.forgejo/workflows/test.yml). + ## jobs ### runs-on @@ -126,9 +256,11 @@ The `runs-on: self-hosted` label will run the jobs in a [LXC](https://linuxconta #### uses -Specifies the repository from which the `Action` will be cloned. +Specifies the repository from which the `Action` will be cloned or a directory where it can be found. -A relative `Action` such as `uses: actions/checkout@v3` will clone the repository at the URL composed by prepending the default actions URL which is https://code.forgejo.org/actions. It is the equivalent of providing the fully qualified URL `uses: https://code.forgejo.org/actions/checkout@v3`. In other words the following: +#### Remote actions + +A relative `Action` such as `uses: actions/checkout@v3` will clone the repository at the URL composed by prepending the default actions URL which is https://code.forgejo.org/. It is the equivalent of providing the fully qualified URL `uses: https://code.forgejo.org/actions/checkout@v3`. In other words the following: ```yaml on: [push] @@ -150,50 +282,102 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 ``` -# Concepts +When possible **it is strongly recommended to choose fully qualified +URLs** to avoid ambiguities. During installation, the `Forgejo' +instance may use another default URL and a workflow could fail because +it gets an outdated version from https://tooold.org/actions/checkout +instead. Or even a repository that does not contain the intended +action. -## Forgejo runner +#### Local actions -`Forgejo` itself does not run the `jobs`, it relies on the [Forgejo runner](https://code.forgejo.org/forgejo/runner) to do so. See the [Forgejo Actions administrator guide](../../admin/actions) for more information. +An action that begins with a `./` will be loaded from a directory +instead of being cloned from a repository. The structure of the +directory is otherwise the same as if it was located in a remote +repository. -## Actions +> **NOTE:** the most common mistake when using an action included in the repository under test is to forget to checkout the repository with `uses: actions/checkout@v3`. -An `Action` is a repository that contains the equivalent of a function in any programming language, with inputs and outputs as desccribed in the `action.yml` file at the root of the repository (see [this example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/action.yml)). +[Checkout the example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-local-action/). -One of the most commonly used action is [checkout](https://code.forgejo.org/actions/checkout#usage) which clones the repository that triggered a `workflow`. Another one is [setup-go](https://code.forgejo.org/actions/setup-go#usage) that will install Go. +# Debugging workflows with forgejo-runner exec -Just as any other program of function, an `Action` has pre-requisites to successfully be installed and run. When looking at re-using an existing `Action`, this is an important consideration. For instance [setup-go](https://code.forgejo.org/actions/setup-go) depends on NodeJS during installation. +To get a quicker debug loop when working on a workflow, it may be more +convenient to run them on your laptop using `forgejo-runner exec`. For +instance: -## Services - -PostgreSQL, redis and other services can conveniently be run from container images with something similar to (see the [full example](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-service/.forgejo/workflows/test.yml)): - -```yaml -services: - pgsql: - image: postgres:15 - env: - POSTGRES_DB: test - POSTGRES_PASSWORD: postgres - ports: - - '5432:5432' +```sh +$ git clone --depth 1 http://code.forgejo.org/forgejo/runner +$ cd runner +$ forgejo-runner exec --workflows .forgejo/workflows/test.yml --job lint +INFO[0000] Using default workflow event: push +INFO[0000] Planning job: lint +INFO[0000] cache handler listens on: http://192.168.1.20:44261 +INFO[0000] Start server on http://192.168.1.20:34567 +[checks/check and test] 🚀 Start image=node:16-bullseye +[checks/check and test] 🐳 docker pull image=node:16-bullseye platform= username= forcePull=false +[checks/check and test] 🐳 docker create image=node:16-bullseye platform= entrypoint=["/bin/sleep" "10800"] cmd=[] +[checks/check and test] 🐳 docker run image=node:16-bullseye platform= entrypoint=["/bin/sleep" "10800"] cmd=[] +[checks/check and test] ☁ git clone 'https://code.forgejo.org/actions/setup-go' # ref=v3 +[checks/check and test] ⭐ Run Main actions/setup-go@v3 +[checks/check and test] 🐳 docker cp src=/home/loic/.cache/act/actions-setup-go@v3/ dst=/var/run/act/actions/actions-setup-go@v3/ +... +| +| ==> Ok +| +[checks/check and test] ✅ Success - Main test +[checks/check and test] ⭐ Run Post actions/setup-go@v3 +[checks/check and test] 🐳 docker exec cmd=[node /var/run/act/actions/actions-setup-go@v3/dist/cache-save/index.js] user= workdir= +[checks/check and test] ✅ Success - Post actions/setup-go@v3 +[checks/check and test] Cleaning up services for job check and test +[checks/check and test] Cleaning up container for job check and test +[checks/check and test] Cleaning up network for job check and test, and network name is: FORGEJO-ACTIONS-TASK-push_WORKFLOW-checks_JOB-check-and-test-network +[checks/check and test] 🏁 Job succeeded ``` -A container with the specified `image:` is run before the `job` starts and is terminated when it completes. The job can address the service using its name, in this case `pgsql`. - # Examples -Each example is part of the [setup-forgejo](https://code.forgejo.org/actions/setup-forgejo/) action [test suite](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata). +Each example is part of the [setup-forgejo](https://code.forgejo.org/actions/setup-forgejo/) action [test suite](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata). They can be run locally with something similar to: + +```sh +$ git clone --depth 1 http://code.forgejo.org/actions/setup-forgejo +$ cd setup-forgejo +$ forgejo-runner exec --workflows testdata/example-expression/.forgejo/workflows/test.yml +INFO[0000] Using the only detected workflow event: push +INFO[0000] Planning jobs for event: push +INFO[0000] cache handler listens on: http://192.168.1.20:43773 +INFO[0000] Start server on http://192.168.1.20:34567 +[test.yml/test] 🚀 Start image=node:16-bullseye +[test.yml/test] 🐳 docker pull image=node:16-bullseye platform= username= forcePull=false +[test.yml/test] 🐳 docker create image=node:16-bullseye platform= entrypoint=["/bin/sleep" "10800"] cmd=[] +[test.yml/test] 🐳 docker run image=node:16-bullseye platform= entrypoint=["/bin/sleep" "10800"] cmd=[] +[test.yml/test] ⭐ Run Main set -x +test "KEY1=value1" = "KEY1=value1" +test "KEY2=$KEY2" = "KEY2=value2" +[test.yml/test] 🐳 docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/0] user= workdir= +| + test KEY1=value1 = KEY1=value1 +| + test KEY2=value2 = KEY2=value2 +[test.yml/test] ✅ Success - Main set -x +test "KEY1=value1" = "KEY1=value1" +test "KEY2=$KEY2" = "KEY2=value2" +[test.yml/test] Cleaning up services for job test +[test.yml/test] Cleaning up container for job test +[test.yml/test] Cleaning up network for job test, and network name is: FORGEJO-ACTIONS-TASK-push_WORKFLOW-test-yml_JOB-test-network +[test.yml/test] 🏁 Job succeeded +``` - [Echo](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-echo/.forgejo/workflows/test.yml) - a single step that prints one sentence. +- [Expression](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-expression/.forgejo/workflows/test.yml) - a collection of various forms of expression +- [Local actions](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-local-action/.forgejo) - using an action found in a directory instead of a remote repository - [PostgreSQL service](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-service/.forgejo/workflows/test.yml) - a PostgreSQL service and a connection to display the (empty) list of tables of the default database. - [Choosing the image with `container`](https://code.forgejo.org/actions/setup-forgejo/src/branch/main/testdata/example-container/.forgejo/workflows/test.yml) - replacing the `runs-on: docker` image with the `alpine:3.18` image using `container:`. # Glossary -- **workflow:** a file in the `.forgejo/workflows` directory that contains **jobs**. -- **job:** a sequential set of **steps**. -- **step:** a command the **runner** is required to carry out. - **action:** a repository that can be used in a way similar to a function in any programming language to run a single **step**. -- **runner:** the [Forgejo runner](https://code.forgejo.org/forgejo/runner) daemon tasked to execute the **workflows**. +- **expression:** a string enclosed in `${{ ... }}` and evaluated at runtime +- **job:** a sequential set of **steps**. - **label** the kind of machine that is matched against the value of `runs-on` in a **workflow**. +- **runner:** the [Forgejo runner](https://code.forgejo.org/forgejo/runner) daemon tasked to execute the **workflows**. +- **step:** a command the **runner** is required to carry out. +- **workflow or task:** a file in the `.forgejo/workflows` directory that contains **jobs**.