-
Notifications
You must be signed in to change notification settings - Fork 54
265 lines (229 loc) · 10.1 KB
/
container.yaml
File metadata and controls
265 lines (229 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
name: Container
# Path policy: skip this workflow when every changed file is documentation.
# See .github/workflows/docs-lint.yaml for the lightweight docs-only workflow.
on:
push:
branches:
- "develop"
- "main"
- "releases/**/*"
paths-ignore:
- "**/*.md"
- "project-words.txt"
pull_request:
branches:
- "develop"
- "main"
paths-ignore:
- "**/*.md"
- "project-words.txt"
env:
CARGO_TERM_COLOR: always
jobs:
test:
# Builds the container image and runs E2E tests against it before any publish step.
# "release" here is the Containerfile stage name (Cargo release profile: opt-level 3, fat LTO).
#
# Unit tests run inside the Containerfile build itself (via `cargo nextest run` in the `test`
# stage, using `rust:slim-trixie` as the tester base image). Note: this environment differs
# from the production runtime (`distroless/cc-debian13`); the unit tests do not prove the
# binary works in distroless — that is covered by the E2E steps below. The in-container
# unit tests validate the compiled binary in the build pipeline before it enters the runtime
# stage, and share the same Debian trixie glibc as the production image. See ADR
# 20260603000000_keep_unit_tests_inside_container_build.md.
#
# Cache flow: the `build` step writes the BuildKit layer cache to the `container-release`
# GHA scope (mode=max, all intermediate layers). The publish_development and publish_release
# jobs read from this scope first, so they get a cache hit and avoid a full rebuild when
# running on the same commit. The cache is written during `docker build`, before the E2E
# steps below, so it is available to publish jobs even if E2E tests fail (though in that
# case the publish jobs are blocked anyway by the `needs: test` dependency chain).
#
# When this workflow runs (push to develop/main/releases, PR targeting develop/main),
# the docker-e2e job in testing.yaml is skipped to avoid running the same E2E suite twice.
# For feature branch pushes where this workflow does not trigger, testing.yaml provides
# equivalent coverage. See issue #1854.
name: Test (Docker)
runs-on: ubuntu-latest
timeout-minutes: 90
strategy:
matrix:
target: [release]
steps:
- id: checkout
name: Checkout Repository
uses: actions/checkout@v6
- id: setup-buildx
name: Setup Buildx
uses: docker/setup-buildx-action@v4
- id: setup-toolchain
name: Setup Toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
- id: cache
name: Enable Job Cache
uses: Swatinem/rust-cache@v2
- id: fetch
name: Download Dependencies
run: cargo fetch --verbose
- id: build
name: Build Tracker Image
uses: docker/build-push-action@v7
with:
file: ./Containerfile
push: false
load: true
target: ${{ matrix.target }}
tags: torrust-tracker:local
cache-from: type=gha,scope=container-${{ matrix.target }}
cache-to: type=gha,scope=container-${{ matrix.target }},mode=max
- id: run-tracker-e2e-tests
name: Run E2E Tests
run: >-
cargo run -p torrust-tracker-e2e-tools --bin e2e_tests_runner
-- --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml"
--tracker-image "torrust-tracker:local" --skip-build
- id: run-qbittorrent-e2e-test-sqlite3
name: Run qBittorrent E2E Test (SQLite)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver sqlite3 --timeout-seconds 600
- id: run-qbittorrent-e2e-test-mysql
name: Run qBittorrent E2E Test (MySQL)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver mysql --timeout-seconds 600
- id: run-qbittorrent-e2e-test-postgresql
name: Run qBittorrent E2E Test (PostgreSQL)
run: cargo run -p torrust-tracker-e2e-tools --bin qbittorrent_e2e_runner -- --tracker-image "torrust-tracker:local" --skip-build --db-driver postgresql --timeout-seconds 600
context:
name: Context
needs: test
runs-on: ubuntu-latest
outputs:
continue: ${{ steps.check.outputs.continue }}
type: ${{ steps.check.outputs.type }}
version: ${{ steps.check.outputs.version }}
steps:
- id: check
name: Check Context
run: |
if [[ "${{ github.repository }}" == "torrust/torrust-tracker" ]]; then
if [[ "${{ github.event_name }}" == "push" ]]; then
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "type=development" >> $GITHUB_OUTPUT
echo "continue=true" >> $GITHUB_OUTPUT
echo "On \`main\` Branch, Type: \`development\`"
elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
echo "type=development" >> $GITHUB_OUTPUT
echo "continue=true" >> $GITHUB_OUTPUT
echo "On \`develop\` Branch, Type: \`development\`"
elif [[ "${{ github.ref }}" =~ ^refs/heads/releases/ ]]; then
semver_regex='^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$'
version=$(echo "${{ github.ref }}" | sed -n -E 's#^refs/heads/releases/##p')
if [[ ! "$version" =~ $semver_regex ]]; then
echo "Not a valid release branch semver. Will Not Continue"
exit 0
fi
echo "version=$version" >> $GITHUB_OUTPUT
echo "type=release" >> $GITHUB_OUTPUT
echo "continue=true" >> $GITHUB_OUTPUT
echo "In \`releases/$version\` Branch, Type: \`release\`"
else
echo "Not Correct Branch. Will Not Continue"
fi
else
echo "Not a Push Event. Will Not Continue"
fi
else
echo "On a Forked Repository. Will Not Continue"
fi
publish_development:
# Publishes a Docker Hub image tagged with the branch name (e.g. "develop").
# "Development" here means "built from a development branch, not a versioned release" —
# it is not the Cargo dev profile. Both publish jobs always use `target: release`
# (the optimized Containerfile stage) because Docker Hub images must be production-grade
# binaries regardless of whether they originate from develop or a release branch.
# The Cargo release profile (opt-level 3, fat LTO) applies in both cases.
name: Publish (Development)
environment: dockerhub-torrust
needs: context
if: needs.context.outputs.continue == 'true' && needs.context.outputs.type == 'development'
runs-on: ubuntu-latest
steps:
- id: checkout
name: Checkout Repository
uses: actions/checkout@v6
- id: meta
name: Docker Meta
uses: docker/metadata-action@v6
with:
images: |
"${{ secrets.DOCKER_HUB_USERNAME }}/${{secrets.DOCKER_HUB_REPOSITORY_NAME }}"
tags: |
type=ref,event=branch
- id: login
name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- id: setup
name: Setup Toolchain
uses: docker/setup-buildx-action@v4
- name: Build and push
uses: docker/build-push-action@v7
with:
file: ./Containerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: release
# Read from the test job's cache first (container-release scope) so that when
# the test and publish jobs run on the same commit the publish step gets a
# cache hit and avoids a full rebuild. Falls back to the publish-specific scope.
cache-from: |
type=gha,scope=container-release
type=gha,scope=container-publish-dev
cache-to: type=gha,scope=container-publish-dev,mode=max
publish_release:
name: Publish (Release)
environment: dockerhub-torrust
needs: context
if: needs.context.outputs.continue == 'true' && needs.context.outputs.type == 'release'
runs-on: ubuntu-latest
steps:
- id: checkout
name: Checkout Repository
uses: actions/checkout@v6
- id: meta
name: Docker Meta
uses: docker/metadata-action@v6
with:
images: |
"${{ secrets.DOCKER_HUB_USERNAME }}/${{secrets.DOCKER_HUB_REPOSITORY_NAME }}"
tags: |
type=semver,value=${{ needs.context.outputs.version }},pattern={{raw}}
type=semver,value=${{ needs.context.outputs.version }},pattern={{version}}
type=semver,value=${{ needs.context.outputs.version }},pattern=v{{major}}
type=semver,value=${{ needs.context.outputs.version }},pattern={{major}}.{{minor}}
- id: login
name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- id: setup
name: Setup Toolchain
uses: docker/setup-buildx-action@v4
- name: Build and push
uses: docker/build-push-action@v7
with:
file: ./Containerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
target: release
# Read from the test job's cache first (container-release scope) for the same
# reason as publish_development above.
cache-from: |
type=gha,scope=container-release
type=gha,scope=container-publish-release
cache-to: type=gha,scope=container-publish-release,mode=max