diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index cde69a462..4c112c5f4 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -11,19 +11,133 @@ on: jobs: package: - uses: pendulum-project/ploutos/.github/workflows/pkg-rust.yml@provide-debug-symbols - with: - workspace_package: statime-linux + runs-on: ubuntu-latest + strategy: + matrix: + target: + - aarch64-unknown-linux-gnu + - armv7-unknown-linux-gnueabihf + - x86_64-unknown-linux-gnu + - i686-unknown-linux-gnu + steps: + - name: Setup packaging tools for cross compiled artifacts + uses: awalsh128/cache-apt-pkgs-action@a6c3917cc929dd0345bfb2d3feaf9101823370ad # v1.4.2 + with: + packages: qemu-user-static crossbuild-essential-armhf crossbuild-essential-arm64 crossbuild-essential-i386 + version: 1 - package_build_rules: | - pkg: statime - image: - - "ubuntu:xenial" - target: x86_64 + - name: Install toolchain + uses: dtolnay/rust-toolchain@d8352f6b1d2e870bc5716e7a6d9b65c4cc244a1a + with: + toolchain: "stable" + components: "llvm-tools" - package_test_scripts_path: pkg/test-scripts/test-statime.sh + - name: Install cross, cargo-deb and cargo-generate-rpm + uses: taiki-e/install-action@60784cb1f434ce8a3cc04670ea753e1c8868e17e + with: + tool: cross, cargo-deb, cargo-generate-rpm - rpm_scriptlets_path: pkg/rpm/scriptlets.toml + - name: Checkout sources + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - rpm_extra_build_packages: git - deb_extra_build_packages: git + - name: Build the release binaries + run: RELEASE_TARGETS="${{ matrix.target }}" utils/build-release.sh + + - name: Upload artifacts + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: release-binaries-${{ matrix.target }} + path: target/pkg/ + if-no-files-found: error + + gather: + needs: package + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + pattern: release-binaries-* + path: target/pkg/ + merge-multiple: true + - name: Create a SHA256SUMS file + run: | + cd target/pkg/ + rm -rf SHA256SUMS + sha256sum -b * > SHA256SUMS + - name: Upload artifacts + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: release-binaries + path: target/pkg/ + if-no-files-found: error + + checks: + uses: './.github/workflows/rust.yml' + + release: + needs: [gather, checks] + runs-on: ubuntu-latest + if: ${{ startsWith(github.ref, 'refs/heads/release/') }} + permissions: + # This part of the release pipeline needs to create a tag and a release + contents: write + steps: + - name: Checkout sources + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + + - name: Download artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: release-binaries + path: target/pkg/ + + - name: Install toolchain + uses: dtolnay/rust-toolchain@d8352f6b1d2e870bc5716e7a6d9b65c4cc244a1a + with: + toolchain: "stable" + components: "llvm-tools" + + - name: Check that the release commit is verified + run: | + commit_url="${{ github.api_url }}/repos/${{ github.repository }}/commits/${{ github.sha }}" + json_accept_header="Accept: application/vnd.github+json" + auth_bearer_header="Authorization: Bearer ${{ github.token }}" + test "$(curl -sf -H "$json_accept_header" -H "$auth_bearer_header" "$commit_url" | jq .commit.verification.verified)" == "true" + + - name: Read the version from the manifest file + run: echo "release_version=$(cargo read-manifest --manifest-path statime-linux/Cargo.toml | jq -r .version)" >> "$GITHUB_ENV" + + - name: Version in Cargo.toml must match the branch name + run: test "release/$release_version" == "${{ github.ref_name }}" + + - name: Ensure there is not already a released tag with a non-draft release + run: test "$(gh release view "v$release_version" --json isDraft --jq .isDraft 2>/dev/null || echo "true")" == "true" + + - name: Verify that the changelog top most entry concerns this release + run: | + release_notes="$(awk '/^## / && !found { found=1; print; next } /^## / && found { exit } found { print }' CHANGELOG.md)" + release_notes_header="$(echo "$release_notes" | head -1)" + echo "Found release notes for '$release_notes_header'" + release_notes_body="$(echo "$release_notes" | tail +2)" + release_notes_body="${release_notes_body#"${release_notes_body%%[![:space:]]*}"}" + release_notes_body="${release_notes_body%"${release_notes_body##*[![:space:]]}"}" + release_notes_version="$(echo "$release_notes_header" | cut -d' ' -f2 | sed 's/[][]//g')" + echo "Found version '$release_notes_version' in release notes" + test "$release_notes_version" == "${{ env.release_version }}" + { + echo "release_notes_body<> "$GITHUB_ENV" + + - name: Create a draft release + uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 # v2.0.5 + with: + draft: true + fail_on_unmatched_files: true + tag_name: "v${{ env.release_version }}" + target_commitish: "${{ github.sha }}" + name: "Version ${{ env.release_version }}" + files: target/pkg/* + body: "${{ env.release_notes_body }}" diff --git a/utils/build-release.sh b/utils/build-release.sh new file mode 100755 index 000000000..4925c03e8 --- /dev/null +++ b/utils/build-release.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +set -eo pipefail + +: "${RELEASE_TARGETS:=aarch64-unknown-linux-gnu,armv7-unknown-linux-gnueabihf,x86_64-unknown-linux-gnu,i686-unknown-linux-gnu}" +IFS=',' read -r -a targets <<< "$RELEASE_TARGETS" + +target_dir="target/pkg" + +rm -rf "$target_dir" +mkdir -p "$target_dir" + +package_version=$(cargo read-manifest --manifest-path statime-linux/Cargo.toml | jq -r .version) +toolchain=$(rustup show active-toolchain | cut -d' ' -f1) +host_target=$(echo "$toolchain" | cut -d'-' -f2-) +sysroot=$(rustc --print sysroot) +llvm_tools_path="$sysroot/lib/rustlib/$host_target/bin" + +echo "--- Running on toolchain '${toolchain}', make sure the llvm-tools component is installed" +echo "--- Host target is '$host_target'" + +for target in "${targets[@]}"; do + dbg_sym_tar="statime_dbg_$package_version-$target.tar.gz" + + echo "--- Calling cross for building statime package for target '$target'" + cross build --target "$target" --package statime-linux --release --features "${RELEASE_FEATURES:-}" + + echo "--- Creating separate debug symbol files for target '$target'" + ( + cd "target/$target/release" + find . -maxdepth 1 -type f -executable -print0 | while IFS= read -r -d '' file; do + echo "--- Writing debug symbols from '$file' to '$file.dbg'" + "$llvm_tools_path/llvm-strip" --only-keep-debug -o "$file.dbg" "$file" + chmod -x "$file.dbg" + echo "--- Removing all symbols from binary '$file'" + "$llvm_tools_path/llvm-strip" -s "$file" + done + ); + + echo "--- Create tar for debug symbols" + ( + cd "target/$target/release" + rm -f "$dbg_sym_tar" + find . -maxdepth 1 -type f -name '*.dbg' -exec tar uvf "$dbg_sym_tar" {} + + ); + + echo "--- Creating deb package" + cargo deb --no-build --no-strip --target "$target" --compress-type xz --package statime-linux + + echo "--- Creating rpm package" + cargo generate-rpm --payload-compress xz --package statime-linux --target "$target" --target-dir target + + echo "--- Copying output files to target" + cp "target/$target/release/$dbg_sym_tar" "$target_dir/" + find "target/$target/debian" -maxdepth 1 -type f -name '*.deb' -exec cp "{}" "$target_dir/" \; + find "target/$target/generate-rpm" -maxdepth 1 -type f -name '*.rpm' -exec cp "{}" "$target_dir/" \; +done + +echo "--- Generating SHA256SUMS file" +( + cd $target_dir + sha256sum -b * > SHA256SUMS +) + +echo "--- Done, output is in $target_dir"