-
Notifications
You must be signed in to change notification settings - Fork 4
180 lines (167 loc) · 7.27 KB
/
Copy pathdotnet.yml
File metadata and controls
180 lines (167 loc) · 7.27 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
name: CI
# Single pipeline: detect relevant changes → unit tests + e2e tests → build & push the image.
# The image build `needs` BOTH test jobs, so an image is only published when unit AND e2e pass.
#
# "Required only on code changes": the test/build jobs are gated on a paths filter via job-level
# `if` (NOT `on.paths`). On a docs-only PR the jobs are skipped, and GitHub treats a skipped
# required status check as passing — so unrelated PRs aren't blocked, while C#/version/dependency
# PRs must pass unit tests.
#
# e2e is opt-in per PR via the `run-e2e-tests` label: it runs only while that label is present.
# `labeled`/`unlabeled` are in the trigger list so adding the label starts a run and removing it
# starts a fresh run where e2e is skipped; the `concurrency` block cancels the in-flight run so a
# still-running e2e is stopped when the label is removed.
on:
pull_request:
branches: [ main ]
types: [ opened, synchronize, reopened, labeled, unlabeled ]
push:
branches: [ main, master ]
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*' # semver release tags, v-prefixed (v1.2.3, v1.2.3-rc1)
- '[0-9]+.[0-9]+.[0-9]+*' # semver release tags, bare (1.2.3)
workflow_dispatch:
permissions:
contents: read
pull-requests: read # dorny/paths-filter uses the REST API on pull_request events
packages: write # push the image to ghcr
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
# One in-flight run per PR (or per ref for pushes). Removing the `run-e2e-tests` label triggers a
# new run that cancels the previous one, stopping an e2e job that was still executing.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# Detects whether C# code, versions, or dependencies changed. Everything else gates on this.
changes:
runs-on: ubuntu-latest
outputs:
code: ${{ steps.filter.outputs.code }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so the filter can diff push events too
- uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3
id: filter
with:
filters: |
code:
# C# / generated code
- '**/*.cs'
- '**/*.razor'
- '**/*.cshtml'
- '**/*.proto'
# versions & dependencies
- '**/*.csproj'
- '*.sln'
- 'Directory.Build.props'
- 'Directory.Packages.props'
- '**/packages.lock.json'
- 'global.json'
- 'nuget.config'
- 'NuGet.config'
# build/e2e harness that exercises the above
- 'src/Dockerfile'
- 'docker-compose.yml'
- 'docker/**'
- '.github/workflows/dotnet.yml'
unit-test:
needs: changes
# Run for code/version/dependency changes, and always on manual dispatch and tag (release) pushes.
if: ${{ needs.changes.outputs.code == 'true' || github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Restore
run: dotnet restore
- name: Unit tests (excludes e2e)
run: dotnet test --filter "Category!=E2E"
e2e-test:
needs: changes
# Same code/dispatch/tag gate as unit tests, but on PRs it additionally requires the
# `run-e2e-tests` label. Adding the label starts an e2e run; removing it re-runs the workflow
# with e2e skipped (a skipped required check counts as passing, so the PR isn't blocked).
if: >-
${{ ( needs.changes.outputs.code == 'true'
&& ( github.event_name != 'pull_request'
|| contains(github.event.pull_request.labels.*.name, 'run-e2e-tests') ) )
|| github.event_name == 'workflow_dispatch'
|| startsWith(github.ref, 'refs/tags/') }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run e2e tests
# Clean slate first (DbInitializer only funds the dev wallets on an empty DB), then `run`
# brings up the chain (bitcoind → alice/bob/carol → setup-e2e + extract-env → nodeguard →
# e2e-runner). The runner's exit code becomes the job result.
run: |
COMPOSE_PROFILES=polar,e2e docker compose -f docker-compose.yml down -v --remove-orphans || true
COMPOSE_PROFILES=polar,e2e docker compose -f docker-compose.yml run --rm --build e2e-runner
- name: Tear down
if: always()
run: COMPOSE_PROFILES=polar,e2e docker compose -f docker-compose.yml down -v --remove-orphans
# Build + push the image ONLY after unit + e2e pass, on: pushes to main/master (with relevant
# changes) and semver tag pushes (releases). Never on PRs or manual dispatch — those only test.
docker-build:
needs: [ changes, unit-test, e2e-test ]
# Test success is asserted explicitly so a future change to the test jobs' triggers can't
# silently let an image build (or silently skip it).
if: >-
${{ !cancelled()
&& needs.unit-test.result == 'success'
&& needs.e2e-test.result == 'success'
&& github.event_name == 'push'
&& ( startsWith(github.ref, 'refs/tags/')
|| ((github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
&& needs.changes.outputs.code == 'true') ) }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log into the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Branch pushes → branch name (+ `latest` on the default branch). Semver tag pushes →
# full version + major.minor + major (the `v` prefix is stripped by type=semver).
tags: |
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
labels: |
commit=${{ github.sha }}
actions_run=${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
- name: Build and push the Docker image
uses: docker/build-push-action@v6
with:
context: .
file: src/Dockerfile
push: true
platforms: linux/amd64
provenance: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Scan SBOM
uses: anchore/scan-action@3343887d815d7b07465f6fdcd395bd66508d486a # v3.6.4
with:
image: ${{ steps.meta.outputs.tags }}
add-cpes-if-none: true
output-format: table
severity-cutoff: critical
fail-build: false