Skip to content

Commit 2923728

Browse files
committed
Use self-hosted cert linting to make CI tests more reliable
1 parent 0a09893 commit 2923728

2 files changed

Lines changed: 55 additions & 53 deletions

File tree

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ jobs:
1919
deploys-docs: true
2020
- node-version: latest
2121

22+
services:
23+
# Self-hosted certificate linter, to run lintcert tests reliably against a local instance
24+
certlinter:
25+
image: ghcr.io/pkimetal/pkimetal:latest
26+
ports:
27+
- 8080:8080
28+
2229
steps:
2330
- uses: actions/checkout@v6
2431

@@ -31,13 +38,18 @@ jobs:
3138

3239
- run: npm install
3340

41+
- name: Wait for cert linter
42+
run: timeout 60 bash -c 'until curl -sf http://localhost:8080/ >/dev/null; do sleep 1; done'
43+
3444
- run: npm run ci-tests
3545
env:
3646
# Node v22+ needs no strip-types (because we use ts-node for full TS instead)
3747
NODE_OPTIONS: >-
3848
${{ (!startsWith(matrix.node-version, '20') && '--no-experimental-strip-types') || '' }}
3949
# We log performance test results to Posthog to track trends:
4050
POSTHOG_PERF_API_KEY: ${{ secrets.POSTHOG_PERF_API_KEY }}
51+
# Point lintcert tests at the self-hosted linter service above:
52+
PKIMETAL_BASE_URL: http://localhost:8080
4153

4254
- name: Upload docs artifact
4355
uses: actions/upload-artifact@v6

test/certificates.spec.ts

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import {
88
DestroyableServer,
99
makeDestroyable,
1010
expect,
11-
ignoreNetworkError,
1211
nodeOnly
1312
} from "./test-utils";
1413

1514
import { getCA, CA, generateCACertificate, generateSPKIFingerprint } from '../src/util/certificates';
1615

16+
// We use public pkimet.al for local dev, CI uses a self-hosted version for reliability
17+
const LINTCERT_URL = `${process.env.PKIMETAL_BASE_URL ?? 'https://pkimet.al'}/lintcert`;
18+
1719
const validateLintSiteCertResults = (cert: string, results: any[]) => {
1820
// We don't worry about warnings
1921
const errors = results.filter((result: any) => result.Severity !== 'warning');
@@ -351,19 +353,16 @@ nodeOnly(() => {
351353

352354
const { cert } = caCertificate;
353355

354-
const response = await ignoreNetworkError(
355-
fetch('https://pkimet.al/lintcert', {
356-
method: 'POST',
357-
headers: { 'content-type': 'application/x-www-form-urlencoded' },
358-
body: new URLSearchParams({
359-
'b64input': cert,
360-
'format': 'json',
361-
'severity': 'warning',
362-
'profile': 'tbr_root_tlsserver' // TLS Baseline root CA
363-
})
364-
}),
365-
{ context: this }
366-
);
356+
const response = await fetch(LINTCERT_URL, {
357+
method: 'POST',
358+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
359+
body: new URLSearchParams({
360+
'b64input': cert,
361+
'format': 'json',
362+
'severity': 'warning',
363+
'profile': 'tbr_root_tlsserver' // TLS Baseline root CA
364+
})
365+
});
367366

368367
expect(response.status).to.equal(200);
369368
const results = await response.json();
@@ -384,19 +383,16 @@ nodeOnly(() => {
384383
{ type: 'dns', 'value': 'httptoolkit.com' },
385384
]);
386385

387-
const response = await ignoreNetworkError(
388-
fetch('https://pkimet.al/lintcert', {
389-
method: 'POST',
390-
headers: { 'content-type': 'application/x-www-form-urlencoded' },
391-
body: new URLSearchParams({
392-
'b64input': cert,
393-
'format': 'json',
394-
'severity': 'warning',
395-
'profile': 'tbr_leaf_tlsserver_dv' // TLS Baseline domain-validated server
396-
})
397-
}),
398-
{ context: this }
399-
);
386+
const response = await fetch(LINTCERT_URL, {
387+
method: 'POST',
388+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
389+
body: new URLSearchParams({
390+
'b64input': cert,
391+
'format': 'json',
392+
'severity': 'warning',
393+
'profile': 'tbr_leaf_tlsserver_dv' // TLS Baseline domain-validated server
394+
})
395+
});
400396

401397
expect(response.status).to.equal(200);
402398
const results = await response.json();
@@ -417,19 +413,16 @@ nodeOnly(() => {
417413
{ type: 'dns', 'value': '*.httptoolkit.com' },
418414
]);
419415

420-
const response = await ignoreNetworkError(
421-
fetch('https://pkimet.al/lintcert', {
422-
method: 'POST',
423-
headers: { 'content-type': 'application/x-www-form-urlencoded' },
424-
body: new URLSearchParams({
425-
'b64input': cert,
426-
'format': 'json',
427-
'severity': 'warning',
428-
'profile': 'tbr_leaf_tlsserver_dv' // TLS Baseline domain-validated server
429-
})
430-
}),
431-
{ context: this, timeout: 9000 }
432-
);
416+
const response = await fetch(LINTCERT_URL, {
417+
method: 'POST',
418+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
419+
body: new URLSearchParams({
420+
'b64input': cert,
421+
'format': 'json',
422+
'severity': 'warning',
423+
'profile': 'tbr_leaf_tlsserver_dv' // TLS Baseline domain-validated server
424+
})
425+
});
433426

434427
expect(response.status).to.equal(200);
435428
const results = await response.json();
@@ -449,19 +442,16 @@ nodeOnly(() => {
449442

450443
const { cert } = caCertificate;
451444

452-
const response = await ignoreNetworkError(
453-
fetch('https://pkimet.al/lintcert', {
454-
method: 'POST',
455-
headers: { 'content-type': 'application/x-www-form-urlencoded' },
456-
body: new URLSearchParams({
457-
'b64input': cert,
458-
'format': 'json',
459-
'severity': 'warning',
460-
'profile': 'tbr_root_tlsserver' // TLS Baseline root CA
461-
})
462-
}),
463-
{ context: this }
464-
);
445+
const response = await fetch(LINTCERT_URL, {
446+
method: 'POST',
447+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
448+
body: new URLSearchParams({
449+
'b64input': cert,
450+
'format': 'json',
451+
'severity': 'warning',
452+
'profile': 'tbr_root_tlsserver' // TLS Baseline root CA
453+
})
454+
});
465455

466456
expect(response.status).to.equal(200);
467457
const results = await response.json();

0 commit comments

Comments
 (0)