forked from open-component-model/open-component-model
-
Notifications
You must be signed in to change notification settings - Fork 0
406 lines (377 loc) · 17.8 KB
/
Copy pathci.yml
File metadata and controls
406 lines (377 loc) · 17.8 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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
name: CI
on:
pull_request:
push:
branches:
- main
env:
# Check Only Changed Modules
# If true, only changed modules will be analyzed.
# If false, all discovered modules will be analyzed.
check_only_changed: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
discover_modules:
name: "Discover Go Modules"
runs-on: ubuntu-24.04-arm
permissions:
pull-requests: read
outputs:
# modules_json = all modules on push or when CI workflow changed, else changed modules only
modules_json: ${{ steps.filtered.outputs.modules_json }}
# lint_modules_json = all modules when .env changed (lint version bump), else same as modules_json
lint_modules_json: ${{ steps.filtered.outputs.lint_modules_json }}
integration_test_modules_json: ${{ steps.filtered_test.outputs.integration_test_modules_json }}
unit_test_modules_json: ${{ steps.filtered_test.outputs.unit_test_modules_json }}
env:
DIR: ${{ github.workspace }}
steps:
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
# Detect .env changes so lint runs on all modules when the golangci-lint version changes
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: env_changes
with:
filters: |
env:
- '.env'
# Detect CI workflow changes to rebuild/test all modules
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: ci_changes
with:
filters: |
ci:
- '.github/workflows/ci.yml'
- name: Discover Go Modules
id: discover
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const { execSync } = require('child_process');
// Get all Go modules using task
const modulesOutput = execSync('task go_modules --output interleaved', { encoding: 'utf-8' });
const modules = modulesOutput.split('\n').filter(Boolean);
// Generate filters for paths-filter
const filters = modules.map(module => {
const lines = [`${module}:`];
lines.push(` - "${module}/**"`);
// If this is an integration module, also trigger on parent module changes
if (module.includes('/integration')) {
const parentModule = module.split('/integration')[0];
lines.push(` - "${parentModule}/**"`);
console.log(`🔍 Detected integration test module: ${module}`);
console.log(` └─ Linked to parent module: ${parentModule}`);
}
return lines.join('\n');
}).join('\n');
// Set outputs
core.setOutput('modules_json', JSON.stringify(modules));
core.setOutput('filters', filters);
// Log for debugging
console.log('📦 Detected modules:', modules);
console.log('🎯 Generated filters:', filters);
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4
id: changes
with:
filters: ${{ steps.discover.outputs.filters }}
- name: Filter JSONs Based on Changes
id: filtered
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
MODULES_JSON: ${{ steps.discover.outputs.modules_json }}
CHANGE_JSON: ${{ steps.changes.outputs.changes }}
ENV_CHANGED: ${{ steps.env_changes.outputs.env }}
CI_CHANGED: ${{ steps.ci_changes.outputs.ci }}
with:
# Decides which Go modules to build/lint/test.
# Three branches, in priority order:
# 1. CI workflow changed - build, lint & test everything
# 2. PR (check_only_changed=true) - build & test only changed modules;
# if .env also changed, lint all modules (version bump)
# 3. Push to main - everything
script: |
const modulesJson = JSON.parse(process.env.MODULES_JSON || '[]');
const changeJson = JSON.parse(process.env.CHANGE_JSON || '[]');
const envChanged = process.env.ENV_CHANGED === 'true';
const ciChanged = process.env.CI_CHANGED === 'true';
if (ciChanged) {
console.log("CI workflow changed, running all modules.");
core.setOutput("modules_json", JSON.stringify(modulesJson));
core.setOutput('lint_modules_json', JSON.stringify(modulesJson));
} else if (process.env.check_only_changed === "true") {
console.log(`Filtering modules based on changes: ${JSON.stringify(changeJson)}`);
const filteredModules = modulesJson.filter(module => {
return changeJson.some(change => change.includes(module));
});
console.log(`Filtered modules: ${JSON.stringify(filteredModules)}`);
core.setOutput("modules_json", JSON.stringify(filteredModules));
// .env holds the golangci-lint version; lint all modules when it changes
core.setOutput('lint_modules_json', JSON.stringify(envChanged ? modulesJson : filteredModules));
} else {
console.log("check_only_changed is false, no filtering applied.");
core.setOutput("modules_json", JSON.stringify(modulesJson));
core.setOutput('lint_modules_json', JSON.stringify(modulesJson));
}
- name: Filter based on Testability
id: filtered_test
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
MODULES_JSON: ${{ steps.filtered.outputs.modules_json }}
with:
# Probes each module's Taskfile to see if it has "test" and/or
# "test/integration" targets, then splits them into two lists.
script: |
const { execSync } = require('child_process');
const modules = JSON.parse(process.env.MODULES_JSON || '[]');
const unitTestModules = [];
const integrationTestModules = [];
for (const module of modules) {
try {
const output = execSync(`task -d ${module} -aj`, { encoding: 'utf-8' });
const parsed = JSON.parse(output);
const taskNames = parsed.tasks.map(task => task.name);
if (taskNames.includes('test')) {
unitTestModules.push(module);
}
if (taskNames.includes('test/integration')) {
integrationTestModules.push(module);
}
} catch (error) {
console.log(`Skipping module '${module}' due to error or no taskfile: ${error.message}`);
}
}
console.log(`Unit test modules: ${JSON.stringify(unitTestModules)}`);
console.log(`Integration test modules: ${JSON.stringify(integrationTestModules)}`);
core.setOutput('unit_test_modules_json', JSON.stringify(unitTestModules));
core.setOutput('integration_test_modules_json', JSON.stringify(integrationTestModules));
- name: Generate Job Summary
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
env:
MODULES_JSON: ${{ steps.discover.outputs.modules_json }}
FILTERED_JSON: ${{ steps.filtered.outputs.modules_json }}
LINT_MODULES_JSON: ${{ steps.filtered.outputs.lint_modules_json }}
ENV_CHANGED: ${{ steps.env_changes.outputs.env }}
CI_CHANGED: ${{ steps.ci_changes.outputs.ci }}
CHECK_ONLY_CHANGED: ${{ env.check_only_changed }}
UNIT_TESTS_JSON: ${{ steps.filtered_test.outputs.unit_test_modules_json }}
INTEGRATION_TESTS_JSON: ${{ steps.filtered_test.outputs.integration_test_modules_json }}
with:
script: |
const modules = JSON.parse(process.env.MODULES_JSON || '[]');
const filtered = JSON.parse(process.env.FILTERED_JSON || '[]');
const lintModules = JSON.parse(process.env.LINT_MODULES_JSON || '[]');
const envChanged = process.env.ENV_CHANGED === 'true';
const ciChanged = process.env.CI_CHANGED === 'true';
const checkOnlyChanged = process.env.CHECK_ONLY_CHANGED === 'true';
const unitTests = JSON.parse(process.env.UNIT_TESTS_JSON || '[]');
const integrationTests = JSON.parse(process.env.INTEGRATION_TESTS_JSON || '[]');
function toMarkdownList(items) {
return items.length ? items.map(item => `- \`${item}\``).join('\n') : '_None_';
}
// Must mirror the logic in "Filter JSONs Based on Changes" above.
const buildScope = ciChanged
? 'all modules (CI workflow changed)'
: checkOnlyChanged
? 'changed modules only'
: 'all modules (push)';
const lintScope = (ciChanged || envChanged)
? `all modules (${ciChanged ? 'CI workflow' : '.env'} changed)`
: checkOnlyChanged
? 'changed modules only'
: 'all modules (push)';
let summary = `### 🧩 Go Module Discovery Summary\n\n`;
summary += `**🔍 Discovered Modules (${modules.length}):**\n${toMarkdownList(modules)}\n\n`;
summary += `**🎯 Filtered Modules (${filtered.length}):**\n${toMarkdownList(filtered)}\n\n`;
summary += `**🔨 Build/Test Scope:** ${buildScope}\n\n`;
summary += `**🧹 Lint Scope:** ${lintScope}\n\n`;
summary += `**🧪 Unit Test Modules (${unitTests.length}):**\n${toMarkdownList(unitTests)}\n\n`;
summary += `**🧬 Integration Test Modules (${integrationTests.length}):**\n${toMarkdownList(integrationTests)}\n`;
core.summary.addRaw(summary).write();
golangci_lint_verify:
name: "golangci-lint-verify"
runs-on: ubuntu-24.04-arm
permissions:
# Optional: allow write access to checks to allow the action to annotate code in the PR.
# Automatically downgraded to read-only for pull requests from forks
# https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/#setting-permissions-in-the-workflow
# but are kept for runs on main or on pull requests on branches in the repo (renovate).
checks: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
sparse-checkout: |
golangci.yml
.env
persist-credentials: false
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Read tool versions
id: versions
run: |
source .env
echo "golangci_lint=${GOLANGCI_LINT_VERSION}" >> $GITHUB_OUTPUT
- name: Verify the golangci-lint config
run:
task tools:golangci-lint/verify
golangci_lint:
name: "golangci-lint"
needs:
- discover_modules
- golangci_lint_verify
runs-on: ubuntu-24.04-arm
permissions:
# Optional: allow write access to checks to allow the action to annotate code in the PR.
# Automatically downgraded to read-only for pull requests from forks
# https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/#setting-permissions-in-the-workflow
# but are kept for runs on main or on pull requests on branches in the repo (renovate).
checks: write
# Run for all modules when .env changed, else only for changed modules
if: ${{ needs.discover_modules.outputs.lint_modules_json != '[]' }}
strategy:
matrix:
module: ${{ fromJSON(needs.discover_modules.outputs.lint_modules_json) }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
sparse-checkout: |
${{ matrix.module }}
golangci.yml
.env
persist-credentials: false
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version-file: '${{ github.workspace }}/${{ matrix.module }}/go.mod'
cache-dependency-path: '${{ github.workspace }}/${{ matrix.module }}/go.sum'
- name: Read tool versions
id: versions
run: |
source .env
echo "golangci_lint=${GOLANGCI_LINT_VERSION}" >> $GITHUB_OUTPUT
- name: golangci-lint ${{ matrix.modules }}
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
with:
verify: 'false' # we verify in a separate command ONCE instead of every run on every module
version: ${{ steps.versions.outputs.golangci_lint }}
working-directory: ${{ github.workspace }}/${{ matrix.module }}
args: --timeout 10m --config=${{ github.workspace }}/golangci.yml
run_integration_tests:
name: "Integration Tests"
needs: discover_modules
# Runner override map — add entries to run specific modules on a different runner.
# Modules not listed here use the default: ubuntu-24.04-arm.
# Example: '{"some/module/integration":"ubuntu-latest","other":"ubuntu-22.04"}'
runs-on: ${{ fromJSON('{"bindings/go/sigstore/integration":"ubuntu-latest"}')[matrix.module] || 'ubuntu-24.04-arm' }}
if: ${{ fromJSON(needs.discover_modules.outputs.integration_test_modules_json)[0] != null }} # skip if no modules are found
strategy:
matrix:
module: ${{ fromJSON(needs.discover_modules.outputs.integration_test_modules_json) }}
env:
TESTCONTAINER_DOCKER_NETWORK: integration-testcontainers
steps:
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version-file: '${{ github.workspace }}/${{ matrix.module }}/go.mod'
cache-dependency-path: '${{ github.workspace }}/${{ matrix.module }}/go.sum'
- name: Create Docker network for running Testcontainers
run: docker network create ${{ env.TESTCONTAINER_DOCKER_NETWORK }}
- name: Run Tests
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USER: ${{ github.actor }}
MODULE: ${{ matrix.module }}
run: task "${MODULE}:test/integration"
run_unit_tests:
name: "Unit Tests"
needs: discover_modules
runs-on: ubuntu-24.04-arm
if: ${{ fromJSON(needs.discover_modules.outputs.unit_test_modules_json)[0] != null }} # skip if no modules are found
strategy:
matrix:
module: ${{ fromJSON(needs.discover_modules.outputs.unit_test_modules_json) }}
steps:
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
sparse-checkout: |
${{ matrix.module }}
reuse.Taskfile.yml
persist-credentials: false
- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version-file: '${{ github.workspace }}/${{ matrix.module }}/go.mod'
cache-dependency-path: '${{ github.workspace }}/${{ matrix.module }}/go.sum'
- name: Run Tests
env:
MODULE: ${{ matrix.module }}
run: task "${MODULE}:test"
generate:
runs-on: ubuntu-24.04-arm
name: "Code Generation"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2
with:
version: 3.x
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Go (required by some generators)
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with:
go-version-file: ${{ github.workspace }}/bindings/go/generator/go.mod
cache-dependency-path: |
${{ github.workspace }}/bindings/go/generator/go.sum
- name: Run Code Generation
run: task generate
- name: Ensure Clean Target Repository
run: |
gitStatus="$(git status --porcelain)"
if [[ -z "${gitStatus}" ]]; then
exit 0
fi
echo "${gitStatus}"
exit 1
# failure aggregation job
# Our CI matrix is dynamic so it cannot be used for required status checks in github.
# However we can add a failure step that can get triggered if any dependency fails or is cancelled.
# If this is the case, this job will fail. If CI is successful, the CI Completion Check will be skipped.
# see https://github.com/orgs/community/discussions/60792 for details on why this is needed
check-completion:
name: "Completion"
runs-on: ubuntu-24.04-arm
needs:
- discover_modules
- generate
- run_unit_tests
- run_integration_tests
- golangci_lint
if: ${{ failure() }}
steps:
- name: Some CI step failed or was cancelled!
run: exit 1