mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-04 03:01:25 +08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b712b6e43b | |||
| 7e75373c5c | |||
| d26ce6125a | |||
| fc90615350 |
@@ -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 }}
|
||||
@@ -179,6 +183,7 @@ jobs:
|
||||
- windows-signer-gate
|
||||
- package-distribution-windows-x64
|
||||
uses: ./.github/workflows/windows-signer.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
files: ${{ needs.package-distribution-windows-x64.outputs.files_to_be_signed }}
|
||||
artifact-name: packaged-win32-x64
|
||||
@@ -189,6 +194,7 @@ jobs:
|
||||
- windows-signer-gate
|
||||
- package-distribution-windows-arm64
|
||||
uses: ./.github/workflows/windows-signer.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
files: ${{ needs.package-distribution-windows-arm64.outputs.files_to_be_signed }}
|
||||
artifact-name: packaged-win32-arm64
|
||||
@@ -311,6 +317,7 @@ jobs:
|
||||
- windows-signer-gate
|
||||
- make-windows-installer
|
||||
uses: ./.github/workflows/windows-signer.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
files: ${{ needs.make-windows-installer.outputs.FILES_TO_BE_SIGNED_x64 }}
|
||||
artifact-name: installer-win32-x64
|
||||
@@ -321,6 +328,7 @@ jobs:
|
||||
- windows-signer-gate
|
||||
- make-windows-installer
|
||||
uses: ./.github/workflows/windows-signer.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
files: ${{ needs.make-windows-installer.outputs.FILES_TO_BE_SIGNED_arm64 }}
|
||||
artifact-name: installer-win32-arm64
|
||||
|
||||
@@ -10,26 +10,91 @@ 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_RS_EXPERIMENT: this_is_unstable_software
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ inputs.artifact-name }}
|
||||
path: ${{ env.ARCHIVE_DIR }}
|
||||
- name: Connect Tailscale
|
||||
uses: tailscale/github-action@v4
|
||||
with:
|
||||
authkey: ${{ secrets.AFFINE_SIGNER_TS_AUTH_KEY }}
|
||||
hostname: affine-signer-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Check signer connectivity
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Parts = "$env:AFFINE_SIGNER_ADDR".Split(':')
|
||||
if ($Parts.Count -ne 2) {
|
||||
throw "AFFINE_SIGNER_ADDR must be host:port, got $env:AFFINE_SIGNER_ADDR"
|
||||
}
|
||||
|
||||
$Result = Test-NetConnection -ComputerName $Parts[0] -Port ([int]$Parts[1])
|
||||
if (!$Result.TcpTestSucceeded) {
|
||||
throw "Unable to connect to signer at $env:AFFINE_SIGNER_ADDR"
|
||||
}
|
||||
- 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: Resolve signtool
|
||||
shell: pwsh
|
||||
run: |
|
||||
$Command = Get-Command signtool.exe -ErrorAction SilentlyContinue
|
||||
if ($Command) {
|
||||
"SIGNTOOL=$($Command.Source)" >> $env:GITHUB_ENV
|
||||
Write-Host "Using signtool: $($Command.Source)"
|
||||
exit 0
|
||||
}
|
||||
|
||||
$KitsRoot = "${env:ProgramFiles(x86)}\Windows Kits\10\bin"
|
||||
$Candidates = @()
|
||||
if (Test-Path -LiteralPath $KitsRoot) {
|
||||
$Candidates = Get-ChildItem -Path $KitsRoot -Recurse -Filter signtool.exe |
|
||||
Where-Object { $_.FullName -match '\\x64\\signtool\.exe$' } |
|
||||
Sort-Object FullName -Descending
|
||||
}
|
||||
|
||||
if ($Candidates.Count -eq 0) {
|
||||
throw "Unable to find signtool.exe under PATH or $KitsRoot"
|
||||
}
|
||||
|
||||
"SIGNTOOL=$($Candidates[0].FullName)" >> $env:GITHUB_ENV
|
||||
Write-Host "Using signtool: $($Candidates[0].FullName)"
|
||||
- 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 `
|
||||
--plain-tcp
|
||||
- name: collect signed file diff
|
||||
shell: powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File {0}
|
||||
run: |
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user