# `github_actions`

| Package | Kind | Provides the role | Needs | Choose with |
| --- | --- | --- | --- | --- |
| [`smf_github_actions`](https://pub.dev/packages/smf_github_actions) | infrastructure | CI | nothing | `-m github_actions` |

`github_actions` writes what the CI role says into a workflow of [GitHub Actions](https://docs.github.com/actions), which runs once you push the app to GitHub. What runs, and how the values of each environment reach a build, is in [CI](https://doc.saymyframe.com/guides/ci.md).

## What it adds to the app

| In the app | What it is |
| --- | --- |
| `.github/workflows/ci.yml` | The workflow, with the jobs `checks` and `build` |
| The section "GitHub Actions" of the README | How to start a build, where the values of each environment go and how to stay on one version of Flutter |

Whichever module provides it, the role adds the section "Continuous integration" of the README, and in an app with [the values in `.env`](https://doc.saymyframe.com/guides/env.md) the script `tool/write_env.dart`.

In the [guide for coding agents](https://doc.saymyframe.com/guides/coding-agents.md) of the app, the role says that CI runs the commands of its section, so an agent keeps them passing. The module adds where the jobs are and how a new key reaches a build.

The module adds no package and has no step after generation or by hand. The checks pass on the first push without any setup.

## The workflow

| Job | Runs on | Does |
| --- | --- | --- |
| `checks` | each push to a branch | Sets up Flutter and runs the checks of the role, within 20 minutes |
| `build` | `workflow_dispatch`, from the Actions tab or `gh workflow run` | In the GitHub environment that you pick: sets up Java and Flutter, writes `.env` from the variables of that environment, builds the release APK and keeps it as an artifact, within 45 minutes. The upload fails when the file is missing. |

Both run on `ubuntu-latest`, and the workflow reads the repository and nothing else (`contents: read`). A new push cancels the run of an older push of its branch, and each environment has a group of its own for its builds.

Each key of the app is a line of the step that writes `.env`, such as `REST_BASE_URL: ${{ vars.REST_BASE_URL }}`. No `run:` line has an expression, so a value never becomes a part of the text of a script. Keep it that way in what you add: pass a value through `env:` of the step, and read it as a variable of the shell.

Each action is pinned to a full commit, with its tag in a comment, and the app gets no `dependabot.yml`, so what SMF puts into your repository does not change under you. Nothing updates the pins. Change the commit and the tag together to update an action.

## Choosing it

`smf create` asks which module provides CI, and the answer may be none. To choose it without the question:

```bash
smf create my_app -m github_actions
```
