@ferrflow/doc 7.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs-en/ci/github-actions.md +120 -0
- package/docs-en/ci/gitlab-ci.md +90 -0
- package/docs-en/ci/hosted-bot.md +82 -0
- package/docs-en/ci/pipeline-triggers.md +287 -0
- package/docs-en/configuration/config-file.md +1259 -0
- package/docs-en/configuration/formats.md +220 -0
- package/docs-en/configuration/monorepo.md +390 -0
- package/docs-en/installation.md +56 -0
- package/docs-en/introduction.md +56 -0
- package/docs-en/quickstart.md +66 -0
- package/docs-en/reference/api.md +106 -0
- package/docs-en/reference/cli.md +483 -0
- package/docs-en/reference/conventional-commits.md +103 -0
- package/docs-en/reference/errors.md +508 -0
- package/docs-en/verifying-releases.md +97 -0
- package/docs-fr/ci/github-actions.md +109 -0
- package/docs-fr/ci/gitlab-ci.md +77 -0
- package/docs-fr/ci/hosted-bot.md +82 -0
- package/docs-fr/ci/pipeline-triggers.md +238 -0
- package/docs-fr/configuration/config-file.md +839 -0
- package/docs-fr/configuration/formats.md +163 -0
- package/docs-fr/configuration/monorepo.md +357 -0
- package/docs-fr/installation.md +56 -0
- package/docs-fr/introduction.md +54 -0
- package/docs-fr/quickstart.md +63 -0
- package/docs-fr/reference/api.md +106 -0
- package/docs-fr/reference/cli.md +407 -0
- package/docs-fr/reference/conventional-commits.md +103 -0
- package/docs-fr/reference/errors.md +378 -0
- package/docs-fr/verifying-releases.md +97 -0
- package/docs-fr-v4/ci/github-actions.md +106 -0
- package/docs-fr-v4/ci/gitlab-ci.md +77 -0
- package/docs-fr-v4/ci/pipeline-triggers.md +214 -0
- package/docs-fr-v4/configuration/config-file.md +769 -0
- package/docs-fr-v4/configuration/formats.md +128 -0
- package/docs-fr-v4/configuration/monorepo.md +324 -0
- package/docs-fr-v4/installation.md +48 -0
- package/docs-fr-v4/introduction.md +54 -0
- package/docs-fr-v4/legal/telemetry.md +65 -0
- package/docs-fr-v4/quickstart.md +63 -0
- package/docs-fr-v4/reference/cli.md +130 -0
- package/docs-fr-v4/reference/conventional-commits.md +67 -0
- package/docs-fr-v4/reference/errors.md +372 -0
- package/docs-fr-v5/ci/github-actions.md +109 -0
- package/docs-fr-v5/ci/gitlab-ci.md +77 -0
- package/docs-fr-v5/ci/hosted-bot.md +82 -0
- package/docs-fr-v5/ci/pipeline-triggers.md +238 -0
- package/docs-fr-v5/configuration/config-file.md +812 -0
- package/docs-fr-v5/configuration/formats.md +150 -0
- package/docs-fr-v5/configuration/monorepo.md +357 -0
- package/docs-fr-v5/installation.md +56 -0
- package/docs-fr-v5/introduction.md +54 -0
- package/docs-fr-v5/legal/telemetry.md +26 -0
- package/docs-fr-v5/quickstart.md +63 -0
- package/docs-fr-v5/reference/api.md +106 -0
- package/docs-fr-v5/reference/cli.md +356 -0
- package/docs-fr-v5/reference/conventional-commits.md +88 -0
- package/docs-fr-v5/reference/errors.md +378 -0
- package/docs-fr-v5/verifying-releases.md +97 -0
- package/docs-fr-v6/ci/github-actions.md +109 -0
- package/docs-fr-v6/ci/gitlab-ci.md +77 -0
- package/docs-fr-v6/ci/hosted-bot.md +82 -0
- package/docs-fr-v6/ci/pipeline-triggers.md +238 -0
- package/docs-fr-v6/configuration/config-file.md +813 -0
- package/docs-fr-v6/configuration/formats.md +150 -0
- package/docs-fr-v6/configuration/monorepo.md +357 -0
- package/docs-fr-v6/installation.md +56 -0
- package/docs-fr-v6/introduction.md +54 -0
- package/docs-fr-v6/quickstart.md +63 -0
- package/docs-fr-v6/reference/api.md +106 -0
- package/docs-fr-v6/reference/cli.md +356 -0
- package/docs-fr-v6/reference/conventional-commits.md +88 -0
- package/docs-fr-v6/reference/errors.md +378 -0
- package/docs-fr-v6/verifying-releases.md +97 -0
- package/docs-v0/ci/github-actions.md +77 -0
- package/docs-v0/ci/gitlab-ci.md +59 -0
- package/docs-v0/configuration/config-file.md +97 -0
- package/docs-v0/configuration/formats.md +86 -0
- package/docs-v0/configuration/monorepo.md +59 -0
- package/docs-v0/installation.md +48 -0
- package/docs-v0/introduction.md +34 -0
- package/docs-v0/legal/telemetry.md +63 -0
- package/docs-v0/quickstart.md +58 -0
- package/docs-v0/reference/cli.md +95 -0
- package/docs-v0/reference/conventional-commits.md +68 -0
- package/docs-v1/ci/github-actions.md +76 -0
- package/docs-v1/ci/gitlab-ci.md +58 -0
- package/docs-v1/configuration/config-file.md +515 -0
- package/docs-v1/configuration/formats.md +115 -0
- package/docs-v1/configuration/monorepo.md +246 -0
- package/docs-v1/installation.md +48 -0
- package/docs-v1/introduction.md +39 -0
- package/docs-v1/legal/telemetry.md +63 -0
- package/docs-v1/quickstart.md +62 -0
- package/docs-v1/reference/cli.md +128 -0
- package/docs-v1/reference/conventional-commits.md +67 -0
- package/docs-v2/ci/github-actions.md +117 -0
- package/docs-v2/ci/gitlab-ci.md +90 -0
- package/docs-v2/ci/pipeline-triggers.md +263 -0
- package/docs-v2/configuration/config-file.md +806 -0
- package/docs-v2/configuration/formats.md +98 -0
- package/docs-v2/configuration/monorepo.md +324 -0
- package/docs-v2/installation.md +48 -0
- package/docs-v2/introduction.md +40 -0
- package/docs-v2/legal/telemetry.md +66 -0
- package/docs-v2/quickstart.md +63 -0
- package/docs-v2/reference/cli.md +130 -0
- package/docs-v2/reference/conventional-commits.md +67 -0
- package/docs-v2/reference/errors.md +500 -0
- package/docs-v2/self-hosting.md +101 -0
- package/docs-v3/ci/github-actions.md +117 -0
- package/docs-v3/ci/gitlab-ci.md +90 -0
- package/docs-v3/ci/pipeline-triggers.md +263 -0
- package/docs-v3/configuration/config-file.md +806 -0
- package/docs-v3/configuration/formats.md +99 -0
- package/docs-v3/configuration/monorepo.md +324 -0
- package/docs-v3/installation.md +48 -0
- package/docs-v3/introduction.md +40 -0
- package/docs-v3/legal/telemetry.md +66 -0
- package/docs-v3/quickstart.md +66 -0
- package/docs-v3/reference/cli.md +161 -0
- package/docs-v3/reference/conventional-commits.md +67 -0
- package/docs-v3/reference/errors.md +502 -0
- package/docs-v3/self-hosting.md +137 -0
- package/docs-v4/ci/github-actions.md +117 -0
- package/docs-v4/ci/gitlab-ci.md +90 -0
- package/docs-v4/ci/pipeline-triggers.md +263 -0
- package/docs-v4/configuration/config-file.md +850 -0
- package/docs-v4/configuration/formats.md +182 -0
- package/docs-v4/configuration/monorepo.md +324 -0
- package/docs-v4/installation.md +48 -0
- package/docs-v4/introduction.md +56 -0
- package/docs-v4/legal/telemetry.md +65 -0
- package/docs-v4/quickstart.md +66 -0
- package/docs-v4/reference/cli.md +161 -0
- package/docs-v4/reference/conventional-commits.md +67 -0
- package/docs-v4/reference/errors.md +502 -0
- package/docs-v4/self-hosting.md +137 -0
- package/docs-v5/ci/github-actions.md +120 -0
- package/docs-v5/ci/gitlab-ci.md +90 -0
- package/docs-v5/ci/hosted-bot.md +82 -0
- package/docs-v5/ci/pipeline-triggers.md +287 -0
- package/docs-v5/configuration/config-file.md +1133 -0
- package/docs-v5/configuration/formats.md +206 -0
- package/docs-v5/configuration/monorepo.md +390 -0
- package/docs-v5/installation.md +56 -0
- package/docs-v5/introduction.md +56 -0
- package/docs-v5/legal/telemetry.md +26 -0
- package/docs-v5/quickstart.md +66 -0
- package/docs-v5/reference/api.md +106 -0
- package/docs-v5/reference/cli.md +431 -0
- package/docs-v5/reference/conventional-commits.md +88 -0
- package/docs-v5/reference/errors.md +508 -0
- package/docs-v5/verifying-releases.md +97 -0
- package/docs-v6/ci/github-actions.md +120 -0
- package/docs-v6/ci/gitlab-ci.md +90 -0
- package/docs-v6/ci/hosted-bot.md +82 -0
- package/docs-v6/ci/pipeline-triggers.md +287 -0
- package/docs-v6/configuration/config-file.md +1134 -0
- package/docs-v6/configuration/formats.md +206 -0
- package/docs-v6/configuration/monorepo.md +390 -0
- package/docs-v6/installation.md +56 -0
- package/docs-v6/introduction.md +56 -0
- package/docs-v6/quickstart.md +66 -0
- package/docs-v6/reference/api.md +106 -0
- package/docs-v6/reference/cli.md +431 -0
- package/docs-v6/reference/conventional-commits.md +88 -0
- package/docs-v6/reference/errors.md +508 -0
- package/docs-v6/verifying-releases.md +97 -0
- package/package.json +17 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Self-hosting
|
|
3
|
+
description: Run FerrFlow on your own infrastructure with a single Docker image.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The self-host bundle is a single Docker image that contains the API and the
|
|
7
|
+
dashboard. The API serves the dashboard assets on the same origin, so there is
|
|
8
|
+
only one container to run and no CORS configuration to manage.
|
|
9
|
+
|
|
10
|
+
Image: `ghcr.io/ferrlabs/ferrflow-selfhost:latest`
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
- Docker 24+ and Docker Compose
|
|
15
|
+
- A PostgreSQL 16 database with the TimescaleDB extension (the reference compose
|
|
16
|
+
file below provisions one for you)
|
|
17
|
+
|
|
18
|
+
## Quickstart with Docker Compose
|
|
19
|
+
|
|
20
|
+
Download the reference compose file and environment template from the
|
|
21
|
+
[Application repository](https://github.com/FerrLabs/Application):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -O https://raw.githubusercontent.com/FerrLabs/Application/main/docker-compose.selfhost.yml
|
|
25
|
+
curl -o .env https://raw.githubusercontent.com/FerrLabs/Application/main/.env.example.selfhost
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Generate secrets and edit `.env`:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Database password (any long random string)
|
|
32
|
+
echo "DB_PASSWORD=$(openssl rand -base64 32)" >> .env.secrets
|
|
33
|
+
# JWT signing secret
|
|
34
|
+
echo "JWT_SECRET=$(openssl rand -base64 64)" >> .env.secrets
|
|
35
|
+
# AES-256-GCM key for encrypting secrets at rest (must be base64-encoded 32 bytes)
|
|
36
|
+
echo "ENCRYPTION_KEY=$(openssl rand -base64 32)" >> .env.secrets
|
|
37
|
+
# HMAC secret used by the FerrFlow CLI telemetry endpoint
|
|
38
|
+
echo "FERRFLOW_HMAC_SECRET=$(openssl rand -hex 32)" >> .env.secrets
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Merge `.env.secrets` into `.env` manually, then start the stack:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
docker compose -f docker-compose.selfhost.yml up -d
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The dashboard is now available on `http://localhost:3000`.
|
|
48
|
+
|
|
49
|
+
## Environment variables
|
|
50
|
+
|
|
51
|
+
| Variable | Required | Purpose |
|
|
52
|
+
| -------------------------- | ---------------------- | ----------------------------------------------------- |
|
|
53
|
+
| `DATABASE_URL` | yes | Postgres connection string |
|
|
54
|
+
| `JWT_SECRET` | yes | Signing key for session JWTs |
|
|
55
|
+
| `ENCRYPTION_KEY` | yes | 32-byte base64 key for the secrets at-rest encryption |
|
|
56
|
+
| `FERRFLOW_HMAC_SECRET` | yes | HMAC key for CLI telemetry ingestion |
|
|
57
|
+
| `SERVER_HOST` | no (default `0.0.0.0`) | Bind address |
|
|
58
|
+
| `SERVER_PORT` | no (default `3000`) | Bind port |
|
|
59
|
+
| `DATABASE_MAX_CONNECTIONS` | no (default `10`) | Postgres pool size |
|
|
60
|
+
| `RATE_LIMIT_REQUESTS` | no (default `60`) | Requests per minute before rate-limiting |
|
|
61
|
+
| `RUST_LOG` | no (default `info`) | Log level |
|
|
62
|
+
|
|
63
|
+
## Using an external Postgres
|
|
64
|
+
|
|
65
|
+
Remove the `db` service and the `depends_on` block from the compose file, then
|
|
66
|
+
point `DATABASE_URL` at your existing instance. The TimescaleDB extension is
|
|
67
|
+
required — create it once with:
|
|
68
|
+
|
|
69
|
+
```sql
|
|
70
|
+
CREATE EXTENSION IF NOT EXISTS timescaledb;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Migrations run automatically on startup.
|
|
74
|
+
|
|
75
|
+
## Reverse proxy and TLS
|
|
76
|
+
|
|
77
|
+
Terminate TLS at a proxy in front of the container. Example Caddyfile:
|
|
78
|
+
|
|
79
|
+
```caddy
|
|
80
|
+
ferrflow.example.com {
|
|
81
|
+
reverse_proxy localhost:3000
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
No CORS origins need to be whitelisted because the browser only talks to the
|
|
86
|
+
single proxy origin.
|
|
87
|
+
|
|
88
|
+
## Updating
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
docker compose -f docker-compose.selfhost.yml pull
|
|
92
|
+
docker compose -f docker-compose.selfhost.yml up -d
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Database migrations are applied on startup. Take a database backup before
|
|
96
|
+
upgrading across a major version.
|
|
97
|
+
|
|
98
|
+
## Health check
|
|
99
|
+
|
|
100
|
+
`GET /health` returns `200` once the API has connected to Postgres and applied
|
|
101
|
+
migrations.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GitHub Actions
|
|
3
|
+
description: Run FerrFlow releases automatically in GitHub Actions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Using the official action
|
|
7
|
+
|
|
8
|
+
The easiest way to use FerrFlow in GitHub Actions is the `FerrLabs/ferrflow@v3` action. It installs the binary and runs `ferrflow release` automatically.
|
|
9
|
+
|
|
10
|
+
```yaml title=".github/workflows/release.yml"
|
|
11
|
+
name: Release
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
branches: [main]
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
release:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write # required to push tags and create releases
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0 # full history needed for commit scanning
|
|
26
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
|
|
28
|
+
- uses: FerrLabs/ferrflow@v3
|
|
29
|
+
env:
|
|
30
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
<aside class="ferr-aside ferr-aside--warning"><div class="ferr-aside__body"><p><code>fetch-depth: 0</code> is required. Without it, FerrFlow cannot find previous tags and will treat every commit as new.</p>
|
|
34
|
+
</div></aside>
|
|
35
|
+
|
|
36
|
+
## Permissions
|
|
37
|
+
|
|
38
|
+
FerrFlow needs `contents: write` to:
|
|
39
|
+
|
|
40
|
+
- Push version bump commits
|
|
41
|
+
- Create and push git tags
|
|
42
|
+
- Create GitHub Releases
|
|
43
|
+
|
|
44
|
+
If your repository has branch protection rules, create a dedicated token with the necessary permissions and pass it as `FERRFLOW_TOKEN` or configure the action's `token` input.
|
|
45
|
+
|
|
46
|
+
## Accessing the release output
|
|
47
|
+
|
|
48
|
+
The action exposes the new version as an output you can use in downstream steps:
|
|
49
|
+
|
|
50
|
+
```yaml title=".github/workflows/release.yml"
|
|
51
|
+
- uses: FerrLabs/ferrflow@v3
|
|
52
|
+
id: ferrflow
|
|
53
|
+
env:
|
|
54
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
55
|
+
|
|
56
|
+
- name: Build Docker image
|
|
57
|
+
if: steps.ferrflow.outputs.version != ''
|
|
58
|
+
run: |
|
|
59
|
+
docker build -t myimage:${{ steps.ferrflow.outputs.version }} .
|
|
60
|
+
docker push myimage:${{ steps.ferrflow.outputs.version }}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Skip CI on release commits
|
|
64
|
+
|
|
65
|
+
FerrFlow commits version bumps with `[skip ci]` in the message by default to prevent infinite loops. No extra configuration needed.
|
|
66
|
+
|
|
67
|
+
## PR preview comments
|
|
68
|
+
|
|
69
|
+
FerrFlow can post a comment on every pull request showing what versions will be bumped when the PR is merged. The comment is automatically updated on each push.
|
|
70
|
+
|
|
71
|
+
```yaml title=".github/workflows/preview.yml"
|
|
72
|
+
name: FerrFlow Preview
|
|
73
|
+
|
|
74
|
+
on:
|
|
75
|
+
pull_request:
|
|
76
|
+
|
|
77
|
+
permissions:
|
|
78
|
+
contents: read
|
|
79
|
+
pull-requests: write
|
|
80
|
+
|
|
81
|
+
jobs:
|
|
82
|
+
preview:
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v6
|
|
86
|
+
with:
|
|
87
|
+
fetch-depth: 0
|
|
88
|
+
- uses: FerrLabs/ferrflow@v3
|
|
89
|
+
with:
|
|
90
|
+
mode: preview
|
|
91
|
+
env:
|
|
92
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The comment looks like:
|
|
96
|
+
|
|
97
|
+
> **FerrFlow Release Preview**
|
|
98
|
+
>
|
|
99
|
+
> | Package | Current | Next | Bump |
|
|
100
|
+
> | ------- | ------- | ------- | ----- |
|
|
101
|
+
> | api | `1.5.0` | `1.6.0` | minor |
|
|
102
|
+
> | site | `1.8.0` | `1.8.1` | patch |
|
|
103
|
+
>
|
|
104
|
+
> Based on 3 commit(s).
|
|
105
|
+
|
|
106
|
+
If no releasable changes are detected, the comment says so.
|
|
107
|
+
|
|
108
|
+
## Monorepo example
|
|
109
|
+
|
|
110
|
+
In a monorepo, FerrFlow releases each changed package in a single run:
|
|
111
|
+
|
|
112
|
+
```yaml title=".github/workflows/release.yml"
|
|
113
|
+
- uses: FerrLabs/ferrflow@v3
|
|
114
|
+
env:
|
|
115
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
116
|
+
# Creates api@v1.3.0 and site@v0.5.1 in one step if both changed
|
|
117
|
+
```
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GitLab CI
|
|
3
|
+
description: Run FerrFlow releases automatically in GitLab CI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Using the Docker image
|
|
7
|
+
|
|
8
|
+
The official FerrFlow Docker image ships the binary and can be used directly as a GitLab CI job image.
|
|
9
|
+
|
|
10
|
+
```yaml title=".gitlab-ci.yml"
|
|
11
|
+
release:
|
|
12
|
+
image: ghcr.io/ferrlabs/ferrflow:latest
|
|
13
|
+
stage: release
|
|
14
|
+
script:
|
|
15
|
+
- ferrflow release
|
|
16
|
+
variables:
|
|
17
|
+
GITLAB_TOKEN: $CI_JOB_TOKEN
|
|
18
|
+
rules:
|
|
19
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
20
|
+
when: on_success
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
<aside class="ferr-aside ferr-aside--warning"><div class="ferr-aside__body"><p>Make sure your CI runner clones with full history. Add <code>GIT_DEPTH: 0</code> to the job variables to disable shallow cloning.</p>
|
|
24
|
+
</div></aside>
|
|
25
|
+
|
|
26
|
+
## Full history
|
|
27
|
+
|
|
28
|
+
```yaml title=".gitlab-ci.yml"
|
|
29
|
+
release:
|
|
30
|
+
image: ghcr.io/ferrlabs/ferrflow:latest
|
|
31
|
+
variables:
|
|
32
|
+
GIT_DEPTH: 0 # full history — required for tag scanning
|
|
33
|
+
GITLAB_TOKEN: $CI_JOB_TOKEN
|
|
34
|
+
script:
|
|
35
|
+
- ferrflow release
|
|
36
|
+
rules:
|
|
37
|
+
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Using a deploy token
|
|
41
|
+
|
|
42
|
+
If `CI_JOB_TOKEN` doesn't have permission to push tags, create a project deploy token with `write_repository` access and store it as a CI variable:
|
|
43
|
+
|
|
44
|
+
```yaml title=".gitlab-ci.yml"
|
|
45
|
+
release:
|
|
46
|
+
image: ghcr.io/ferrlabs/ferrflow:latest
|
|
47
|
+
variables:
|
|
48
|
+
GIT_DEPTH: 0
|
|
49
|
+
GITLAB_TOKEN: $FERRFLOW_DEPLOY_TOKEN # CI variable with write_repository access
|
|
50
|
+
script:
|
|
51
|
+
- ferrflow release
|
|
52
|
+
rules:
|
|
53
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## MR preview comments
|
|
57
|
+
|
|
58
|
+
FerrFlow can post a comment on every merge request showing what versions will be bumped when the MR is merged. The comment is automatically updated on each push.
|
|
59
|
+
|
|
60
|
+
```yaml title=".gitlab-ci.yml"
|
|
61
|
+
ferrflow-preview:
|
|
62
|
+
image: ghcr.io/ferrlabs/ferrflow:latest
|
|
63
|
+
stage: test
|
|
64
|
+
variables:
|
|
65
|
+
GIT_DEPTH: 0
|
|
66
|
+
GITLAB_TOKEN: $CI_JOB_TOKEN
|
|
67
|
+
script:
|
|
68
|
+
- ferrflow check --comment
|
|
69
|
+
rules:
|
|
70
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The comment looks like:
|
|
74
|
+
|
|
75
|
+
> **FerrFlow Release Preview**
|
|
76
|
+
>
|
|
77
|
+
> | Package | Current | Next | Bump |
|
|
78
|
+
> | ------- | ------- | ------- | ----- |
|
|
79
|
+
> | api | `1.5.0` | `1.6.0` | minor |
|
|
80
|
+
>
|
|
81
|
+
> Based on 2 commit(s).
|
|
82
|
+
|
|
83
|
+
If no releasable changes are detected, the comment says so.
|
|
84
|
+
|
|
85
|
+
<aside class="ferr-aside ferr-aside--note"><div class="ferr-aside__body"><p><code>CI_JOB_TOKEN</code> has permission to post MR notes by default. If your project restricts this, use a project access token with <code>api</code> scope stored as a CI variable.</p>
|
|
86
|
+
</div></aside>
|
|
87
|
+
|
|
88
|
+
## GitLab Releases
|
|
89
|
+
|
|
90
|
+
When `GITLAB_TOKEN` is set, FerrFlow creates a GitLab Release with the generated changelog as release notes, matching the behaviour of the GitHub integration.
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Pipeline Triggers
|
|
3
|
+
description: Choose the right CI trigger strategy for your FerrFlow releases.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
FerrFlow works with any CI trigger strategy. This page covers the most common patterns, when to use each one, and how they interact with `releaseCommitMode`.
|
|
7
|
+
|
|
8
|
+
## Push to main
|
|
9
|
+
|
|
10
|
+
The simplest setup: run `ferrflow release` on every push to the default branch. FerrFlow decides whether a release is needed based on the commits since the last tag.
|
|
11
|
+
|
|
12
|
+
```yaml title=".github/workflows/release.yml"
|
|
13
|
+
name: Release
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
push:
|
|
17
|
+
branches: [main]
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
# Skip release commits to avoid infinite loops
|
|
23
|
+
if: "!startsWith(github.event.head_commit.message, 'chore(release):')"
|
|
24
|
+
permissions:
|
|
25
|
+
contents: write
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v6
|
|
28
|
+
with:
|
|
29
|
+
fetch-depth: 0
|
|
30
|
+
token: ${{ secrets.FERRFLOW_TOKEN }}
|
|
31
|
+
|
|
32
|
+
- uses: FerrLabs/ferrflow@v3
|
|
33
|
+
env:
|
|
34
|
+
GITHUB_TOKEN: ${{ secrets.FERRFLOW_TOKEN }}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**When to use:** Most projects. Simple, predictable, fully automated.
|
|
38
|
+
|
|
39
|
+
**Trade-offs:** Every push to main triggers a workflow run, even if no release is needed. FerrFlow exits early when there are no releasable commits, so the cost is minimal.
|
|
40
|
+
|
|
41
|
+
**Works with:** `releaseCommitMode: commit` (default) or `none`.
|
|
42
|
+
|
|
43
|
+
## Tag-triggered
|
|
44
|
+
|
|
45
|
+
Run your build/deploy pipeline when FerrFlow creates a new tag. This separates the release step (tagging) from the downstream steps (building, publishing, deploying).
|
|
46
|
+
|
|
47
|
+
```yaml title=".github/workflows/build.yml"
|
|
48
|
+
name: Build & Publish
|
|
49
|
+
|
|
50
|
+
on:
|
|
51
|
+
push:
|
|
52
|
+
tags:
|
|
53
|
+
- 'v*' # single-repo: v1.2.0
|
|
54
|
+
- '*@v*' # monorepo: api@v1.2.0, site@v0.5.1
|
|
55
|
+
|
|
56
|
+
jobs:
|
|
57
|
+
build:
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v6
|
|
61
|
+
|
|
62
|
+
- name: Extract version from tag
|
|
63
|
+
id: version
|
|
64
|
+
run: |
|
|
65
|
+
TAG="${GITHUB_REF_NAME}"
|
|
66
|
+
VERSION="${TAG##*v}"
|
|
67
|
+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
68
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
69
|
+
|
|
70
|
+
- name: Build
|
|
71
|
+
run: echo "Building version ${{ steps.version.outputs.version }}"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**When to use:** When you want to decouple versioning from build/deploy. Common for Docker image builds, npm publishing, or binary releases.
|
|
75
|
+
|
|
76
|
+
**Trade-offs:** Requires two workflows: one for the release (push-to-main) and one for the downstream build (tag-triggered). Adds a few seconds of latency between the tag push and the build start.
|
|
77
|
+
|
|
78
|
+
### Monorepo: per-package builds
|
|
79
|
+
|
|
80
|
+
In a monorepo, use tag patterns to build only the package that was released:
|
|
81
|
+
|
|
82
|
+
```yaml title=".github/workflows/build.yml"
|
|
83
|
+
name: Build Package
|
|
84
|
+
|
|
85
|
+
on:
|
|
86
|
+
push:
|
|
87
|
+
tags:
|
|
88
|
+
- 'api@v*'
|
|
89
|
+
- 'site@v*'
|
|
90
|
+
|
|
91
|
+
jobs:
|
|
92
|
+
build-api:
|
|
93
|
+
if: startsWith(github.ref_name, 'api@v')
|
|
94
|
+
runs-on: ubuntu-latest
|
|
95
|
+
steps:
|
|
96
|
+
- uses: actions/checkout@v6
|
|
97
|
+
- run: echo "Building API ${{ github.ref_name }}"
|
|
98
|
+
|
|
99
|
+
build-site:
|
|
100
|
+
if: startsWith(github.ref_name, 'site@v')
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@v6
|
|
104
|
+
- run: echo "Building site ${{ github.ref_name }}"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
<aside class="ferr-aside ferr-aside--note"><div class="ferr-aside__body"><p>If FerrFlow releases multiple packages in a single run (e.g. <code>api@v1.3.0</code> and <code>site@v0.5.1</code>), each tag triggers its own workflow run. The builds happen in parallel automatically.</p>
|
|
108
|
+
</div></aside>
|
|
109
|
+
|
|
110
|
+
## Release-triggered
|
|
111
|
+
|
|
112
|
+
Run a pipeline when a GitHub Release is published. This works well with FerrFlow's `--draft` flag: FerrFlow creates a draft release, you review it, then publishing triggers the build.
|
|
113
|
+
|
|
114
|
+
```yaml title=".github/workflows/deploy.yml"
|
|
115
|
+
name: Deploy
|
|
116
|
+
|
|
117
|
+
on:
|
|
118
|
+
release:
|
|
119
|
+
types: [published]
|
|
120
|
+
|
|
121
|
+
jobs:
|
|
122
|
+
deploy:
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
steps:
|
|
125
|
+
- uses: actions/checkout@v6
|
|
126
|
+
with:
|
|
127
|
+
ref: ${{ github.event.release.tag_name }}
|
|
128
|
+
|
|
129
|
+
- name: Deploy
|
|
130
|
+
run: echo "Deploying ${{ github.event.release.tag_name }}"
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**When to use:** When you want a manual review gate before deploying. Create draft releases with `ferrflow release --draft`, review the changelog, then publish.
|
|
134
|
+
|
|
135
|
+
**Trade-offs:** Adds a manual step. The draft release must be published before the deploy runs.
|
|
136
|
+
|
|
137
|
+
**Works with:** All `releaseCommitMode` values.
|
|
138
|
+
|
|
139
|
+
## Manual (workflow_dispatch)
|
|
140
|
+
|
|
141
|
+
Trigger a release on demand with an optional dry-run flag. Useful for controlled release cadences or when you don't want every merge to potentially release.
|
|
142
|
+
|
|
143
|
+
```yaml title=".github/workflows/release.yml"
|
|
144
|
+
name: Release
|
|
145
|
+
|
|
146
|
+
on:
|
|
147
|
+
workflow_dispatch:
|
|
148
|
+
inputs:
|
|
149
|
+
dry_run:
|
|
150
|
+
description: 'Dry run (no tags, no commits, no releases)'
|
|
151
|
+
type: boolean
|
|
152
|
+
default: false
|
|
153
|
+
|
|
154
|
+
jobs:
|
|
155
|
+
release:
|
|
156
|
+
runs-on: ubuntu-latest
|
|
157
|
+
permissions:
|
|
158
|
+
contents: write
|
|
159
|
+
steps:
|
|
160
|
+
- uses: actions/checkout@v6
|
|
161
|
+
with:
|
|
162
|
+
fetch-depth: 0
|
|
163
|
+
token: ${{ secrets.FERRFLOW_TOKEN }}
|
|
164
|
+
|
|
165
|
+
- uses: FerrLabs/ferrflow@v3
|
|
166
|
+
with:
|
|
167
|
+
args: ${{ inputs.dry_run == true && '--dry-run' || '' }}
|
|
168
|
+
env:
|
|
169
|
+
GITHUB_TOKEN: ${{ secrets.FERRFLOW_TOKEN }}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**When to use:** Teams that prefer explicit release decisions over automatic releases. Also useful as a secondary workflow alongside push-to-main for ad-hoc releases.
|
|
173
|
+
|
|
174
|
+
**Trade-offs:** Requires someone to click "Run workflow" in the Actions tab. Commits can pile up between releases, producing larger changelogs.
|
|
175
|
+
|
|
176
|
+
## PR-based
|
|
177
|
+
|
|
178
|
+
Use `releaseCommitMode: pr` to have FerrFlow open a pull request with the version bump instead of committing directly. The release completes when the PR is merged.
|
|
179
|
+
|
|
180
|
+
```yaml title="ferrflow.json"
|
|
181
|
+
{ 'workspace': { 'releaseCommitMode': 'pr' } }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```yaml title=".github/workflows/release.yml"
|
|
185
|
+
name: Release
|
|
186
|
+
|
|
187
|
+
on:
|
|
188
|
+
push:
|
|
189
|
+
branches: [main]
|
|
190
|
+
|
|
191
|
+
jobs:
|
|
192
|
+
release:
|
|
193
|
+
runs-on: ubuntu-latest
|
|
194
|
+
if: "!startsWith(github.event.head_commit.message, 'chore(release):')"
|
|
195
|
+
permissions:
|
|
196
|
+
contents: write
|
|
197
|
+
pull-requests: write
|
|
198
|
+
steps:
|
|
199
|
+
- uses: actions/checkout@v6
|
|
200
|
+
with:
|
|
201
|
+
fetch-depth: 0
|
|
202
|
+
token: ${{ secrets.FERRFLOW_TOKEN }}
|
|
203
|
+
|
|
204
|
+
- uses: FerrLabs/ferrflow@v3
|
|
205
|
+
env:
|
|
206
|
+
GITHUB_TOKEN: ${{ secrets.FERRFLOW_TOKEN }}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**When to use:** When you want to review version bumps before they land, or when branch protection prevents direct pushes to main.
|
|
210
|
+
|
|
211
|
+
**Trade-offs:** Adds an extra merge step. The PR must be merged before tags are created.
|
|
212
|
+
|
|
213
|
+
**Works with:** `releaseCommitMode: pr` only. Requires `pull-requests: write` permission.
|
|
214
|
+
|
|
215
|
+
## Combining strategies
|
|
216
|
+
|
|
217
|
+
A common production setup combines push-to-main for versioning with tag-triggered builds:
|
|
218
|
+
|
|
219
|
+
```yaml title=".github/workflows/release.yml"
|
|
220
|
+
# Workflow 1: Version and tag on every push to main
|
|
221
|
+
name: Release
|
|
222
|
+
on:
|
|
223
|
+
push:
|
|
224
|
+
branches: [main]
|
|
225
|
+
jobs:
|
|
226
|
+
release:
|
|
227
|
+
if: "!startsWith(github.event.head_commit.message, 'chore(release):')"
|
|
228
|
+
runs-on: ubuntu-latest
|
|
229
|
+
permissions:
|
|
230
|
+
contents: write
|
|
231
|
+
steps:
|
|
232
|
+
- uses: actions/checkout@v6
|
|
233
|
+
with:
|
|
234
|
+
fetch-depth: 0
|
|
235
|
+
token: ${{ secrets.FERRFLOW_TOKEN }}
|
|
236
|
+
- uses: FerrLabs/ferrflow@v3
|
|
237
|
+
env:
|
|
238
|
+
GITHUB_TOKEN: ${{ secrets.FERRFLOW_TOKEN }}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```yaml title=".github/workflows/build.yml"
|
|
242
|
+
# Workflow 2: Build and deploy when a tag is pushed
|
|
243
|
+
name: Build
|
|
244
|
+
on:
|
|
245
|
+
push:
|
|
246
|
+
tags: ['v*', '*@v*']
|
|
247
|
+
jobs:
|
|
248
|
+
build:
|
|
249
|
+
runs-on: ubuntu-latest
|
|
250
|
+
steps:
|
|
251
|
+
- uses: actions/checkout@v6
|
|
252
|
+
- run: echo "Building ${{ github.ref_name }}"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Summary
|
|
256
|
+
|
|
257
|
+
| Trigger | Automatic | Review gate | Best for |
|
|
258
|
+
| ----------------- | --------- | ----------- | -------------------------- |
|
|
259
|
+
| Push to main | Yes | No | Most projects |
|
|
260
|
+
| Tag-triggered | Yes | No | Decoupled build/deploy |
|
|
261
|
+
| Release-triggered | No | Yes | Draft → review → publish |
|
|
262
|
+
| Manual | No | Yes | Controlled release cadence |
|
|
263
|
+
| PR-based | Partial | Yes | Branch protection / review |
|