Repository navigation
183 lines (167 loc) · 8.45 KB
/
Copy pathci.yml
File metadata and controls
183 lines (167 loc) · 8.45 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
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
# Manual runs from the Actions tab ("Run workflow").
workflow_dispatch:
concurrency:
# Pull requests: one run per branch, newest wins — a run against a head
# that has been superseded is answering a question nobody is asking any
# more.
#
# Pushes: one run per commit, and nothing cancels anything. A commit with
# no verdict is a hole nobody comes back to fill: the next commit contains
# it, so the code does get tested eventually, but once that run is red
# there is no longer any way to say which of the two commits did it.
#
# Keying the group on the SHA, rather than only turning cancel-in-progress
# off, is what makes that hold for more than two pushes: a group keeps at
# most one run *pending*, so a third push discards the second before it
# ever starts.
group: ci-${{ github.event_name == 'pull_request' && github.ref || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
build-and-test:
# The same two-leg matrix as the Styx and Hermod gates, so all three
# repositories answer for the same platform pair:
#
# * Windows, because it is the platform whose default checkout rewrites
# line endings, and the test fixtures here are signed charge
# transparency records whose bytes are the thing under test. Upstream
# ChargyCore.TS had exactly one leg go red for a week over this, and it
# was this one.
# * Debian 13, because that is what this code runs on in production.
# GitHub offers no Debian runner image, so the leg runs in a bare
# debian:13 container on an Ubuntu runner — the same container Styx and
# Hermod use.
#
# fail-fast is off on purpose: "red on exactly one platform" is the most
# valuable signal this matrix produces, so one leg must not cancel the
# other.
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
leg: windows-latest
- os: ubuntu-latest
container: debian:13
leg: debian-13-container
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
# Before the checkout, not after it, which is where Styx and Hermod put
# the same step. Two of these packages have to be in place by then:
# actions/checkout falls back to downloading a tarball through the REST
# API when the container has no git, and a working tree with no index
# behind it is precisely what the fixture check below cannot work with.
# mawk is what that check compares with.
#
# The rest are the .NET prerequisites setup-dotnet expects: curl for the
# install script, ICU and tzdata for globalization — this library resolves
# Europe/Berlin to read what a meter signed — OpenSSL for crypto and
# ca-certificates for NuGet over HTTPS. Package names verified on Debian
# 13 (trixie).
- name: Install .NET prerequisites (Debian container)
if: runner.os == 'Linux'
run: apt-get update && apt-get install -y --no-install-recommends ca-certificates curl git mawk libicu76 libssl3t64 libstdc++6 tzdata
- uses: actions/checkout@v7
with:
path: ChargyCore.NET
# ChargyCore.NET cannot be built on its own: its projects reference
# ..\..\Styx\... and ..\..\Hermod\... — SIBLING directories — and there is
# no submodule for either. Both are checked out alongside, which
# reproduces the layout those relative paths assume, exactly as Hermod
# does for Styx.
#
# Note what this does not do: pin either of them. This builds against
# their master branches, so a breaking change there turns this red without
# anything in this repository having moved.
- uses: actions/checkout@v7
with:
repository: Vanaheimr/Styx
path: Styx
- uses: actions/checkout@v7
with:
repository: Vanaheimr/Hermod
path: Hermod
- uses: actions/setup-dotnet@v6
with:
dotnet-version: '10.0.x'
# .gitattributes marks the whole TestData tree as "-text" so that no
# end-of-line heuristic can reach a signed fixture. This is what says so
# rather than assuming it: the file on disk is hashed with the filters
# switched off and compared against the blob the repository holds, which
# is the one comparison a conversion cannot hide from — asking git for a
# diff would apply the very filter under suspicion to both sides.
- name: Fixtures arrived byte for byte
shell: bash
working-directory: ChargyCore.NET
run: |
echo "core.autocrlf: $(git config --get core.autocrlf || echo 'unset')"
git ls-files > ../paths.txt
git ls-files -s | awk '{print $2}' > ../index.sha
git hash-object --no-filters --stdin-paths < ../paths.txt > ../ondisk.sha
# Every tracked file is measured, not only the fixtures. The fixtures
# decide the step; the rest is the control that gives the verdict its
# meaning — on a runner that converts nothing, "no fixture was altered"
# would be true no matter what .gitattributes said.
paste ../paths.txt ../index.sha ../ondisk.sha |
awk -F'\t' '
$1 ~ /^ChargyCoreTests\/TestData\// {
fixtures++
if ($2 != $3) { print "::error file=ChargyCore.NET/" $1 "::checked out with other bytes than the repository holds"; altered++ }
next
}
$2 != $3 { converted++ }
END {
printf "%d fixtures checked, %d altered by the checkout\n", fixtures, altered
printf "%d of the %d other tracked files were rewritten on checkout\n", converted, NR - fixtures
if (converted == 0)
print "note: this runner converts nothing at all, so the fixture result above is not evidence on its own"
exit altered ? 1 : 0
}'
- name: Build
working-directory: ChargyCore.NET
run: dotnet build ChargyCore.slnx --configuration Release
# TRX alongside the console log. The console says whether the suite passed
# and very little else: which test failed takes grepping the step log, and
# reading that needs a signed-in browser session once the run is not the
# newest. TRX keeps outcome, duration, error message and stack trace per
# test, and `gh run download` fetches it without a browser. The file is
# named after the leg, so the two are directly comparable — and comparable
# with the Styx and Hermod artifacts, which name theirs the same way.
- name: Test
timeout-minutes: 15
working-directory: ChargyCore.NET
run: dotnet test ChargyCore.slnx --configuration Release --no-build --logger "console;verbosity=normal" --logger "trx;LogFileName=${{ matrix.leg }}.trx" --results-directory artifacts
# !cancelled() rather than success(): a red run is when these files matter
# most, and a build that fails before the test step leaves no .trx, which
# upload-artifact reports as a warning rather than a second failure.
- name: Upload test results
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v7
with:
name: test-results-${{ matrix.leg }}
path: ChargyCore.NET/artifacts/*.trx
# Project by project rather than the whole solution: Styx and Hermod are in
# the solution too, and packing them here would build other people's
# projects into this repository's artifacts.
#
# One leg packs, and it is the platform this code runs on. The packages are
# platform independent, and two legs producing them would only raise the
# question which of the two shipped.
- name: Pack
if: matrix.leg == 'debian-13-container'
working-directory: ChargyCore.NET
run: |
dotnet pack ChargyCore/ChargyCore.csproj --configuration Release --no-build --output artifacts/packages
dotnet pack ChargyCore.QRCodes/ChargyCore.QRCodes.csproj --configuration Release --no-build --output artifacts/packages
- name: Upload packages
if: matrix.leg == 'debian-13-container'
uses: actions/upload-artifact@v7
with:
name: packages
path: ChargyCore.NET/artifacts/packages/*.*nupkg