diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 202394a..6bbfe83 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,8 +93,8 @@ jobs: exit 1 fi - build-windows-x64: - name: Build windows-x64 + build-release-assets: + name: Build release assets runs-on: ubuntu-latest needs: prepare-release steps: @@ -114,8 +114,9 @@ jobs: release_tag="$(git describe --tags --abbrev=0)" fi echo "RELEASE_TAG=${release_tag}" >> "${GITHUB_ENV}" + echo "VERSION=${release_tag#v}" >> "${GITHUB_ENV}" - - name: Install cross compile dependencies + - name: Configure Cargo mirror shell: bash run: | set -euo pipefail @@ -133,178 +134,85 @@ jobs: ar = "x86_64-w64-mingw32-ar" EOF + - name: Install Windows cross compile dependencies + shell: bash + run: | + set -euo pipefail + if command -v sudo >/dev/null 2>&1; then + sudo sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g; s|http://security.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g' /etc/apt/sources.list sudo apt-get update - sudo apt-get install -y --no-install-recommends mingw-w64 gcc-mingw-w64-x86-64 + sudo apt-get install -y --no-install-recommends binutils-mingw-w64-x86-64 gcc-mingw-w64-x86-64-posix mingw-w64-x86-64-dev else + sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g; s|http://security.ubuntu.com/ubuntu|https://mirrors.tuna.tsinghua.edu.cn/ubuntu|g' /etc/apt/sources.list apt-get update - apt-get install -y --no-install-recommends mingw-w64 gcc-mingw-w64-x86-64 + apt-get install -y --no-install-recommends binutils-mingw-w64-x86-64 gcc-mingw-w64-x86-64-posix mingw-w64-x86-64-dev fi rustup target add x86_64-pc-windows-gnu - - name: Build release binary + - name: Build Windows x64 shell: bash run: | set -euo pipefail - tag="${RELEASE_TAG}" - version="${tag#v}" mkdir -p dist cargo build --release --target x86_64-pc-windows-gnu - cp target/x86_64-pc-windows-gnu/release/cdxs.exe "dist/cdxs-${version}-windows-x64.exe" + cp target/x86_64-pc-windows-gnu/release/cdxs.exe "dist/cdxs-${VERSION}-windows-x64.exe" - - name: Upload release asset + - name: Build Linux assets + shell: bash + run: | + set -euo pipefail + + build_linux() { + local target_name="$1" + local rust_target="$2" + local platform="$3" + local image_tag="cdxs-build:${target_name}-${GITHUB_RUN_ID:-manual}" + local container_name="cdxs-build-${target_name}-${GITHUB_RUN_ID:-manual}" + + docker buildx build \ + --platform "${platform}" \ + --target builder \ + --build-arg "RUST_TARGET=${rust_target}" \ + --build-arg "RUST_IMAGE=${RUST_IMAGE}" \ + --build-arg "CARGO_REGISTRY=${CARGO_REGISTRY}" \ + --load \ + -t "${image_tag}" \ + -f scripts/docker/Dockerfile.release \ + . + + local container_id + container_id="$(docker create --name "${container_name}" "${image_tag}")" + docker cp "${container_id}:/out/cdxs" "dist/cdxs-${VERSION}-${target_name}" + docker rm -f "${container_name}" >/dev/null + } + + build_linux linux-x64 x86_64-unknown-linux-gnu linux/amd64 + build_linux linux-arm64 aarch64-unknown-linux-gnu linux/arm64 + + - name: Upload release assets shell: bash env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail - tag="${RELEASE_TAG}" api_base="${GITEA_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" - curl -sS -H "Authorization: token ${GITEA_TOKEN}" "${api_base}/releases/tags/${tag}" > release.json + curl -sS -H "Authorization: token ${GITEA_TOKEN}" "${api_base}/releases/tags/${RELEASE_TAG}" > release.json release_id="$(python3 -c 'import json; print(json.load(open("release.json"))["id"])')" - file="$(find dist -maxdepth 1 -type f | head -n 1)" - name="$(basename "${file}")" - curl -fsS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -F "attachment=@${file}" \ - "${api_base}/releases/${release_id}/assets?name=${name}" + curl -sS -H "Authorization: token ${GITEA_TOKEN}" "${api_base}/releases/${release_id}/assets" > assets.json - build-linux-x64: - name: Build linux-x64 - runs-on: ubuntu-latest - needs: prepare-release - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Resolve release tag - shell: bash - run: | - set -euo pipefail - - if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then - release_tag="${GITHUB_REF_NAME}" - else - release_tag="$(git describe --tags --abbrev=0)" - fi - echo "RELEASE_TAG=${release_tag}" >> "${GITHUB_ENV}" - - - name: Build release binary - shell: bash - run: | - set -euo pipefail - - tag="${RELEASE_TAG}" - version="${tag#v}" - target_name="linux-x64" - rust_target="x86_64-unknown-linux-gnu" - platform="linux/amd64" - image_tag="cdxs-build:${target_name}-${GITHUB_RUN_ID:-manual}" - container_name="cdxs-build-${target_name}-${GITHUB_RUN_ID:-manual}" - - mkdir -p dist - docker buildx build \ - --platform "${platform}" \ - --target builder \ - --build-arg "RUST_TARGET=${rust_target}" \ - --build-arg "RUST_IMAGE=${RUST_IMAGE}" \ - --build-arg "CARGO_REGISTRY=${CARGO_REGISTRY}" \ - --load \ - -t "${image_tag}" \ - -f scripts/docker/Dockerfile.release \ - . - - container_id="$(docker create --name "${container_name}" "${image_tag}")" - trap 'docker rm -f "${container_name}" >/dev/null 2>&1 || true' EXIT - docker cp "${container_id}:/out/cdxs" "dist/cdxs-${version}-${target_name}" - - - name: Upload release asset - shell: bash - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: | - set -euo pipefail - - tag="${RELEASE_TAG}" - api_base="${GITEA_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" - curl -sS -H "Authorization: token ${GITEA_TOKEN}" "${api_base}/releases/tags/${tag}" > release.json - release_id="$(python3 -c 'import json; print(json.load(open("release.json"))["id"])')" - file="$(find dist -maxdepth 1 -type f | head -n 1)" - name="$(basename "${file}")" - curl -fsS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -F "attachment=@${file}" \ - "${api_base}/releases/${release_id}/assets?name=${name}" - - build-linux-arm64: - name: Build linux-arm64 - runs-on: ubuntu-latest - needs: prepare-release - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Resolve release tag - shell: bash - run: | - set -euo pipefail - - if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then - release_tag="${GITHUB_REF_NAME}" - else - release_tag="$(git describe --tags --abbrev=0)" - fi - echo "RELEASE_TAG=${release_tag}" >> "${GITHUB_ENV}" - - - name: Build release binary - shell: bash - run: | - set -euo pipefail - - tag="${RELEASE_TAG}" - version="${tag#v}" - target_name="linux-arm64" - rust_target="aarch64-unknown-linux-gnu" - platform="linux/arm64" - image_tag="cdxs-build:${target_name}-${GITHUB_RUN_ID:-manual}" - container_name="cdxs-build-${target_name}-${GITHUB_RUN_ID:-manual}" - - mkdir -p dist - docker buildx build \ - --platform "${platform}" \ - --target builder \ - --build-arg "RUST_TARGET=${rust_target}" \ - --build-arg "RUST_IMAGE=${RUST_IMAGE}" \ - --build-arg "CARGO_REGISTRY=${CARGO_REGISTRY}" \ - --load \ - -t "${image_tag}" \ - -f scripts/docker/Dockerfile.release \ - . - - container_id="$(docker create --name "${container_name}" "${image_tag}")" - trap 'docker rm -f "${container_name}" >/dev/null 2>&1 || true' EXIT - docker cp "${container_id}:/out/cdxs" "dist/cdxs-${version}-${target_name}" - - - name: Upload release asset - shell: bash - env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - run: | - set -euo pipefail - - tag="${RELEASE_TAG}" - api_base="${GITEA_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" - curl -sS -H "Authorization: token ${GITEA_TOKEN}" "${api_base}/releases/tags/${tag}" > release.json - release_id="$(python3 -c 'import json; print(json.load(open("release.json"))["id"])')" - file="$(find dist -maxdepth 1 -type f | head -n 1)" - name="$(basename "${file}")" - curl -fsS -X POST \ - -H "Authorization: token ${GITEA_TOKEN}" \ - -F "attachment=@${file}" \ - "${api_base}/releases/${release_id}/assets?name=${name}" + for file in dist/*; do + name="$(basename "${file}")" + existing_asset_id="$(python3 -c 'import json, sys; target = sys.argv[1]; print(next((str(asset["id"]) for asset in json.load(open("assets.json")) if asset.get("name") == target), ""))' "${name}")" + if [[ -n "${existing_asset_id}" ]]; then + curl -fsS -X DELETE \ + -H "Authorization: token ${GITEA_TOKEN}" \ + "${api_base}/releases/${release_id}/assets/${existing_asset_id}" + fi + curl -fsS -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -F "attachment=@${file}" \ + "${api_base}/releases/${release_id}/assets?name=${name}" + done