Skip to content

ci: assemble complete latest.json across all platforms #111

ci: assemble complete latest.json across all platforms

ci: assemble complete latest.json across all platforms #111

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
jobs:
release:
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
target: x86_64-apple-darwin
args:
- os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
args:
- os: windows-latest
target: x86_64-pc-windows-msvc
args:
- os: macos-latest
target: aarch64-apple-darwin
args:
- os: windows-latest
target: aarch64-pc-windows-msvc
args: --bundles nsis,updater
- os: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
args:
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: AlistGo/desktop
token: ${{ secrets.MY_TOKEN }}
- name: Install dependencies (ubuntu only)
if: contains(matrix.target, 'unknown-linux-gnu')
# You can remove libayatana-appindicator3-dev if you don't use the system tray feature.
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev
- name: Rust setup
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: "./src-tauri -> target"
- uses: pnpm/action-setup@v2
with:
version: 9
run_install: false
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: "pnpm" # Set this to npm, yarn or pnpm.
- name: Install app dependencies and build web
run: pnpm i
- name: Replace version
run: |
npx tsx ./scripts/version.ts
cat src-tauri/tauri.conf.json
env:
AD_VERSION: ${{ github.ref_name }}
- name: Get AList version
id: get-alist-version
uses: fangqiuming/latest-release-version@v1.2.0-beta
with:
repository: AlistGo/alist
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get Rclone version
id: get-rclone-version
uses: fangqiuming/latest-release-version@v1.2.0-beta
with:
repository: rclone/rclone
token: ${{ secrets.GITHUB_TOKEN }}
- name: Download sidecar
run: npx tsx ./scripts/bin.ts
env:
TARGET_TRIPLE: ${{ matrix.target }}
ALIST_VERSION: ${{ steps.get-alist-version.outputs.tag_name }} # v3.19.0
RCLONE_VERSION: ${{ steps.get-rclone-version.outputs.tag_name }} # v1.63.0
- name: Build & publish (coordinator uploads latest.json)
if: ${{ matrix.os == 'macos-latest' && matrix.target == 'x86_64-apple-darwin' }}
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.MY_TOKEN }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
with:
tagName: ${{ github.ref_name }} # This only works if your workflow triggers on new tags.
releaseName: "AList Desktop v__VERSION__" # tauri-action replaces \_\_VERSION\_\_ with the app version.
releaseBody: "See the assets to download and install this version."
args: "--target ${{ matrix.target }} ${{ matrix.args }}"
- name: Build & publish (no updater json)
if: ${{ !(matrix.os == 'macos-latest' && matrix.target == 'x86_64-apple-darwin') }}
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.MY_TOKEN }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
with:
tagName: ${{ github.ref_name }} # This only works if your workflow triggers on new tags.
releaseName: "AList Desktop v__VERSION__" # tauri-action replaces \_\_VERSION\_\_ with the app version.
releaseBody: "See the assets to download and install this version."
args: "--target ${{ matrix.target }} ${{ matrix.args }}"
includeUpdaterJson: false
build_updater:
name: "Build updater"
needs: release
environment: ${{ github.event.inputs.environment || 'Beta' }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 9
run_install: false
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version: "lts/*"
# cache: "pnpm" # Set this to npm, yarn or pnpm.
- name: Generate proxy.json
run: |
npx tsx ./proxy.ts
- name: Upload proxy.json
uses: softprops/action-gh-release@v1
with:
fail_on_unmatched_files: true
token: ${{ secrets.MY_TOKEN }}
files: |
*.proxy.json
compose_latest_json:
name: "Compose complete latest.json"
needs: release
runs-on: ubuntu-latest
steps:
- name: Assemble latest.json from every platform's updater assets
uses: actions/github-script@v7
with:
github-token: ${{ secrets.MY_TOKEN }}
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const tag = "${{ github.ref_name }}";
const rel = await github.rest.repos.getReleaseByTag({ owner, repo, tag });
const assets = await github.paginate(github.rest.repos.listReleaseAssets, {
owner, repo, release_id: rel.data.id, per_page: 100,
});
const byName = new Map(assets.map((a) => [a.name, a]));
const downloadUrl = (name) =>
`https://github.com/${owner}/${repo}/releases/download/${tag}/${encodeURIComponent(name)}`;
async function readSig(name) {
const a = byName.get(name + ".sig");
if (!a) return null;
const res = await github.request(
"GET /repos/{owner}/{repo}/releases/assets/{asset_id}",
{ owner, repo, asset_id: a.id, headers: { accept: "application/octet-stream" } }
);
return Buffer.from(res.data).toString("utf8").trim();
}
// First non-.sig asset whose name matches the regex.
const pick = (re) =>
(assets.find((a) => re.test(a.name) && !a.name.endsWith(".sig")) || {}).name;
const macX = pick(/^alist-desktop_x64\.app\.tar\.gz$/);
const macA = pick(/^alist-desktop_aarch64\.app\.tar\.gz$/);
const winXmsi = pick(/_x64_en-US\.msi\.zip$/);
const winXnsis = pick(/_x64-setup\.nsis\.zip$/);
const winA = pick(/_arm64-setup\.nsis\.zip$/);
const linX = pick(/_amd64\.AppImage\.tar\.gz$/);
const linA = pick(/_aarch64\.AppImage\.tar\.gz$/);
const platforms = {};
async function add(key, name) {
if (!name) return;
const signature = await readSig(name);
if (signature == null) {
core.warning(`no .sig for ${name}, skipping ${key}`);
return;
}
platforms[key] = { signature, url: downloadUrl(name) };
}
await add("darwin-x86_64", macX);
await add("darwin-x86_64-app", macX);
await add("darwin-aarch64", macA);
await add("darwin-aarch64-app", macA);
await add("windows-x86_64", winXmsi || winXnsis);
if (winXmsi) await add("windows-x86_64-msi", winXmsi);
if (winXnsis) await add("windows-x86_64-nsis", winXnsis);
await add("windows-aarch64", winA);
await add("windows-aarch64-nsis", winA);
await add("linux-x86_64", linX);
await add("linux-aarch64", linA);
if (Object.keys(platforms).length === 0) {
core.setFailed("No updater artifacts found; latest.json not composed");
return;
}
let version = tag.replace(/^v/, "");
const versioned = winXnsis || winXmsi || winA || linX || linA || "";
const vm = versioned.match(/alist-desktop_([0-9][^_]*)_/);
if (vm) version = vm[1];
const latest = {
version,
notes: "See the assets to download and install this version.",
pub_date: new Date().toISOString(),
platforms,
};
const body = JSON.stringify(latest, null, 2);
core.info("Composed latest.json:\n" + body);
const existing = byName.get("latest.json");
if (existing) {
await github.rest.repos.deleteReleaseAsset({ owner, repo, asset_id: existing.id });
}
await github.rest.repos.uploadReleaseAsset({
owner, repo, release_id: rel.data.id,
name: "latest.json",
data: body,
headers: {
"content-type": "application/json",
"content-length": Buffer.byteLength(body),
},
});
core.info(`Uploaded latest.json with platforms: ${Object.keys(platforms).join(", ")}`);