-
Notifications
You must be signed in to change notification settings - Fork 0
191 lines (182 loc) · 7.18 KB
/
Copy pathci.yml
File metadata and controls
191 lines (182 loc) · 7.18 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
name: CI
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
# graphle is a public repository, so it runs on GitHub-hosted ubuntu-latest
# runners (free, unlimited Actions minutes for public repos) and deploys to
# GitHub Pages. No self-hosted fleet or runner-selection step is needed.
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-and-run
with:
task: lint
command: pnpm lint
typecheck:
name: Typecheck
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-and-run
with:
task: typecheck
command: pnpm typecheck
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-and-run
with:
task: test
command: pnpm test:coverage
- name: Post coverage summary
if: always()
run: |
if [ -f coverage/coverage-summary.json ]; then
node -e "
const cov = require('./coverage/coverage-summary.json');
const t = cov.total;
const pct = (k) => t[k].pct.toFixed(1) + '%';
const row = (label, k) => '| ' + label + ' | ' + pct(k) + ' |';
console.log('## Coverage');
console.log('');
console.log('| Metric | Coverage |');
console.log('|--------|----------|');
console.log(row('Lines', 'lines'));
console.log(row('Statements', 'statements'));
console.log(row('Functions', 'functions'));
console.log(row('Branches', 'branches'));
" >> "$GITHUB_STEP_SUMMARY"
fi
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-report
path: coverage/
integration-e2e:
name: Integration & E2E
# Independent of lint/typecheck/test and NOT in release/build-and-deploy's
# needs: below — real-network, third-party-API-dependent tests are more
# flake-prone than the mocked unit suite, and gating deploys on a
# transient GitHub API hiccup would trade deploy reliability for coverage
# already exercised, deterministically, by the mocked *.unit.test.ts
# suite. Still runs and reports on every push, just doesn't block release.
runs-on: ubuntu-latest
timeout-minutes: 15
# All four secrets are optional and independent — the tests run once per
# secret that's actually configured, and skip cleanly for the others.
# Named GH_ rather than GITHUB_: Actions rejects any secret name starting
# with GITHUB_ (reserved for its own built-ins). The _PRIVATE pair are
# separate, more-privileged tokens dedicated to reading two otherwise-
# unused fixture repos (Mearman/graphle-test-private,
# ExaDev/graphle-test-private) — kept apart from the public-only pair so
# those stay minimally scoped.
env:
GH_TEST_PAT_CLASSIC: ${{ secrets.GH_TEST_PAT_CLASSIC }}
GH_TEST_PAT_FINE_GRAINED: ${{ secrets.GH_TEST_PAT_FINE_GRAINED }}
GH_TEST_PAT_CLASSIC_PRIVATE: ${{ secrets.GH_TEST_PAT_CLASSIC_PRIVATE }}
GH_TEST_PAT_FINE_GRAINED_PRIVATE: ${{ secrets.GH_TEST_PAT_FINE_GRAINED_PRIVATE }}
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-and-run
with:
task: integration-e2e
command: >-
pnpm test:integration &&
pnpm exec playwright install --with-deps chromium &&
pnpm test:e2e
release:
name: Release
needs: [lint, typecheck, test]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
issues: write
steps:
- uses: actions/checkout@v6
with:
# semantic-release analyses the full commit history since the last release.
fetch-depth: 0
- uses: ./.github/actions/setup-and-run
with:
task: release
# HUSKY=0 so local git hooks never fire during the CI release commit.
command: HUSKY=0 pnpm release
github-token: ${{ secrets.GITHUB_TOKEN }}
build-and-deploy:
name: Build and deploy to Pages
# Build AFTER release so the deploy is built from the tagged release commit
# (semantic-release bumps package.json + tags on the chore(release) commit),
# which makes the header show the version instead of the un-tagged feat
# commit's hash. For non-releasing commits release creates no new tag and the
# header falls back to the hash, which is correct.
needs: [lint, typecheck, test, release]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
# Never overlap two Pages deploys; queue the next behind an in-progress one.
concurrency:
group: deploy-pages
cancel-in-progress: false
# `actions: write` (beyond contents/pages/id-token) lets the artifact-cleanup
# step below delete a `github-pages` artifact left by a prior failed attempt,
# so re-running this job never collides with a stale upload.
permissions:
contents: read
pages: write
id-token: write
actions: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v6
with:
# Check out the latest main (the release commit semantic-release just
# pushed), not the trigger commit, so the build resolves the new tag.
ref: main
# Full history + tags so the build can resolve the release tag.
fetch-depth: 0
- uses: ./.github/actions/setup-and-run
with:
task: build
command: pnpm build
# enablement: true re-enables Pages if it was disabled (e.g. by a
# repository visibility change), so a redeploy never fails on a missing
# Pages site.
- uses: actions/configure-pages@v6
with:
enablement: true
# A failed `deploy-pages` step (GitHub Pages' "Deployment failed, try
# again later" transient) leaves this run's uploaded `github-pages`
# artifact behind. Re-running the job then uploads a second one and
# `deploy-pages` refuses both ("Multiple artifacts named github-pages ...
# count is 2"). Drop any prior attempt's artifact before uploading so
# reruns are clean. No-op on the first attempt (nothing to delete).
- name: Remove prior github-pages artifacts from this run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts" \
--jq '.artifacts[] | select(.name=="github-pages") | .id' |
while read -r id; do
[ -z "$id" ] && continue
echo "Removing stale github-pages artifact $id from a prior attempt"
gh api -X DELETE "repos/${{ github.repository }}/actions/artifacts/$id"
done
- uses: actions/upload-pages-artifact@v5
with:
path: dist
- id: deployment
uses: actions/deploy-pages@v5