# Scripts and CI

Use assent-cli with an agent key from shell scripts, scheduled jobs and CI, to ask before a risky step, wait for the answer and report runs.

The `assent` command lets a script or CI job ask you before a risky step and wait for your answer, check your standing rules, and report each run. It reads its agent key from the environment, so it never needs an interactive login.

## Set it up

1. In Assent, open **Agents**, choose **Add agent**, name it after the job (for example `Release pipeline`) and copy its agent key. It starts with `oak_` and is shown once.
2. Store the key as a secret in your CI, named `ASSENT_AGENT_KEY`. On your own computer, export it or save it in `~/.assent/config.json` (see [Command line](https://docs.specvista.com/assent/cli.md#configure)).
3. Install the command line. It needs Node.js 20 or later.

```bash
npm install -g assent-cli
```

4. Check the key:

```bash
assent whoami
```

It prints one line of JSON describing the agent. Exit code 5 means the key is missing or wrong.

## Ask before a risky step

```bash
assent ask \
  --title "Deploy build 512 to production?" \
  --why "All checks passed on the release branch" \
  --rule-action deploy:web --target production \
  --dedupe deploy:web:512 \
  --wait --timeout 1800
```

- `--wait` checks every 15 seconds until you answer, for at most `--timeout` seconds (default 3600). When you answer, it marks the answer as picked up and prints the ask with its `answer`.
- An approval comes back with `answer.actionId` `done`; a decline with `decline`. Act only on `done`.
- `--rule-action` and `--target` let you answer **Always** or **Never**, so the next matching ask is answered for you.
- `--dedupe` makes a retried job reuse the same ask instead of sending a second one.

Exit codes for `ask --wait`:

| Code | Meaning |
|---|---|
| 0 | Answered (read `answer.actionId` to see what you chose) |
| 3 | The ask expired or was closed without an answer, or a paired computer already picked the answer up |
| 5 | No agent key, or the key is not valid |
| 6 | No answer within `--timeout` |
| 69 | Assent unreachable: network failure, timeout, rate limit or a server error |

Treat anything other than an answer of `done` as "do not go ahead".

## GitHub Actions

```yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 45
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Ask before deploying
        env:
          ASSENT_AGENT_KEY: ${{ secrets.ASSENT_AGENT_KEY }}
        run: |
          ACTION=$(npx --yes assent-cli@latest ask \
            --title "Deploy ${GITHUB_SHA::7} to production?" \
            --why "The release workflow passed on ${GITHUB_REF_NAME}" \
            --rule-action deploy:web --target production \
            --dedupe "deploy:web:${GITHUB_SHA}" \
            --wait --timeout 1800 --get answer | jq -r '.actionId // empty')
          test "$ACTION" = "done"
      - run: ./deploy.sh
```

`npx` runs the latest `assent-cli` without a global install. `--get answer` prints just the answer object. If you decline, or the ask times out (exit 6) or expires (exit 3), `ACTION` is not `done`, so `test` fails the step and the deploy never runs.

## Windows and PowerShell

The commands are the same on Windows. Set the key with `$env:ASSENT_AGENT_KEY = "oak_..."`, and check the exit code with `$LASTEXITCODE`:

```powershell
$answer = assent ask --title "Run the clean-up job?" --why "It deletes builds older than 30 days" --wait --timeout 900 --get answer | ConvertFrom-Json
if ($LASTEXITCODE -ne 0 -or $answer.actionId -ne "done") { exit 1 }
```

If PowerShell refuses to run `assent.ps1` because running scripts is disabled, call `assent.cmd` instead.

## Check your rules first

When the action might already be covered by one of your standing rules, check before asking:

```bash
assent rules check --action deploy:web --target production
```

Exit 0 means a rule allows it, 10 means a rule forbids it, and 11 means no rule covers it, so ask. See [Rules](https://docs.specvista.com/assent/rules.md).

## Report each run

Scheduled jobs can show up in **Runs** with how they ended:

```bash
RUN=$(assent run start --summary "Nightly clean-up" --get uuid)
./clean-up.sh > clean-up.log 2>&1
assent run finish "$RUN" --exit-code $? --summary "Nightly clean-up" --log-file clean-up.log
```

`run finish` redacts emails, keys, tokens, phone numbers and home paths from the summary and log tail before sending.

## Keep two jobs apart

```bash
assent lock acquire deploy:web --ttl 45 --wait 90 && ./deploy.sh; assent lock release deploy:web
```

If another agent holds the lock after 90 seconds, `lock acquire` exits with 3 and the deploy does not start.

## When Assent is unreachable

Decide what a job should do if Assent cannot be reached (exit 69). For a risky step, stop: never treat "no answer" as approval. For reporting commands such as `run start` and `run finish`, carry on with the job.

[Command line](https://docs.specvista.com/assent/cli.md) lists every command, option, setting and exit code.
