Initial commit
This commit is contained in:
366
.github/workflows/release.yml
vendored
Normal file
366
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
env:
|
||||
RUST_BACKTRACE: short
|
||||
HUSKY: 0
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
create-draft-release:
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
release_id: ${{ steps.release.outputs.release_id }}
|
||||
release_url: ${{ steps.release.outputs.release_url }}
|
||||
prerelease: ${{ steps.meta.outputs.prerelease }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- id: meta
|
||||
name: Resolve release channel
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${GITHUB_REF_NAME}" == *"-rc"* ]]; then
|
||||
echo "prerelease=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "prerelease=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Check tag commit belongs to default branch
|
||||
shell: bash
|
||||
run: |
|
||||
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
|
||||
git fetch origin "${DEFAULT_BRANCH}"
|
||||
|
||||
TAG_COMMIT=$(git rev-list -n 1 "${GITHUB_REF_NAME}")
|
||||
if git merge-base --is-ancestor "${TAG_COMMIT}" "origin/${DEFAULT_BRANCH}"; then
|
||||
echo "Tag ${GITHUB_REF_NAME} is based on ${DEFAULT_BRANCH}"
|
||||
else
|
||||
echo "Tag ${GITHUB_REF_NAME} is not based on ${DEFAULT_BRANCH}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Verify tag matches app version
|
||||
shell: bash
|
||||
run: |
|
||||
APP_VERSION=$(node -p "require('./src-tauri/tauri.conf.json').version")
|
||||
if [[ "v$APP_VERSION" != "${GITHUB_REF_NAME}" ]]; then
|
||||
echo "Tag ${GITHUB_REF_NAME} does not match app version v$APP_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- id: release
|
||||
name: Create or reuse draft release
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PRERELEASE: ${{ steps.meta.outputs.prerelease }}
|
||||
with:
|
||||
script: |
|
||||
const tag = context.ref.replace("refs/tags/", "");
|
||||
const { owner, repo } = context.repo;
|
||||
const prerelease = process.env.PRERELEASE === "true";
|
||||
let release;
|
||||
|
||||
try {
|
||||
const existing = await github.rest.repos.getReleaseByTag({
|
||||
owner,
|
||||
repo,
|
||||
tag,
|
||||
});
|
||||
|
||||
if (!existing.data.draft) {
|
||||
core.setFailed(
|
||||
`Release for tag ${tag} already exists and is not a draft.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
release = existing.data;
|
||||
if (release.prerelease !== prerelease) {
|
||||
const updated = await github.rest.repos.updateRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: release.id,
|
||||
prerelease,
|
||||
});
|
||||
release = updated.data;
|
||||
}
|
||||
core.info(`Reusing existing draft release #${release.id}`);
|
||||
} catch (error) {
|
||||
if (error.status !== 404) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const created = await github.rest.repos.createRelease({
|
||||
owner,
|
||||
repo,
|
||||
tag_name: tag,
|
||||
name: `codeg ${tag}`,
|
||||
body: [
|
||||
`Release channel: ${prerelease ? "Pre-release" : "Stable"}`,
|
||||
"",
|
||||
"Assets will be attached automatically by this workflow.",
|
||||
`Workflow run: https://github.com/${owner}/${repo}/actions/runs/${context.runId}`,
|
||||
].join("\n"),
|
||||
draft: true,
|
||||
prerelease,
|
||||
});
|
||||
|
||||
release = created.data;
|
||||
core.info(`Created draft release #${release.id}`);
|
||||
}
|
||||
|
||||
core.setOutput("release_id", String(release.id));
|
||||
core.setOutput("release_url", release.html_url);
|
||||
|
||||
build-tauri:
|
||||
needs: create-draft-release
|
||||
name: Build ${{ matrix.name }}
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: "macOS x64"
|
||||
runner: "macos-latest"
|
||||
target: "x86_64-apple-darwin"
|
||||
- name: "macOS arm64"
|
||||
runner: "macos-latest"
|
||||
target: "aarch64-apple-darwin"
|
||||
- name: "Linux x64"
|
||||
runner: "ubuntu-22.04"
|
||||
target: "x86_64-unknown-linux-gnu"
|
||||
- name: "Linux arm64"
|
||||
runner: "ubuntu-22.04"
|
||||
target: "aarch64-unknown-linux-gnu"
|
||||
- name: "Windows x64"
|
||||
runner: "windows-2022"
|
||||
target: "x86_64-pc-windows-msvc"
|
||||
- name: "Windows arm64"
|
||||
runner: "windows-latest"
|
||||
target: "aarch64-pc-windows-msvc"
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
run_install: false
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Rust cache
|
||||
uses: swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: "./src-tauri -> target"
|
||||
|
||||
- name: Install Linux x64 dependencies
|
||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
libwebkit2gtk-4.1-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
librsvg2-dev \
|
||||
patchelf
|
||||
|
||||
- name: Install Linux arm64 cross dependencies
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
cat > /tmp/sources.list << 'EOF'
|
||||
deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse
|
||||
deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse
|
||||
deb [arch=amd64] http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
|
||||
deb [arch=amd64] http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse
|
||||
|
||||
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse
|
||||
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse
|
||||
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
|
||||
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse
|
||||
EOF
|
||||
sudo mv /etc/apt/sources.list /etc/apt/sources.list.default
|
||||
sudo mv /tmp/sources.list /etc/apt/sources.list
|
||||
|
||||
sudo dpkg --add-architecture arm64
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
libwebkit2gtk-4.1-dev:arm64 \
|
||||
libayatana-appindicator3-dev:arm64 \
|
||||
librsvg2-dev:arm64 \
|
||||
libssl-dev:arm64 \
|
||||
patchelf
|
||||
|
||||
- name: Configure Linux arm64 cross env
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "PKG_CONFIG_ALLOW_CROSS=1" >> "$GITHUB_ENV"
|
||||
echo "PKG_CONFIG_PATH=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV"
|
||||
echo "PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" >> "$GITHUB_ENV"
|
||||
echo "PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu" >> "$GITHUB_ENV"
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR=aarch64-linux-gnu-gcc-ar" >> "$GITHUB_ENV"
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=-Clinker=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
|
||||
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
|
||||
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> "$GITHUB_ENV"
|
||||
echo "AR_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc-ar" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Verify Linux arm64 cross toolchain
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
shell: bash
|
||||
run: |
|
||||
which aarch64-linux-gnu-gcc
|
||||
aarch64-linux-gnu-gcc -v
|
||||
rustup target list --installed
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER}"
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR}"
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS=${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS}"
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build and upload to draft release (Linux arm64)
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
uses: tauri-apps/tauri-action@v0.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
PKG_CONFIG_ALLOW_CROSS: 1
|
||||
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig
|
||||
PKG_CONFIG_LIBDIR: /usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig
|
||||
PKG_CONFIG_SYSROOT_DIR: /usr/aarch64-linux-gnu
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_AR: aarch64-linux-gnu-gcc-ar
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS: -Clinker=aarch64-linux-gnu-gcc
|
||||
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
|
||||
CXX_aarch64_unknown_linux_gnu: aarch64-linux-gnu-g++
|
||||
AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc-ar
|
||||
with:
|
||||
releaseId: ${{ needs.create-draft-release.outputs.release_id }}
|
||||
tagName: ${{ github.ref_name }}
|
||||
releaseDraft: true
|
||||
prerelease: ${{ needs.create-draft-release.outputs.prerelease }}
|
||||
tauriScript: pnpm tauri
|
||||
args: --target ${{ matrix.target }} --bundles deb,rpm
|
||||
includeUpdaterJson: false
|
||||
retryAttempts: 2
|
||||
|
||||
- name: Build and upload to draft release (Non-Linux arm64)
|
||||
if: matrix.target != 'aarch64-unknown-linux-gnu'
|
||||
uses: tauri-apps/tauri-action@v0.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
with:
|
||||
releaseId: ${{ needs.create-draft-release.outputs.release_id }}
|
||||
tagName: ${{ github.ref_name }}
|
||||
releaseDraft: true
|
||||
prerelease: ${{ needs.create-draft-release.outputs.prerelease }}
|
||||
tauriScript: pnpm tauri
|
||||
args: --target ${{ matrix.target }}
|
||||
includeUpdaterJson: true
|
||||
retryAttempts: 2
|
||||
|
||||
publish-release:
|
||||
needs:
|
||||
- create-draft-release
|
||||
- build-tauri
|
||||
if: ${{ needs.build-tauri.result == 'success' }}
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Publish draft release
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
RELEASE_ID: ${{ needs.create-draft-release.outputs.release_id }}
|
||||
with:
|
||||
script: |
|
||||
const { owner, repo } = context.repo;
|
||||
const releaseId = Number(process.env.RELEASE_ID);
|
||||
const prerelease =
|
||||
"${{ needs.create-draft-release.outputs.prerelease }}" === "true";
|
||||
const tag = context.ref.replace("refs/tags/", "");
|
||||
|
||||
const { data: tagRef } = await github.rest.git.getRef({
|
||||
owner,
|
||||
repo,
|
||||
ref: `tags/${tag}`,
|
||||
});
|
||||
|
||||
let commitSha = tagRef.object.sha;
|
||||
if (tagRef.object.type === "tag") {
|
||||
const { data: annotatedTag } = await github.rest.git.getTag({
|
||||
owner,
|
||||
repo,
|
||||
tag_sha: commitSha,
|
||||
});
|
||||
if (annotatedTag.object.type !== "commit") {
|
||||
core.setFailed(
|
||||
`Tag ${tag} points to ${annotatedTag.object.type}, not a commit.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
commitSha = annotatedTag.object.sha;
|
||||
}
|
||||
|
||||
const { data: commit } = await github.rest.repos.getCommit({
|
||||
owner,
|
||||
repo,
|
||||
ref: commitSha,
|
||||
});
|
||||
|
||||
const commitMessage =
|
||||
commit.commit.message?.trim() || "_No commit message._";
|
||||
|
||||
const body = [
|
||||
`Release channel: ${prerelease ? "Pre-release" : "Stable"}`,
|
||||
"",
|
||||
"## Release notes",
|
||||
commitMessage,
|
||||
].join("\n");
|
||||
|
||||
await github.rest.repos.updateRelease({
|
||||
owner,
|
||||
repo,
|
||||
release_id: releaseId,
|
||||
body,
|
||||
draft: false,
|
||||
prerelease,
|
||||
});
|
||||
|
||||
core.info(`Published release #${releaseId}`);
|
||||
Reference in New Issue
Block a user