Fix setup-msys2 pin to valid commit SHA (v2.30.0) #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| include: | |
| - goarch: amd64 | |
| zig_target: x86_64-linux-musl | |
| - goarch: arm64 | |
| zig_target: aarch64-linux-musl | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Install zig | |
| run: | | |
| ZIG_VERSION="0.14.0" | |
| ZIG_SHA256="473ec26806133cf4d1918caf1a410f8403a13d979726a9045b421b685031a982" | |
| ZIG_TARBALL="zig-linux-x86_64-${ZIG_VERSION}.tar.xz" | |
| curl -fsSL "https://ziglang.org/download/${ZIG_VERSION}/${ZIG_TARBALL}" -o "$ZIG_TARBALL" | |
| echo "${ZIG_SHA256} ${ZIG_TARBALL}" | sha256sum -c - || { echo "FATAL: zig checksum mismatch"; exit 1; } | |
| tar -xJf "$ZIG_TARBALL" | |
| echo "$PWD/zig-linux-x86_64-${ZIG_VERSION}" >> $GITHUB_PATH | |
| - name: Build | |
| env: | |
| GOOS: linux | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 1 | |
| CC: zigcc | |
| CXX: zigcxx | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| # Create zig cc/cxx wrappers that target musl for fully static binaries | |
| mkdir -p /tmp/zigbin | |
| cat > /tmp/zigbin/zigcc << 'ZIGEOF' | |
| #!/bin/bash | |
| exec zig cc -target $ZIG_TARGET "$@" | |
| ZIGEOF | |
| cat > /tmp/zigbin/zigcxx << 'ZIGEOF' | |
| #!/bin/bash | |
| exec zig c++ -target $ZIG_TARGET "$@" | |
| ZIGEOF | |
| chmod +x /tmp/zigbin/zigcc /tmp/zigbin/zigcxx | |
| export PATH="/tmp/zigbin:$PATH" | |
| export ZIG_TARGET="${{ matrix.zig_target }}" | |
| export CC=zigcc | |
| export CXX=zigcxx | |
| mkdir -p dist | |
| LDFLAGS="-s -w -X github.com/wesm/msgvault/cmd/msgvault/cmd.Version=v${VERSION} -linkmode external -extldflags '-static -lstdc++ -lm'" | |
| go build -tags fts5 -trimpath -ldflags="$LDFLAGS" -o dist/msgvault ./cmd/msgvault | |
| # Verify the binary is statically linked (fail build if not) | |
| echo "--- Binary type ---" | |
| file dist/msgvault | |
| file dist/msgvault | grep -qE "statically linked|static-pie linked" || { echo "FATAL: binary is not statically linked"; exit 1; } | |
| echo "--- Dynamic dependencies ---" | |
| # readelf is the most reliable check: no NEEDED entries means no shared libs | |
| if command -v readelf &>/dev/null; then | |
| NEEDED=$(readelf -d dist/msgvault 2>/dev/null | grep NEEDED || true) | |
| echo "$NEEDED" | |
| if [ -n "$NEEDED" ]; then | |
| echo "FATAL: binary has dynamic library dependencies:" | |
| echo "$NEEDED" | |
| exit 1 | |
| fi | |
| fi | |
| LDD_OUT=$(ldd dist/msgvault 2>&1 || true) | |
| echo "$LDD_OUT" | |
| # Smoke test on native arch (amd64 only — arm64 is cross-compiled) | |
| if [ "${{ matrix.goarch }}" = "amd64" ]; then | |
| echo "--- Smoke test ---" | |
| SMOKE_OUT=$(dist/msgvault version 2>&1) | |
| echo "$SMOKE_OUT" | |
| echo "$SMOKE_OUT" | grep -q "v${VERSION}" || { echo "FATAL: version output doesn't match tag"; exit 1; } | |
| fi | |
| cd dist | |
| ARCHIVE="msgvault_${VERSION}_linux_${{ matrix.goarch }}.tar.gz" | |
| tar czf "$ARCHIVE" msgvault | |
| rm msgvault | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: msgvault-linux-${{ matrix.goarch }} | |
| path: dist/*.tar.gz | |
| build-darwin: | |
| strategy: | |
| matrix: | |
| include: | |
| - goarch: amd64 | |
| runner: macos-13 | |
| - goarch: arm64 | |
| runner: macos-14 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Build | |
| env: | |
| GOOS: darwin | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 1 | |
| run: | | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| mkdir -p dist | |
| LDFLAGS="-s -w -X github.com/wesm/msgvault/cmd/msgvault/cmd.Version=v${VERSION}" | |
| go build -tags fts5 -trimpath -ldflags="$LDFLAGS" -o dist/msgvault ./cmd/msgvault | |
| # Verify no libstdc++ dependency (macOS should only link libc++ and system libs) | |
| echo "--- Dynamic libraries ---" | |
| otool -L dist/msgvault | |
| if otool -L dist/msgvault | grep -q 'libstdc++'; then | |
| echo "FATAL: binary links libstdc++ — this will cause compatibility issues" | |
| exit 1 | |
| fi | |
| # Smoke test — verify binary runs and reports correct version | |
| echo "--- Smoke test ---" | |
| SMOKE_OUT=$(dist/msgvault version 2>&1) | |
| echo "$SMOKE_OUT" | |
| echo "$SMOKE_OUT" | grep -q "v${VERSION}" || { echo "FATAL: version output doesn't match tag"; exit 1; } | |
| cd dist | |
| ARCHIVE="msgvault_${VERSION}_darwin_${{ matrix.goarch }}.tar.gz" | |
| tar czf "$ARCHIVE" msgvault | |
| rm msgvault | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: msgvault-darwin-${{ matrix.goarch }} | |
| path: dist/*.tar.gz | |
| build-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Set up MinGW | |
| id: msys2 | |
| uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 | |
| with: | |
| msystem: MINGW64 | |
| install: mingw-w64-x86_64-gcc | |
| - name: Build | |
| shell: pwsh | |
| env: | |
| GOOS: windows | |
| GOARCH: amd64 | |
| CGO_ENABLED: '1' | |
| CC: ${{ steps.msys2.outputs.msys2-location }}\mingw64\bin\gcc.exe | |
| run: | | |
| $VERSION = "${{ github.ref_name }}".TrimStart("v") | |
| New-Item -ItemType Directory -Force -Path dist | Out-Null | |
| $LDFLAGS = "-s -w -X github.com/wesm/msgvault/cmd/msgvault/cmd.Version=v${VERSION}" | |
| go build -tags fts5 -trimpath -ldflags="$LDFLAGS" -o dist/msgvault.exe ./cmd/msgvault | |
| if ($LASTEXITCODE -ne 0) { throw "Build failed" } | |
| # Smoke test — check exit code explicitly, then verify version string | |
| Write-Host "--- Smoke test ---" | |
| & dist/msgvault.exe version 2>&1 | Tee-Object -Variable SMOKE_OUT | Out-Null | |
| if ($LASTEXITCODE -ne 0) { throw "FATAL: msgvault.exe version exited with code $LASTEXITCODE" } | |
| $SMOKE_OUT = $SMOKE_OUT | Out-String | |
| Write-Host $SMOKE_OUT | |
| if ($SMOKE_OUT -notmatch "v${VERSION}") { throw "FATAL: version output doesn't match tag" } | |
| # Package as zip | |
| $ARCHIVE = "msgvault_${VERSION}_windows_amd64.zip" | |
| Compress-Archive -Path dist/msgvault.exe -DestinationPath "dist/$ARCHIVE" | |
| Remove-Item dist/msgvault.exe | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: msgvault-windows-amd64 | |
| path: dist/*.zip | |
| release: | |
| needs: [build-linux, build-darwin, build-windows] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Validate artifacts | |
| run: | | |
| echo "--- Validating all archives ---" | |
| for archive in artifacts/*.tar.gz; do | |
| echo "Checking $archive..." | |
| tmpdir=$(mktemp -d) | |
| tar -xzf "$archive" -C "$tmpdir" | |
| test -f "$tmpdir/msgvault" || { echo "FATAL: msgvault binary missing from $archive"; exit 1; } | |
| test -x "$tmpdir/msgvault" || { echo "FATAL: msgvault binary not executable in $archive"; exit 1; } | |
| # Smoke test linux amd64 artifact (runs natively on ubuntu runner) | |
| if echo "$archive" | grep -q "linux_amd64"; then | |
| "$tmpdir/msgvault" version > /tmp/smoke_out.txt 2>&1 | |
| cat /tmp/smoke_out.txt | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| grep -q "v${VERSION}" /tmp/smoke_out.txt || { echo "FATAL: extracted linux_amd64 binary version mismatch"; exit 1; } | |
| echo " linux_amd64 smoke: OK" | |
| fi | |
| file "$tmpdir/msgvault" | |
| rm -rf "$tmpdir" | |
| echo " OK" | |
| done | |
| for archive in artifacts/*.zip; do | |
| [ -e "$archive" ] || continue | |
| echo "Checking $archive..." | |
| tmpdir=$(mktemp -d) | |
| unzip -q "$archive" -d "$tmpdir" | |
| test -f "$tmpdir/msgvault.exe" || { echo "FATAL: msgvault.exe missing from $archive"; exit 1; } | |
| file "$tmpdir/msgvault.exe" | |
| rm -rf "$tmpdir" | |
| echo " OK" | |
| done | |
| - name: Generate checksums | |
| run: | | |
| cd artifacts | |
| sha256sum *.tar.gz *.zip > SHA256SUMS | |
| cat SHA256SUMS | |
| - name: Get tag message | |
| id: tag_message | |
| run: | | |
| TAG_NAME="${GITHUB_REF#refs/tags/}" | |
| TAG_TYPE=$(git cat-file -t "$TAG_NAME") | |
| if [ "$TAG_TYPE" != "tag" ]; then | |
| echo "Warning: $TAG_NAME is a lightweight tag, using auto-generated notes" | |
| echo "has_body=false" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| TAG_MSG=$(git tag -l --format='%(contents:body)' "$TAG_NAME") | |
| if [ -n "$TAG_MSG" ]; then | |
| DELIM="TAGMSG_$(date +%s%N)" | |
| echo "body<<$DELIM" >> $GITHUB_OUTPUT | |
| echo "$TAG_MSG" >> $GITHUB_OUTPUT | |
| echo "$DELIM" >> $GITHUB_OUTPUT | |
| echo "has_body=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_body=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Create Release | |
| uses: softprops/action-gh-release@26994186c0ac3ef5cae75ac16aa32e8153525f77 # v1 | |
| with: | |
| files: | | |
| artifacts/*.tar.gz | |
| artifacts/*.zip | |
| artifacts/SHA256SUMS | |
| body: ${{ steps.tag_message.outputs.has_body == 'true' && steps.tag_message.outputs.body || '' }} | |
| generate_release_notes: ${{ steps.tag_message.outputs.has_body != 'true' }} |