# BugSETI Release Workflow # Builds for all platforms and creates GitHub releases name: "BugSETI Release" on: push: tags: - 'bugseti-v*.*.*' # Stable: bugseti-v1.0.0 - 'bugseti-v*.*.*-beta.*' # Beta: bugseti-v1.0.0-beta.1 - 'bugseti-nightly-*' # Nightly: bugseti-nightly-20260205 permissions: contents: write env: APP_NAME: bugseti WAILS_VERSION: "3" jobs: # Determine release channel from tag prepare: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} channel: ${{ steps.version.outputs.channel }} prerelease: ${{ steps.version.outputs.prerelease }} steps: - name: Determine version and channel id: version env: TAG: ${{ github.ref_name }} run: | if [[ "$TAG" == bugseti-nightly-* ]]; then VERSION="${TAG#bugseti-}" CHANNEL="nightly" PRERELEASE="true" elif [[ "$TAG" == *-beta.* ]]; then VERSION="${TAG#bugseti-v}" CHANNEL="beta" PRERELEASE="true" else VERSION="${TAG#bugseti-v}" CHANNEL="stable" PRERELEASE="false" fi echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "channel=${CHANNEL}" >> "$GITHUB_OUTPUT" echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT" echo "Tag: $TAG" echo "Version: $VERSION" echo "Channel: $CHANNEL" echo "Prerelease: $PRERELEASE" build: needs: prepare strategy: fail-fast: false matrix: include: # macOS ARM64 (Apple Silicon) - os: macos-latest goos: darwin goarch: arm64 ext: "" archive: tar.gz # macOS AMD64 (Intel) - os: macos-13 goos: darwin goarch: amd64 ext: "" archive: tar.gz # Linux AMD64 - os: ubuntu-latest goos: linux goarch: amd64 ext: "" archive: tar.gz # Linux ARM64 - os: ubuntu-24.04-arm goos: linux goarch: arm64 ext: "" archive: tar.gz # Windows AMD64 - os: windows-latest goos: windows goarch: amd64 ext: ".exe" archive: zip runs-on: ${{ matrix.os }} env: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} VERSION: ${{ needs.prepare.outputs.version }} CHANNEL: ${{ needs.prepare.outputs.channel }} defaults: run: working-directory: cmd/bugseti steps: - uses: actions/checkout@v6 - name: Setup Go uses: host-uk/build/actions/setup/go@v4.0.0 with: go-version: "1.25" - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: Install Wails CLI run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest - name: Install frontend dependencies working-directory: cmd/bugseti/frontend run: npm ci - name: Generate bindings run: wails3 generate bindings -f '-tags production' -clean=false -ts -i - name: Build frontend working-directory: cmd/bugseti/frontend run: npm run build - name: Install Linux dependencies if: matrix.goos == 'linux' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev - name: Build BugSETI shell: bash env: EXT: ${{ matrix.ext }} ARCHIVE: ${{ matrix.archive }} COMMIT_SHA: ${{ github.sha }} run: | BINARY="${APP_NAME}${EXT}" ARCHIVE_PREFIX="${APP_NAME}-${GOOS}-${GOARCH}" BUILD_FLAGS="-tags production -trimpath -buildvcs=false" # Version injection via ldflags LDFLAGS="-s -w" LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Version=${VERSION}" LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Channel=${CHANNEL}" LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Commit=${COMMIT_SHA}" LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" if [ "$GOOS" = "windows" ]; then export CGO_ENABLED=0 LDFLAGS="${LDFLAGS} -H windowsgui" # Generate Windows syso resource cd build wails3 generate syso -arch ${GOARCH} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_${GOARCH}.syso 2>/dev/null || true cd .. elif [ "$GOOS" = "darwin" ]; then export CGO_ENABLED=1 export CGO_CFLAGS="-mmacosx-version-min=10.15" export CGO_LDFLAGS="-mmacosx-version-min=10.15" export MACOSX_DEPLOYMENT_TARGET="10.15" else export CGO_ENABLED=1 fi mkdir -p bin go build ${BUILD_FLAGS} -ldflags="${LDFLAGS}" -o "./bin/${BINARY}" # Clean up syso files rm -f *.syso # Package based on platform if [ "$GOOS" = "darwin" ]; then # Create .app bundle mkdir -p "./bin/BugSETI.app/Contents/"{MacOS,Resources} cp build/darwin/icons.icns "./bin/BugSETI.app/Contents/Resources/" 2>/dev/null || true cp "./bin/${BINARY}" "./bin/BugSETI.app/Contents/MacOS/" cp build/darwin/Info.plist "./bin/BugSETI.app/Contents/" codesign --force --deep --sign - "./bin/BugSETI.app" 2>/dev/null || true tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "BugSETI.app" elif [ "$GOOS" = "windows" ]; then cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd .. else tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}" fi # Rename raw binary for individual download mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}" # Generate checksum cd ./bin sha256sum "${ARCHIVE_PREFIX}.${ARCHIVE}" > "${ARCHIVE_PREFIX}.${ARCHIVE}.sha256" sha256sum "${ARCHIVE_PREFIX}${EXT}" > "${ARCHIVE_PREFIX}${EXT}.sha256" - name: Upload artifact uses: actions/upload-artifact@v4 with: name: bugseti-${{ matrix.goos }}-${{ matrix.goarch }} path: | cmd/bugseti/bin/bugseti-* retention-days: 7 release: needs: [prepare, build] runs-on: ubuntu-latest env: TAG_NAME: ${{ github.ref_name }} VERSION: ${{ needs.prepare.outputs.version }} CHANNEL: ${{ needs.prepare.outputs.channel }} PRERELEASE: ${{ needs.prepare.outputs.prerelease }} REPO: ${{ github.repository }} steps: - uses: actions/checkout@v6 - name: Download all artifacts uses: actions/download-artifact@v7 with: path: dist merge-multiple: true - name: List release files run: | echo "=== Release files ===" ls -la dist/ echo "=== Checksums ===" cat dist/*.sha256 - name: Create release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | # Determine release title if [ "$CHANNEL" = "nightly" ]; then TITLE="BugSETI Nightly (${VERSION})" elif [ "$CHANNEL" = "beta" ]; then TITLE="BugSETI v${VERSION} (Beta)" else TITLE="BugSETI v${VERSION}" fi # Create release notes cat > release-notes.md << EOF ## BugSETI ${VERSION} **Channel:** ${CHANNEL} ### Downloads | Platform | Architecture | Binary | Archive | |----------|-------------|--------|---------| | macOS | ARM64 (Apple Silicon) | [bugseti-darwin-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64.tar.gz) | | macOS | AMD64 (Intel) | [bugseti-darwin-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64.tar.gz) | | Linux | AMD64 | [bugseti-linux-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64.tar.gz) | | Linux | ARM64 | [bugseti-linux-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64.tar.gz) | | Windows | AMD64 | [bugseti-windows-amd64.exe](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.exe) | [zip](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.zip) | ### Checksums (SHA256) \`\`\` $(cat dist/*.sha256) \`\`\` --- *BugSETI - Distributed Bug Fixing, like SETI@home but for code* EOF # Build release command RELEASE_ARGS=( --title "$TITLE" --notes-file release-notes.md ) if [ "$PRERELEASE" = "true" ]; then RELEASE_ARGS+=(--prerelease) fi # Create the release gh release create "$TAG_NAME" \ "${RELEASE_ARGS[@]}" \ dist/* # Scheduled nightly builds nightly: if: github.event_name == 'schedule' runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Create nightly tag env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | DATE=$(date -u +%Y%m%d) TAG="bugseti-nightly-${DATE}" # Delete existing nightly tag for today if it exists gh release delete "$TAG" --yes 2>/dev/null || true git push origin ":refs/tags/$TAG" 2>/dev/null || true # Create new tag git tag "$TAG" git push origin "$TAG"