-
Notifications
You must be signed in to change notification settings - Fork 26
260 lines (235 loc) · 10.6 KB
/
linux-install-test.yml
File metadata and controls
260 lines (235 loc) · 10.6 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
name: Linux Install Tests
# ──────────────────────────────────────────────────────────────────────────────
# PURPOSE:
# Smoke-test Linux .deb and .rpm packages produced by the CI workflow.
# Catches packaging regressions before release: missing files, broken
# installs, service registration issues, configuration initialization
# failures, and obvious startup problems.
#
# DESIGN:
# - Separate reusable workflow (workflow_call + workflow_dispatch + schedule).
# - Consumes the merged `devolutions-gateway` artifact from ci.yml.
# - Runs package installation tests inside Docker containers on
# GitHub-hosted runners (x86_64 only).
# - DEB lane: Ubuntu 18.04 container (minimum supported distro; the binary
# is built against an Ubuntu 18.04 sysroot / glibc 2.27).
# - RPM lane: Rocky Linux 9 container (RHEL 9-compatible).
# - Tests are split into:
# 1. Mandatory package smoke tests (must pass).
# 2. Best-effort systemd service tests (informational only).
#
# TRADEOFFS:
# - Separate workflow: Keeps the main CI fast; install tests can run
# independently or be chained into a release pipeline.
# - GitHub-hosted runners: Sufficient for package QA; no self-hosted
# infrastructure required.
# - Container-based: Close enough to real distros for catching packaging
# regressions, though not a perfect replica of production systems.
# - RHEL 9-compatible (Rocky Linux 9): Free, widely-used RHEL 9 rebuild;
# no exact RHEL version matching is required.
# - x86_64 only: GitHub-hosted runners are x86_64; ARM64 packages would
# require QEMU or ARM runners, not worth the complexity for v1.
# - Service testing is best-effort: systemd inside Docker containers is
# unreliable. Full service validation requires a real systemd environment.
# ──────────────────────────────────────────────────────────────────────────────
on:
# Callable from release pipelines (e.g. create-new-release.yml).
# The caller may supply an explicit CI run ID; if omitted the shared run
# context is used (all workflow_call children share the parent run ID).
workflow_call:
inputs:
run:
description: >
CI workflow run ID whose package artifacts to test.
Leave blank to use the current (shared) run context.
type: string
required: false
# Allow ad-hoc manual triggers so engineers can test packages from any
# previous CI run without triggering a full rebuild.
workflow_dispatch:
inputs:
run:
description: >
CI workflow run ID whose package artifacts to test.
Leave empty to use the latest successful CI run on the default branch.
type: string
required: false
# Weekly scheduled run to catch regressions even when no release is in progress.
schedule:
- cron: "0 6 * * 1" # Monday 06:00 UTC
permissions:
contents: read
actions: read
jobs:
# ─── Resolve which CI run to pull artifacts from, and read its version ──────
#
# Priority:
# 1. Explicit input (workflow_dispatch or workflow_call with run supplied).
# 2. Current run ID when called as workflow_call without explicit input
# (all reusable workflows in a chain share the same top-level run ID,
# so ci.yml artifacts are already in scope).
# 3. Latest successful ci.yml run on the default branch (schedule or
# workflow_dispatch without input).
preflight:
name: Preflight
runs-on: ubuntu-latest
outputs:
run-id: ${{ steps.resolve.outputs.run-id }}
version: ${{ steps.version.outputs.version }}
steps:
- name: Resolve CI run ID
id: resolve
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
$explicitRun = "${{ inputs.run }}"
if ($explicitRun) {
$runId = $explicitRun
Write-Host "Using provided run ID: $runId"
} elseif ("${{ github.event_name }}" -eq 'workflow_call') {
# All reusable workflows in a chain share the parent run ID.
$runId = "${{ github.run_id }}"
Write-Host "workflow_call: using shared run ID: $runId"
} else {
# schedule or workflow_dispatch without explicit input.
Write-Host "Looking up latest successful ci.yml run on ${{ github.event.repository.default_branch }}..."
$runId = gh run list `
--workflow ci.yml `
--status success `
--branch "${{ github.event.repository.default_branch }}" `
--limit 1 `
--json databaseId `
--jq '.[0].databaseId' `
--repo $env:GITHUB_REPOSITORY
if (-not $runId -or $runId -eq 'null') {
Write-Host "::error::No successful CI run found on ${{ github.event.repository.default_branch }}"
exit 1
}
Write-Host "Found latest successful CI run: $runId"
}
"run-id=$runId" >> $env:GITHUB_OUTPUT
- name: Download version artifact
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh run download "${{ steps.resolve.outputs.run-id }}" `
-n version `
--repo $env:GITHUB_REPOSITORY
- name: Read version
id: version
shell: pwsh
run: |
$version = Get-Content VERSION -First 1
"version=$version" >> $env:GITHUB_OUTPUT
Write-Host "::notice::Testing packages for version $version from run ${{ steps.resolve.outputs.run-id }}"
# ─── DEB and RPM install tests run in parallel via matrix ───────────────────
install-test:
name: ${{ matrix.display-name }}
needs: [preflight]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# DEB lane: Ubuntu 18.04 (minimum supported; built against Ubuntu 18.04 sysroot / glibc 2.27)
- package-type: deb
display-name: "DEB Install Test (Ubuntu 18.04)"
container-image: "ubuntu:18.04"
test-script: ".github/scripts/smoke-test-deb.sh"
package-pattern: "*.deb"
# RPM lane: Rocky Linux 9 (RHEL 9-compatible)
- package-type: rpm
display-name: "RPM Install Test (Rocky Linux 9)"
container-image: "rockylinux:9"
test-script: ".github/scripts/smoke-test-rpm.sh"
package-pattern: "*.rpm"
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Download devolutions-gateway artifact
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh run download "${{ needs.preflight.outputs.run-id }}" `
-n devolutions-gateway `
-D gateway-artifacts `
--repo $env:GITHUB_REPOSITORY
- name: Locate package file
id: find-package
shell: pwsh
run: |
$packageFile = Get-ChildItem -Path "gateway-artifacts/linux/x86_64" `
-Filter "${{ matrix.package-pattern }}" -File | Select-Object -First 1
if (-not $packageFile) {
Write-Host "::error::No ${{ matrix.package-type }} package found in gateway-artifacts/linux/x86_64"
Write-Host "Available files in gateway-artifacts:"
Get-ChildItem -Path "gateway-artifacts" -Recurse -File | Sort-Object FullName | ForEach-Object { Write-Host $_.FullName }
exit 1
}
$packageFilePath = "gateway-artifacts/linux/x86_64/$($packageFile.Name)"
Write-Host "Found package: $packageFilePath"
"package-file=$packageFilePath" >> $env:GITHUB_OUTPUT
"package-basename=$($packageFile.Name)" >> $env:GITHUB_OUTPUT
- name: Run install tests in container
id: run-tests
shell: pwsh
run: |
chmod +x "${{ matrix.test-script }}"
# Strip the gateway-artifacts/ prefix so the path is relative to
# the /artifacts mount point inside the container.
$packageRelPath = "${{ steps.find-package.outputs.package-file }}"
$packageInContainer = "/artifacts/" + ($packageRelPath -replace '^gateway-artifacts/', '')
docker run --rm `
-v "${{ github.workspace }}:/workspace:ro" `
-v "${{ github.workspace }}/gateway-artifacts:/artifacts:ro" `
-e "PACKAGE_FILE=$packageInContainer" `
-e "VERSION=${{ needs.preflight.outputs.version }}" `
-e "PACKAGE_NAME=devolutions-gateway" `
"${{ matrix.container-image }}" `
/workspace/${{ matrix.test-script }}
- name: Write job summary
if: always()
shell: pwsh
run: |
$outcome = "${{ steps.run-tests.outcome }}"
$status = if ($outcome -eq 'success') { "✅ Passed" } else { "❌ Failed" }
@"
## ${{ matrix.display-name }} — $status
| Property | Value |
|----------|-------|
| Result | $status |
| Package | ``${{ steps.find-package.outputs.package-basename }}`` |
| Version | ``${{ needs.preflight.outputs.version }}`` |
| Container | ``${{ matrix.container-image }}`` |
| CI Run | ``${{ needs.preflight.outputs.run-id }}`` |
"@ | Add-Content -Path $env:GITHUB_STEP_SUMMARY
# ─── Slack notification on scheduled failure ─────────────────────────────────
notify:
name: Notify failure
runs-on: ubuntu-latest
if: ${{ always() && contains(needs.*.result, 'failure') && github.event_name == 'schedule' }}
needs:
- preflight
- install-test
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_ARCHITECTURE }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
steps:
- name: Send Slack notification
uses: slackapi/slack-github-action@v1.26.0
with:
payload: |
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*${{ github.repository }}* :fire::fire::fire::fire::fire: \n The scheduled Linux install test for *${{ github.repository }}* is <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|broken>"
}
}
]
}