feat: faster sign

This commit is contained in:
DarkSky
2026-07-04 00:13:48 +08:00
parent c36b5b201e
commit fc90615350
3 changed files with 51 additions and 94 deletions
+5 -1
View File
@@ -89,9 +89,13 @@ jobs:
id: check
run: node ./scripts/check-windows-signer.mjs
env:
AFFINE_SIGN_CLIENT_HASH: ${{ secrets.AFFINE_SIGN_CLIENT_HASH }}
AFFINE_SIGNER_ADDR: ${{ secrets.AFFINE_SIGNER_ADDR }}
AFFINE_SIGNER_TOKEN: ${{ secrets.AFFINE_SIGNER_TOKEN }}
AFFINE_SIGNER_TS_AUTH_KEY: ${{ secrets.AFFINE_SIGNER_TS_AUTH_KEY }}
BUILD_TYPE: ${{ inputs.build-type }}
GITHUB_TOKEN: ${{ github.token }}
REQUIRE_SIGNER: ${{ inputs.require-windows-signing }}
WINDOWS_SIGNER_PUBLIC_CERT_BASE64: ${{ secrets.WINDOWS_SIGNER_PUBLIC_CERT_BASE64 }}
make-distribution-macos:
if: ${{ inputs.desktop_macos }}
+35 -9
View File
@@ -10,26 +10,52 @@ on:
type: string
jobs:
sign:
runs-on: [self-hosted, win-signer]
runs-on: windows-latest
env:
ARCHIVE_DIR: ${{ github.run_id }}-${{ github.run_attempt }}-${{ inputs.artifact-name }}
AFFINE_SIGNER_ADDR: ${{ secrets.AFFINE_SIGNER_ADDR }}
AFFINE_SIGNER_TOKEN: ${{ secrets.AFFINE_SIGNER_TOKEN }}
TS_AUTH_KEY: ${{ secrets.AFFINE_SIGNER_TS_AUTH_KEY }}
TS_CONTROL_URL: ${{ secrets.AFFINE_SIGNER_TS_CONTROL_URL }}
TS_RS_EXPERIMENT: this_is_unstable_software
steps:
- uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact-name }}
path: ${{ env.ARCHIVE_DIR }}
- name: Download remote signer client
shell: pwsh
run: |
if (!$env:AFFINE_SIGN_CLIENT_HASH) {
throw 'AFFINE_SIGN_CLIENT_HASH is required.'
}
Invoke-WebRequest -Uri "https://cdn.affine.pro/sign-client/$env:AFFINE_SIGN_CLIENT_HASH" -OutFile affine-sign-client.exe
env:
AFFINE_SIGN_CLIENT_HASH: ${{ secrets.AFFINE_SIGN_CLIENT_HASH }}
- name: Prepare public signing certificate
shell: pwsh
run: |
if (!$env:WINDOWS_SIGNER_PUBLIC_CERT_BASE64) {
throw 'WINDOWS_SIGNER_PUBLIC_CERT_BASE64 is required.'
}
[IO.File]::WriteAllBytes('windows-signer-public.cer', [Convert]::FromBase64String($env:WINDOWS_SIGNER_PUBLIC_CERT_BASE64))
env:
WINDOWS_SIGNER_PUBLIC_CERT_BASE64: ${{ secrets.WINDOWS_SIGNER_PUBLIC_CERT_BASE64 }}
- name: unzip file
shell: cmd
# 7za is pre-installed on the signer machine
shell: pwsh
run: |
cd ${{ env.ARCHIVE_DIR }}
md out
7za x archive.zip -y -oout
New-Item -ItemType Directory -Path '${{ env.ARCHIVE_DIR }}/out' -Force | Out-Null
Expand-Archive -Path '${{ env.ARCHIVE_DIR }}/archive.zip' -DestinationPath '${{ env.ARCHIVE_DIR }}/out'
- name: sign
shell: cmd
shell: pwsh
run: |
cd ${{ env.ARCHIVE_DIR }}/out
signtool sign /tr http://timestamp.globalsign.com/tsa/r6advanced1 /td sha256 /fd sha256 /a ${{ inputs.files }}
./affine-sign-client.exe `
--server "$env:AFFINE_SIGNER_ADDR" `
--token "$env:AFFINE_SIGNER_TOKEN" `
--workdir '${{ env.ARCHIVE_DIR }}/out' `
--files '${{ inputs.files }}' `
--cert windows-signer-public.cer `
--allow-file-fallback
- name: collect signed file diff
shell: powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File {0}
run: |
+11 -84
View File
@@ -4,47 +4,21 @@ const buildType = process.env.BUILD_TYPE;
const requireSigner =
process.env.REQUIRE_SIGNER === 'true' ||
['beta', 'stable'].includes(buildType);
const githubToken = process.env.GITHUB_TOKEN;
const repository = process.env.GITHUB_REPOSITORY;
const apiUrl = process.env.GITHUB_API_URL ?? 'https://api.github.com';
const outputPath = process.env.GITHUB_OUTPUT;
if (!githubToken) {
fail('Missing GITHUB_TOKEN.');
}
const missing = [
'AFFINE_SIGN_CLIENT_HASH',
'AFFINE_SIGNER_ADDR',
'AFFINE_SIGNER_TOKEN',
'AFFINE_SIGNER_TS_AUTH_KEY',
'WINDOWS_SIGNER_PUBLIC_CERT_BASE64',
].filter(name => !process.env[name]);
if (!repository) {
fail('Missing GITHUB_REPOSITORY.');
}
const [owner, repo] = repository.split('/');
if (!owner || !repo) {
fail(`Invalid GITHUB_REPOSITORY: ${repository}`);
}
try {
const runners = await listAllRunners(owner, repo);
const signerAvailable = runners.some(runner => {
const labels = (runner.labels ?? []).map(label => label.name);
return runner.status === 'online' && labels.includes('win-signer');
});
setOutput('signer_available', signerAvailable ? 'true' : 'false');
if (!signerAvailable) {
const message =
'No online self-hosted runner with label "win-signer" is available.';
if (requireSigner) {
fail(message);
} else {
console.warn(
`::warning::${message} Windows installer executables will be skipped.`
);
}
}
} catch (error) {
if (missing.length === 0) {
setOutput('signer_available', 'true');
} else {
setOutput('signer_available', 'false');
const message = `Failed to query self-hosted runner availability: ${formatError(error)}`;
const message = `Missing remote Windows signer configuration: ${missing.join(', ')}.`;
if (requireSigner) {
fail(message);
} else {
@@ -54,46 +28,6 @@ try {
}
}
async function listAllRunners(owner, repo) {
const runners = [];
let page = 1;
while (true) {
const url = new URL(
`/repos/${owner}/${repo}/actions/runners`,
ensureTrailingSlash(apiUrl)
);
url.searchParams.set('per_page', '100');
url.searchParams.set('page', String(page));
const response = await fetch(url, {
headers: {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${githubToken}`,
'X-GitHub-Api-Version': '2022-11-28',
},
});
if (!response.ok) {
const body = await response.text();
throw new Error(`GitHub API ${response.status}: ${body}`);
}
const data = await response.json();
runners.push(...(data.runners ?? []));
if ((data.runners ?? []).length < 100) {
return runners;
}
page += 1;
}
}
function ensureTrailingSlash(url) {
return url.endsWith('/') ? url : `${url}/`;
}
function setOutput(name, value) {
if (!outputPath) return;
fs.appendFileSync(outputPath, `${name}=${value}\n`);
@@ -103,10 +37,3 @@ function fail(message) {
console.error(`::error::${message}`);
process.exit(1);
}
function formatError(error) {
if (error instanceof Error) {
return error.message;
}
return String(error);
}