mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-09-19 16:21:37 +02:00
fix: retry release uploads and retain artifacts for seven days (#690)
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
// Retain only distributable bundle files, never the target tree or signing material.
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
import {
|
||||||
|
copyFileSync,
|
||||||
|
createReadStream,
|
||||||
|
existsSync,
|
||||||
|
mkdirSync,
|
||||||
|
readdirSync,
|
||||||
|
writeFileSync,
|
||||||
|
} from "node:fs";
|
||||||
|
import { join, relative } from "node:path";
|
||||||
|
|
||||||
|
const env = process.env;
|
||||||
|
const bundle = join("target", env.RELEASE_TARGET || "", "release", "bundle");
|
||||||
|
const destination = join(env.RUNNER_TEMP, "yaak-release-artifacts");
|
||||||
|
const extensions =
|
||||||
|
/\.(dmg|deb|rpm|AppImage|exe|msi|app\.tar\.gz|AppImage\.tar\.gz|nsis\.zip|msi\.zip)(\.sig)?$/;
|
||||||
|
const files = [];
|
||||||
|
|
||||||
|
function snapshot(directory) {
|
||||||
|
if (!existsSync(directory)) return;
|
||||||
|
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
||||||
|
const source = join(directory, entry.name);
|
||||||
|
// Only descend through the bundler's immediate output folders. This excludes
|
||||||
|
// .app trees and the extracted CEF deb contents (which contain executables).
|
||||||
|
if (entry.isDirectory() && directory === bundle) {
|
||||||
|
snapshot(source);
|
||||||
|
} else if (
|
||||||
|
entry.isFile() &&
|
||||||
|
(extensions.test(entry.name) || /^yaak-cef_.*_linux_.*\.tar\.gz$/.test(entry.name))
|
||||||
|
) {
|
||||||
|
// Match tauri-action's default macOS updater asset naming exactly.
|
||||||
|
const arch = env.RELEASE_ARCH === "arm64" ? "aarch64" : "x64";
|
||||||
|
const assetName = entry.name.replace(/\.app\.tar\.gz(\.sig)?$/, `_${arch}.app.tar.gz$1`);
|
||||||
|
mkdirSync(destination, { recursive: true });
|
||||||
|
const retained = join(destination, assetName);
|
||||||
|
// The second snapshot must not overwrite the original user installer/signature.
|
||||||
|
if (!existsSync(retained)) copyFileSync(source, retained);
|
||||||
|
files.push({ source: relative(".", source), assetName });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot(bundle);
|
||||||
|
if (existsSync(destination)) {
|
||||||
|
const assets = readdirSync(destination)
|
||||||
|
.filter((name) => name !== "provenance.json")
|
||||||
|
.sort();
|
||||||
|
const checksums = [];
|
||||||
|
for (const assetName of assets) {
|
||||||
|
const hash = createHash("sha256");
|
||||||
|
for await (const chunk of createReadStream(join(destination, assetName))) hash.update(chunk);
|
||||||
|
checksums.push({ assetName, sha256: hash.digest("hex") });
|
||||||
|
}
|
||||||
|
writeFileSync(
|
||||||
|
join(destination, "provenance.json"),
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
repository: env.GITHUB_REPOSITORY,
|
||||||
|
tag: env.GITHUB_REF_NAME,
|
||||||
|
sha: env.GITHUB_SHA,
|
||||||
|
runId: env.GITHUB_RUN_ID,
|
||||||
|
runAttempt: env.GITHUB_RUN_ATTEMPT,
|
||||||
|
workflowRef: env.GITHUB_WORKFLOW_REF,
|
||||||
|
workflowSha: env.GITHUB_WORKFLOW_SHA,
|
||||||
|
tauriAction: "tauri-apps/tauri-action@v0",
|
||||||
|
platform: env.RELEASE_PLATFORM,
|
||||||
|
runtime: env.RELEASE_RUNTIME,
|
||||||
|
arch: env.RELEASE_ARCH,
|
||||||
|
target: env.RELEASE_TARGET,
|
||||||
|
args: env.RELEASE_ARGS,
|
||||||
|
assets: checksums,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
) + "\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log(`Found ${files.length} distributable bundle files in ${bundle}`);
|
||||||
@@ -172,7 +172,8 @@ jobs:
|
|||||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/protoc/yaakprotoc || true
|
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/protoc/yaakprotoc || true
|
||||||
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/node/yaaknode || true
|
codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/node/yaaknode || true
|
||||||
|
|
||||||
- uses: tauri-apps/tauri-action@v0
|
- name: Build and upload Tauri bundles
|
||||||
|
uses: tauri-apps/tauri-action@v0
|
||||||
env:
|
env:
|
||||||
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
|
||||||
|
|
||||||
@@ -194,6 +195,8 @@ jobs:
|
|||||||
AZURE_CLIENT_SECRET: ${{ matrix.os == 'windows' && secrets.AZURE_CLIENT_SECRET }}
|
AZURE_CLIENT_SECRET: ${{ matrix.os == 'windows' && secrets.AZURE_CLIENT_SECRET }}
|
||||||
AZURE_TENANT_ID: ${{ matrix.os == 'windows' && secrets.AZURE_TENANT_ID }}
|
AZURE_TENANT_ID: ${{ matrix.os == 'windows' && secrets.AZURE_TENANT_ID }}
|
||||||
with:
|
with:
|
||||||
|
# Also retries builds; upload retries alone cannot clean up starter assets.
|
||||||
|
retryAttempts: 3
|
||||||
tauriScript: "node ../../node_modules/@tauri-apps/cli/tauri.js"
|
tauriScript: "node ../../node_modules/@tauri-apps/cli/tauri.js"
|
||||||
tagName: "v__VERSION__"
|
tagName: "v__VERSION__"
|
||||||
releaseName: "Release __VERSION__"
|
releaseName: "Release __VERSION__"
|
||||||
@@ -203,6 +206,17 @@ jobs:
|
|||||||
projectPath: ./crates-tauri/yaak-app-client
|
projectPath: ./crates-tauri/yaak-app-client
|
||||||
args: "${{ matrix.args }}"
|
args: "${{ matrix.args }}"
|
||||||
|
|
||||||
|
# Snapshot before the per-machine build overwrites the regular NSIS bundle/signature.
|
||||||
|
- name: Snapshot Tauri bundles
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
run: node .github/scripts/preserve-release-artifacts.mjs
|
||||||
|
env:
|
||||||
|
RELEASE_TARGET: ${{ matrix.targets }}
|
||||||
|
RELEASE_PLATFORM: ${{ matrix.platform }}
|
||||||
|
RELEASE_RUNTIME: ${{ matrix.runtime }}
|
||||||
|
RELEASE_ARCH: ${{ matrix.yaak_arch }}
|
||||||
|
RELEASE_ARGS: ${{ matrix.args }}
|
||||||
|
|
||||||
- name: Build and upload CEF tarball from deb (Linux only)
|
- name: Build and upload CEF tarball from deb (Linux only)
|
||||||
if: matrix.os == 'ubuntu' && matrix.runtime == 'cef'
|
if: matrix.os == 'ubuntu' && matrix.runtime == 'cef'
|
||||||
env:
|
env:
|
||||||
@@ -217,7 +231,13 @@ jobs:
|
|||||||
mkdir -p "$extract_dir"
|
mkdir -p "$extract_dir"
|
||||||
dpkg-deb -x "$deb" "$extract_dir"
|
dpkg-deb -x "$deb" "$extract_dir"
|
||||||
tar -C "$extract_dir" -czf "$tarball" .
|
tar -C "$extract_dir" -czf "$tarball" .
|
||||||
gh release upload "${{ github.ref_name }}" "$tarball" --clobber
|
for attempt in 1 2 3 4; do
|
||||||
|
if gh release upload "$GITHUB_REF_NAME" "$tarball" --clobber; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$attempt" -eq 4 ]; then exit 1; fi
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
|
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
|
||||||
- name: Build and upload machine-wide installer (Windows only)
|
- name: Build and upload machine-wide installer (Windows only)
|
||||||
@@ -235,6 +255,7 @@ jobs:
|
|||||||
Get-ChildItem -Recurse -Path target -File -Filter "*.exe.sig" | Remove-Item -Force
|
Get-ChildItem -Recurse -Path target -File -Filter "*.exe.sig" | Remove-Item -Force
|
||||||
Push-Location crates-tauri/yaak-app-client
|
Push-Location crates-tauri/yaak-app-client
|
||||||
npx tauri bundle ${{ matrix.args }} --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
|
npx tauri bundle ${{ matrix.args }} --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
Pop-Location
|
Pop-Location
|
||||||
$setup = Get-ChildItem -Recurse -Path target -Filter "*setup*.exe" | Select-Object -First 1
|
$setup = Get-ChildItem -Recurse -Path target -Filter "*setup*.exe" | Select-Object -First 1
|
||||||
$setupSig = "$($setup.FullName).sig"
|
$setupSig = "$($setup.FullName).sig"
|
||||||
@@ -242,5 +263,30 @@ jobs:
|
|||||||
$destSig = "$dest.sig"
|
$destSig = "$dest.sig"
|
||||||
Copy-Item $setup.FullName $dest
|
Copy-Item $setup.FullName $dest
|
||||||
Copy-Item $setupSig $destSig
|
Copy-Item $setupSig $destSig
|
||||||
gh release upload "${{ github.ref_name }}" "$dest" --clobber
|
foreach ($asset in @($dest, $destSig)) {
|
||||||
gh release upload "${{ github.ref_name }}" "$destSig" --clobber
|
for ($attempt = 1; $attempt -le 4; $attempt++) {
|
||||||
|
gh release upload "$env:GITHUB_REF_NAME" "$asset" --clobber
|
||||||
|
if ($LASTEXITCODE -eq 0) { break }
|
||||||
|
if ($attempt -eq 4) { exit $LASTEXITCODE }
|
||||||
|
Start-Sleep -Seconds 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Snapshot additional release bundles
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
run: node .github/scripts/preserve-release-artifacts.mjs
|
||||||
|
env:
|
||||||
|
RELEASE_TARGET: ${{ matrix.targets }}
|
||||||
|
RELEASE_PLATFORM: ${{ matrix.platform }}
|
||||||
|
RELEASE_RUNTIME: ${{ matrix.runtime }}
|
||||||
|
RELEASE_ARCH: ${{ matrix.yaak_arch }}
|
||||||
|
RELEASE_ARGS: ${{ matrix.args }}
|
||||||
|
|
||||||
|
- name: Retain release bundles for recovery
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-${{ github.ref_name }}-${{ matrix.platform }}-${{ matrix.runtime }}-${{ matrix.yaak_arch }}-${{ github.run_id }}-attempt-${{ github.run_attempt }}
|
||||||
|
path: ${{ runner.temp }}/yaak-release-artifacts/
|
||||||
|
retention-days: 7
|
||||||
|
if-no-files-found: warn
|
||||||
|
|||||||
Reference in New Issue
Block a user