diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml index 3a8b4ec..f43a440 100644 --- a/.forgejo/workflows/release.yaml +++ b/.forgejo/workflows/release.yaml @@ -15,33 +15,18 @@ jobs: - name: Check out source uses: https://data.forgejo.org/actions/checkout@v6 - - name: Install Rust and cross-compilation toolchains + - name: Install Rust toolchain run: | apt-get update apt-get install --yes --no-install-recommends \ - binutils \ build-essential \ ca-certificates \ curl \ - file \ - pkg-config \ - python3-venv + pkg-config curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs \ | sh -s -- --default-toolchain stable --profile minimal --no-modify-path -y echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" - "$HOME/.cargo/bin/rustup" target add \ - x86_64-unknown-linux-musl \ - aarch64-unknown-linux-musl - python3 -m venv /opt/cargo-zigbuild - /opt/cargo-zigbuild/bin/pip install \ - --disable-pip-version-check \ - --no-cache-dir \ - cargo-zigbuild==0.23.0 \ - ziglang==0.16.0 - echo "/opt/cargo-zigbuild/bin" >> "$GITHUB_PATH" "$HOME/.cargo/bin/rustc" --version - /opt/cargo-zigbuild/bin/cargo-zigbuild --version - /opt/cargo-zigbuild/bin/python -m ziglang version - name: Install frontend dependencies working-directory: frontend @@ -57,11 +42,62 @@ jobs: export PIXHELF_SKIP_FRONTEND_BUILD=1 cargo test --locked + release: + if: startsWith(forgejo.ref, 'refs/tags/v') + needs: build + runs-on: docker + container: + image: docker.io/library/node:22-bookworm + volumes: + - /var/run/docker.sock:/var/run/docker.sock + env: + # The runner's Docker daemon uses the containerd image store, which does + # not expose the MergedDir required by CROSS_CONTAINER_IN_CONTAINER. + # Remote mode transfers the project and artifacts through Docker volumes. + CROSS_REMOTE: "true" + # Non-hidden paths are required so cross can expose the Rust toolchain in + # the remote build container when the workflow itself runs as root. + CARGO_HOME: /opt/cargo + RUSTUP_HOME: /opt/rustup + steps: + - name: Check out source + uses: https://data.forgejo.org/actions/checkout@v6 + + - name: Install Rust, Docker CLI, and cross + run: | + apt-get update + apt-get install --yes --no-install-recommends \ + binutils \ + build-essential \ + ca-certificates \ + curl \ + docker.io \ + file \ + pkg-config + curl --proto '=https' --tlsv1.2 --silent --show-error --fail https://sh.rustup.rs \ + | sh -s -- --default-toolchain stable --profile minimal --no-modify-path -y + echo "$CARGO_HOME/bin" >> "$GITHUB_PATH" + "$CARGO_HOME/bin/cargo" install \ + --git https://github.com/cross-rs/cross \ + --rev 8c1a8aa4b661711f4b7b6ac07c2e8929ce2f7d27 \ + --locked \ + cross + docker version + "$CARGO_HOME/bin/rustc" --version + "$CARGO_HOME/bin/cross" --version + + - name: Install frontend dependencies + working-directory: frontend + run: npm ci + + - name: Build frontend + working-directory: frontend + run: npm run build + - name: Build static musl release binaries run: | set -eu - export PATH="/opt/cargo-zigbuild/bin:$HOME/.cargo/bin:$PATH" - export CARGO_ZIGBUILD_PYTHON_PATH=/opt/cargo-zigbuild/bin/python + export PATH="$CARGO_HOME/bin:$PATH" export PIXHELF_SKIP_FRONTEND_BUILD=1 mkdir -p dist @@ -71,7 +107,7 @@ jobs: machine="$3" binary="target/${target}/release/pixhelf" - cargo zigbuild --release --locked --target "$target" + cross build --release --locked --target "$target" file "$binary" if ! readelf -h "$binary" | grep -q "Machine:.*${machine}"; then @@ -102,13 +138,11 @@ jobs: dist/pixhelf-amd64-linux --help >/dev/null - name: Prepare release metadata - if: startsWith(forgejo.ref, 'refs/tags/v') run: | tag="${FORGEJO_REF_NAME:-${GITHUB_REF_NAME}}" printf 'RELEASE_TAG=%s\n' "$tag" >> "$GITHUB_ENV" - name: Create Forgejo release and upload assets - if: startsWith(forgejo.ref, 'refs/tags/v') run: | set -eu token="${FORGEJO_TOKEN:-${GITHUB_TOKEN:-}}" diff --git a/Cargo.lock b/Cargo.lock index 01e5330..6413ebf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -618,7 +618,7 @@ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pixhelf" -version = "0.1.7" +version = "0.1.8" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index d32036c..4589156 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pixhelf" -version = "0.1.7" +version = "0.1.8" edition = "2024" build = "build.rs" diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 0000000..4c75105 --- /dev/null +++ b/Cross.toml @@ -0,0 +1,8 @@ +# The frontend assets are architecture-independent and are built on the host +# before cross is invoked. build.rs then embeds the existing frontend/dist +# files without requiring Node.js inside the cross container. +[build] +default-target = "x86_64-unknown-linux-musl" + +[build.env] +passthrough = ["PIXHELF_SKIP_FRONTEND_BUILD=1"] diff --git a/README.md b/README.md index 9358967..b3f6944 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,24 @@ cargo build --release `cargo build` 会自动执行 React 生产构建,并将结果嵌入 `target/release/pixhelf`。 -发布工作流使用 musl 静态链接,并在同一台 AMD64 构建机上交叉编译两个版本: +使用 `cross` 交叉编译 musl 版本时,先在宿主机生成与架构无关的前端资源; +`Cross.toml` 会让容器直接复用这些资源,因此容器内不需要安装 Node.js: + +```bash +npm ci --prefix frontend +npm run build --prefix frontend + +# 默认 target,由 Cross.toml 配置为 AMD64 musl +cross build --release --locked + +# ARM64 musl +cross build --release --locked --target aarch64-unknown-linux-musl +``` + +产物分别位于 `target/x86_64-unknown-linux-musl/release/pixhelf` 和 +`target/aarch64-unknown-linux-musl/release/pixhelf`。 + +发布工作流使用 `cross` 和 musl 静态链接,并在同一台 AMD64 构建机上交叉编译两个版本: - `pixhelf-amd64-linux`:`x86_64-unknown-linux-musl` - `pixhelf-arm64-linux`:`aarch64-unknown-linux-musl` diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 476552e..132e882 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "pixhelf-frontend", - "version": "0.1.7", + "version": "0.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pixhelf-frontend", - "version": "0.1.7", + "version": "0.1.8", "dependencies": { "preact": "^10.27.1" }, diff --git a/frontend/package.json b/frontend/package.json index 58fe9df..1410646 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "pixhelf-frontend", "private": true, - "version": "0.1.7", + "version": "0.1.8", "type": "module", "scripts": { "dev": "vite --host 0.0.0.0",