Merge pull request #402 from wendylabsinc/jo/wendy-lite-gcp #1485
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: Build products and release | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| publish: | |
| description: "Publish artifacts and create a stable release" | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: build-${{ github.ref }} | |
| cancel-in-progress: true | |
| # Add permissions needed for creating releases | |
| permissions: | |
| contents: write | |
| jobs: | |
| determine-version: | |
| name: Determine Version | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.set-version.outputs.version }} | |
| is_release: ${{ steps.set-version.outputs.is_release }} | |
| is_prerelease: ${{ steps.set-version.outputs.is_prerelease }} | |
| tag_name: ${{ steps.set-version.outputs.tag_name }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set version | |
| id: set-version | |
| run: | | |
| TIMESTAMP=$(date +'%Y.%m.%d-%H%M%S') | |
| if [ "$GITHUB_REF" == "refs/heads/main" ]; then | |
| VERSION="${TIMESTAMP}" | |
| else | |
| VERSION="${TIMESTAMP}-dev" | |
| fi | |
| # Stable release when manually triggered with publish=true | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ inputs.publish }}" == "true" ]]; then | |
| IS_RELEASE="true" | |
| IS_PRERELEASE="false" | |
| else | |
| IS_RELEASE="false" | |
| IS_PRERELEASE="true" | |
| fi | |
| TAG_NAME="$VERSION" | |
| echo "version=$VERSION, release=$IS_RELEASE, prerelease=$IS_PRERELEASE" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "is_release=$IS_RELEASE" >> $GITHUB_OUTPUT | |
| echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| build: | |
| name: ${{ matrix.artifact-name }} | |
| runs-on: ubuntu-latest | |
| needs: [determine-version] | |
| strategy: | |
| matrix: | |
| include: | |
| - artifact-name: wendy-agent-linux-amd64 | |
| goos: linux | |
| goarch: amd64 | |
| product: wendy-agent | |
| cmd: wendy-agent | |
| - artifact-name: wendy-agent-linux-arm64 | |
| goos: linux | |
| goarch: arm64 | |
| product: wendy-agent | |
| cmd: wendy-agent | |
| - artifact-name: wendy-cli-linux-amd64 | |
| goos: linux | |
| goarch: amd64 | |
| product: wendy | |
| cmd: wendy | |
| - artifact-name: wendy-cli-linux-arm64 | |
| goos: linux | |
| goarch: arm64 | |
| product: wendy | |
| cmd: wendy | |
| - artifact-name: wendy-cli-windows-amd64 | |
| goos: windows | |
| goarch: amd64 | |
| product: wendy.exe | |
| cmd: wendy | |
| - artifact-name: wendy-cli-windows-arm64 | |
| goos: windows | |
| goarch: arm64 | |
| product: wendy.exe | |
| cmd: wendy | |
| defaults: | |
| run: | |
| working-directory: go | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go/go.mod | |
| cache-dependency-path: go/go.sum | |
| - name: Build | |
| env: | |
| CGO_ENABLED: "0" | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| LDFLAGS="-s -w -X github.com/wendylabsinc/wendy/internal/shared/version.Version=${VERSION}" | |
| mkdir -p ../${{ matrix.artifact-name }} | |
| go build -ldflags "${LDFLAGS}" -o ../${{ matrix.artifact-name }}/${{ matrix.product }} ./cmd/${{ matrix.cmd }} | |
| - name: Create archive | |
| working-directory: . | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| if [[ "${{ matrix.goos }}" == "windows" ]]; then | |
| ARCHIVE="${{ matrix.artifact-name }}-${VERSION}.zip" | |
| apt-get update && apt-get install -y zip | |
| zip -r "$ARCHIVE" ${{ matrix.artifact-name }}/ | |
| else | |
| ARCHIVE="${{ matrix.artifact-name }}-${VERSION}.tar.gz" | |
| tar -czvf "$ARCHIVE" ${{ matrix.artifact-name }}/ | |
| fi | |
| echo "archive=$ARCHIVE" >> $GITHUB_ENV | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.archive }} | |
| path: ${{ env.archive }} | |
| retention-days: 14 | |
| if-no-files-found: error | |
| build-go-macos: | |
| name: ${{ matrix.artifact-name }} | |
| runs-on: macos-15 | |
| needs: [determine-version] | |
| strategy: | |
| matrix: | |
| include: | |
| - artifact-name: wendy-cli-darwin-arm64 | |
| goarch: arm64 | |
| - artifact-name: wendy-cli-darwin-amd64 | |
| goarch: amd64 | |
| defaults: | |
| run: | |
| working-directory: go | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go/go.mod | |
| cache-dependency-path: go/go.sum | |
| - name: Build | |
| env: | |
| CGO_ENABLED: "1" | |
| GOOS: darwin | |
| GOARCH: ${{ matrix.goarch }} | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| LDFLAGS="-s -w -X github.com/wendylabsinc/wendy/internal/shared/version.Version=${VERSION}" | |
| mkdir -p ../${{ matrix.artifact-name }} | |
| go build -ldflags "${LDFLAGS}" -o ../${{ matrix.artifact-name }}/wendy ./cmd/wendy | |
| - name: Create archive | |
| working-directory: . | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| ARCHIVE="${{ matrix.artifact-name }}-${VERSION}.tar.gz" | |
| tar -czvf "$ARCHIVE" ${{ matrix.artifact-name }}/ | |
| echo "archive=$ARCHIVE" >> $GITHUB_ENV | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ env.archive }} | |
| path: ${{ env.archive }} | |
| retention-days: 14 | |
| if-no-files-found: error | |
| package-linux: | |
| name: Package Linux (${{ matrix.arch }}) | |
| runs-on: ubuntu-latest | |
| needs: [determine-version, build] | |
| if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish == true) | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| goarch: amd64 | |
| rpm-arch: x86_64 | |
| - arch: arm64 | |
| goarch: arm64 | |
| rpm-arch: aarch64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install FPM dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y ruby ruby-dev build-essential rpm | |
| sudo gem install fpm | |
| - name: Download CLI artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wendy-cli-linux-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.tar.gz | |
| - name: Download Agent artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wendy-agent-linux-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.tar.gz | |
| - name: Extract artifacts | |
| run: | | |
| ls -la | |
| tar -xzf wendy-cli-linux-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.tar.gz | |
| tar -xzf wendy-agent-linux-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.tar.gz | |
| ls -la | |
| - name: Prepare package roots | |
| run: | | |
| set -euo pipefail | |
| mkdir -p pkgroot/wendy/usr/bin | |
| mkdir -p pkgroot/wendy-agent/usr/bin | |
| mkdir -p pkgroot/wendy-agent/usr/lib/systemd/system | |
| mkdir -p pkgroot/wendy-agent/usr/lib/wendy-agent | |
| mkdir -p pkgroot/wendy-agent/etc/default | |
| mkdir -p pkgroot/wendy-agent/etc/wendy-agent | |
| mkdir -p pkgroot/wendy-agent/etc/avahi/services | |
| mkdir -p pkgroot/wendy-agent/var/lib/wendy-agent/storage | |
| install -m755 ./wendy-cli-linux-${{ matrix.goarch }}/wendy \ | |
| pkgroot/wendy/usr/bin/wendy | |
| install -m755 ./wendy-agent-linux-${{ matrix.goarch }}/wendy-agent \ | |
| pkgroot/wendy-agent/usr/bin/wendy-agent | |
| install -m644 packaging/linux/systemd/wendy-agent.service \ | |
| pkgroot/wendy-agent/usr/lib/systemd/system/wendy-agent.service | |
| install -m644 packaging/linux/default/wendy-agent \ | |
| pkgroot/wendy-agent/etc/default/wendy-agent | |
| install -m644 packaging/linux/avahi/wendy-agent.service \ | |
| pkgroot/wendy-agent/etc/avahi/services/wendy-agent.service | |
| install -m755 packaging/linux/fpm/wendy-agent-setup-mdns.sh \ | |
| pkgroot/wendy-agent/usr/lib/wendy-agent/setup-mdns.sh | |
| # Placeholder config created at install time by package manager. | |
| printf "{}\n" > pkgroot/wendy-agent/etc/wendy-agent/config.json | |
| chmod 600 pkgroot/wendy-agent/etc/wendy-agent/config.json | |
| - name: Build .deb packages | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| # Build wendy .deb | |
| fpm -s dir -t deb \ | |
| -n wendy \ | |
| -v "$VERSION" \ | |
| --architecture ${{ matrix.arch }} \ | |
| --description "Wendy CLI - Remote device debugging and deployment" \ | |
| --url "https://wendy.sh" \ | |
| --maintainer "Wendy Labs Inc. <support@wendy.sh>" \ | |
| --license "Proprietary" \ | |
| --vendor "Wendy Labs Inc." \ | |
| --category "devel" \ | |
| --depends "usbutils" \ | |
| --depends "ca-certificates" \ | |
| -C pkgroot/wendy \ | |
| . | |
| # Build wendy-agent .deb | |
| fpm -s dir -t deb \ | |
| -n wendy-agent \ | |
| -v "$VERSION" \ | |
| --architecture ${{ matrix.arch }} \ | |
| --description "Wendy Agent - Runs on target devices for remote debugging" \ | |
| --url "https://wendy.sh" \ | |
| --maintainer "Wendy Labs Inc. <support@wendy.sh>" \ | |
| --license "Proprietary" \ | |
| --vendor "Wendy Labs Inc." \ | |
| --category "devel" \ | |
| --depends "containerd" \ | |
| --depends "xdg-dbus-proxy" \ | |
| --depends "dbus" \ | |
| --depends "systemd" \ | |
| --depends "ca-certificates" \ | |
| --depends "avahi-daemon" \ | |
| --deb-recommends "nerdctl" \ | |
| --deb-recommends "network-manager | connman" \ | |
| --deb-recommends "bluez" \ | |
| --config-files /etc/default/wendy-agent \ | |
| --config-files /etc/wendy-agent/config.json \ | |
| --config-files /etc/avahi/services/wendy-agent.service \ | |
| --after-install packaging/linux/fpm/wendy-agent-postinstall.sh \ | |
| --before-remove packaging/linux/fpm/wendy-agent-preremove.sh \ | |
| -C pkgroot/wendy-agent \ | |
| . | |
| ls -la *.deb | |
| - name: Build .rpm packages | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| # RPM doesn't allow hyphens in version, replace with underscores | |
| RPM_VERSION=$(echo "$VERSION" | tr '-' '_') | |
| # Build wendy .rpm | |
| fpm -s dir -t rpm \ | |
| -n wendy \ | |
| -v "$RPM_VERSION" \ | |
| --architecture ${{ matrix.rpm-arch }} \ | |
| --description "Wendy CLI - Remote device debugging and deployment" \ | |
| --url "https://wendy.sh" \ | |
| --maintainer "Wendy Labs Inc. <support@wendy.sh>" \ | |
| --license "Proprietary" \ | |
| --vendor "Wendy Labs Inc." \ | |
| --category "Development/Tools" \ | |
| --depends "usbutils" \ | |
| --depends "ca-certificates" \ | |
| -C pkgroot/wendy \ | |
| . | |
| # Build wendy-agent .rpm | |
| fpm -s dir -t rpm \ | |
| -n wendy-agent \ | |
| -v "$RPM_VERSION" \ | |
| --architecture ${{ matrix.rpm-arch }} \ | |
| --description "Wendy Agent - Runs on target devices for remote debugging" \ | |
| --url "https://wendy.sh" \ | |
| --maintainer "Wendy Labs Inc. <support@wendy.sh>" \ | |
| --license "Proprietary" \ | |
| --vendor "Wendy Labs Inc." \ | |
| --category "Development/Tools" \ | |
| --depends "containerd" \ | |
| --depends "xdg-dbus-proxy" \ | |
| --depends "dbus" \ | |
| --depends "systemd" \ | |
| --depends "ca-certificates" \ | |
| --depends "avahi" \ | |
| --config-files /etc/default/wendy-agent \ | |
| --config-files /etc/wendy-agent/config.json \ | |
| --config-files /etc/avahi/services/wendy-agent.service \ | |
| --after-install packaging/linux/fpm/wendy-agent-postinstall.sh \ | |
| --before-remove packaging/linux/fpm/wendy-agent-preremove.sh \ | |
| -C pkgroot/wendy-agent \ | |
| . | |
| ls -la *.rpm | |
| - name: Validate package metadata | |
| run: | | |
| set -euo pipefail | |
| WENDY_DEB=$(ls -1 wendy_*_${{ matrix.arch }}.deb | head -1) | |
| WENDY_AGENT_DEB=$(ls -1 wendy-agent_*_${{ matrix.arch }}.deb | head -1) | |
| WENDY_RPM=$(ls -1 wendy-[0-9]*.rpm | head -1) | |
| WENDY_AGENT_RPM=$(ls -1 wendy-agent-*.rpm | head -1) | |
| dpkg-deb -I "$WENDY_DEB" | grep -E "Depends:.*usbutils" | |
| dpkg-deb -I "$WENDY_DEB" | grep -E "Depends:.*ca-certificates" | |
| dpkg-deb -I "$WENDY_AGENT_DEB" | grep -E "Depends:.*containerd" | |
| dpkg-deb -I "$WENDY_AGENT_DEB" | grep -E "Depends:.*dbus" | |
| dpkg-deb -I "$WENDY_AGENT_DEB" | grep -E "Depends:.*systemd" | |
| dpkg-deb -I "$WENDY_AGENT_DEB" | grep -E "Depends:.*ca-certificates" | |
| dpkg-deb -c "$WENDY_AGENT_DEB" | grep "usr/lib/systemd/system/wendy-agent.service" > /dev/null | |
| dpkg-deb -c "$WENDY_AGENT_DEB" | grep "etc/default/wendy-agent" > /dev/null | |
| dpkg-deb -c "$WENDY_AGENT_DEB" | grep "etc/avahi/services/wendy-agent.service" > /dev/null | |
| dpkg-deb -I "$WENDY_AGENT_DEB" | grep -E "Depends:.*avahi-daemon" | |
| rpm -qp --requires "$WENDY_RPM" | grep "^usbutils" > /dev/null | |
| rpm -qp --requires "$WENDY_RPM" | grep "^ca-certificates" > /dev/null | |
| rpm -qp --requires "$WENDY_AGENT_RPM" | grep "^containerd" > /dev/null | |
| rpm -qp --requires "$WENDY_AGENT_RPM" | grep "^dbus" > /dev/null | |
| rpm -qp --requires "$WENDY_AGENT_RPM" | grep "^systemd" > /dev/null | |
| rpm -qp --requires "$WENDY_AGENT_RPM" | grep "^ca-certificates" > /dev/null | |
| rpm -qp --requires "$WENDY_AGENT_RPM" | grep "^avahi" > /dev/null | |
| rpm -qpl "$WENDY_AGENT_RPM" | grep "/usr/lib/systemd/system/wendy-agent.service" > /dev/null | |
| rpm -qpl "$WENDY_AGENT_RPM" | grep "/etc/default/wendy-agent" > /dev/null | |
| rpm -qpl "$WENDY_AGENT_RPM" | grep "/etc/avahi/services/wendy-agent.service" > /dev/null | |
| - name: Upload .deb packages | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-packages-deb-${{ matrix.arch }} | |
| path: "*.deb" | |
| retention-days: 14 | |
| - name: Upload .rpm packages | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-packages-rpm-${{ matrix.arch }} | |
| path: "*.rpm" | |
| retention-days: 14 | |
| package-windows: | |
| name: Package Windows MSI (${{ matrix.arch }}) | |
| runs-on: windows-latest | |
| needs: [determine-version, build] | |
| if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish == true) | |
| strategy: | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| goarch: amd64 | |
| - arch: arm64 | |
| goarch: arm64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install WiX | |
| run: dotnet tool install --global wix | |
| - name: Download CLI artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wendy-cli-windows-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.zip | |
| - name: Extract artifact | |
| run: | | |
| Expand-Archive "wendy-cli-windows-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.zip" -DestinationPath . | |
| - name: Build MSI | |
| run: | | |
| $VERSION = "${{ needs.determine-version.outputs.version }}" | |
| # MSI requires numeric X.Y.Z version (max 255.255.65535) | |
| if ($VERSION -match '^\d+\.\d+\.\d+') { | |
| $MSI_VERSION = $Matches[0] | |
| } else { | |
| $MSI_VERSION = "0.0.0" | |
| } | |
| $MSI_ARCH = if ("${{ matrix.arch }}" -eq "arm64") { "arm64" } else { "x64" } | |
| wix build ` | |
| -d Version="$MSI_VERSION" ` | |
| -d ExePath="wendy-cli-windows-${{ matrix.goarch }}/wendy.exe" ` | |
| -arch $MSI_ARCH ` | |
| -o "wendy-cli-windows-${{ matrix.goarch }}-${VERSION}.msi" ` | |
| go/installer/windows/wendy.wxs | |
| - name: Upload MSI | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: wendy-cli-windows-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.msi | |
| path: "wendy-cli-windows-${{ matrix.goarch }}-${{ needs.determine-version.outputs.version }}.msi" | |
| retention-days: 14 | |
| if-no-files-found: error | |
| publish-linux-repos: | |
| name: Publish to GCP Artifact Registry | |
| runs-on: ubuntu-latest | |
| needs: [determine-version, package-linux] | |
| if: needs.determine-version.outputs.is_release == 'true' && needs.determine-version.outputs.is_prerelease == 'false' | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Download all .deb packages | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: linux-packages-deb-* | |
| merge-multiple: true | |
| path: packages/deb | |
| - name: Download all .rpm packages | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: linux-packages-rpm-* | |
| merge-multiple: true | |
| path: packages/rpm | |
| - name: Authenticate to GCP | |
| uses: google-github-actions/auth@v2 | |
| with: | |
| workload_identity_provider: ${{ vars.GCP_WORKLOAD_IDENTITY_PROVIDER }} | |
| service_account: ${{ vars.GCP_SERVICE_ACCOUNT }} | |
| - name: Set up Cloud SDK | |
| uses: google-github-actions/setup-gcloud@v2 | |
| - name: Upload APT packages | |
| run: | | |
| echo "Uploading .deb packages to Artifact Registry..." | |
| for deb in packages/deb/*.deb; do | |
| echo "Uploading $deb" | |
| gcloud artifacts apt upload wendy-apt \ | |
| --location=us-central1 \ | |
| --project=${{ vars.GCP_PROJECT_ID }} \ | |
| --source="$deb" | |
| done | |
| - name: Upload YUM packages | |
| run: | | |
| echo "Uploading .rpm packages to Artifact Registry..." | |
| for rpm in packages/rpm/*.rpm; do | |
| echo "Uploading $rpm" | |
| gcloud artifacts yum upload wendy-yum \ | |
| --location=us-central1 \ | |
| --project=${{ vars.GCP_PROJECT_ID }} \ | |
| --source="$rpm" | |
| done | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| needs: [determine-version, build, build-go-macos, package-linux, package-windows] | |
| if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish == true) | |
| steps: | |
| - name: Download artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| merge-multiple: true | |
| - name: List files | |
| run: | | |
| ls -la | |
| # Create a newline-delimited list of release files | |
| { | |
| echo 'FILES<<EOF' | |
| find . -name "*.tar.gz" -o -name "*.zip" -o -name "*.msi" -o -name "*.deb" -o -name "*.rpm" | sort | |
| echo 'EOF' | |
| } >> $GITHUB_ENV | |
| - name: Create Release | |
| id: create_release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: ${{ needs.determine-version.outputs.version }} | |
| tag_name: ${{ needs.determine-version.outputs.tag_name }} | |
| draft: false | |
| prerelease: ${{ needs.determine-version.outputs.is_prerelease == 'true' }} | |
| make_latest: ${{ needs.determine-version.outputs.is_prerelease == 'false' }} | |
| files: ${{ env.FILES }} | |
| generate_release_notes: true | |
| fail_on_unmatched_files: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # Update floating 'latest' tag for nightly prereleases | |
| - name: Checkout repo | |
| if: needs.determine-version.outputs.is_release != 'true' | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Update 'latest' tag | |
| if: needs.determine-version.outputs.is_release != 'true' | |
| run: | | |
| set -euo pipefail | |
| git fetch origin --tags --force | |
| TAG='${{ needs.determine-version.outputs.tag_name }}' | |
| TARGET_SHA="$(git rev-list -n 1 "refs/tags/$TAG" || true)" | |
| if [ -z "$TARGET_SHA" ]; then TARGET_SHA="$GITHUB_SHA"; fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git tag -fa latest "$TARGET_SHA" -m "Latest prerelease: $TAG" | |
| git push -f origin refs/tags/latest | |
| # Discord notification for stable releases | |
| - name: Notify Discord | |
| if: needs.determine-version.outputs.is_prerelease == 'false' | |
| env: | |
| DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.tag_name }}" | |
| REPO="${{ github.repository }}" | |
| URL="https://github.com/${REPO}/releases/tag/${VERSION}" | |
| # Fetch release body via gh CLI (safe from shell injection) | |
| BODY=$(gh release view "$VERSION" --repo "$REPO" --json body -q .body 2>/dev/null || echo "") | |
| BODY=$(echo "$BODY" | tr -d '\r') | |
| SHORT_BODY=$(echo "$BODY" | head -c 800) | |
| # Installation instructions | |
| read -r -d '' INSTALL_INSTRUCTIONS << 'INSTALL_EOF' || true | |
| ## Install the Wendy CLI | |
| **Linux/macOS** | |
| ``` | |
| curl -fsSL https://install.wendy.sh/cli.sh | bash | |
| ``` | |
| ## Install the Wendy Agent | |
| **Linux/macOS** | |
| ``` | |
| curl -fsSL https://install.wendy.sh/agent.sh | bash | |
| ``` | |
| INSTALL_EOF | |
| FULL_DESCRIPTION="${SHORT_BODY} | |
| ${INSTALL_INSTRUCTIONS}" | |
| ESCAPED_DESC=$(echo "$FULL_DESCRIPTION" | jq -Rs .) | |
| cat > /tmp/discord_payload.json << PAYLOAD_EOF | |
| { | |
| "content": "🚀 **New CLI release**: **${VERSION}**", | |
| "embeds": [ | |
| { | |
| "title": "Release ${VERSION}", | |
| "url": "${URL}", | |
| "description": ${ESCAPED_DESC}, | |
| "color": 5814783, | |
| "footer": { "text": "${REPO} • ${VERSION}" } | |
| } | |
| ] | |
| } | |
| PAYLOAD_EOF | |
| if [ -n "$DISCORD_WEBHOOK_URL" ]; then | |
| curl -sS -X POST -H "Content-Type: application/json" \ | |
| -d @/tmp/discord_payload.json \ | |
| "$DISCORD_WEBHOOK_URL" && echo "Discord notification sent" || echo "Discord notification failed" | |
| else | |
| echo "DISCORD_WEBHOOK_URL not configured, skipping notification" | |
| fi | |
| # Bump the formula in homebrew-tap | |
| - name: Create GitHub App Token | |
| id: app-token | |
| uses: actions/create-github-app-token@v2 | |
| with: | |
| app-id: ${{ vars.CLI_PUBLISHER_APP_ID }} | |
| private-key: ${{ secrets.CLI_PUBLISHER_APP_PRIVATE_KEY }} | |
| owner: wendylabsinc | |
| repositories: homebrew-tap | |
| - name: Checkout tap | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: wendylabsinc/homebrew-tap | |
| token: ${{ steps.app-token.outputs.token }} | |
| ref: main | |
| path: tap | |
| - name: Calculate binary checksums | |
| id: checksums | |
| run: | | |
| set -euo pipefail | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| TAG_NAME="${{ needs.determine-version.outputs.tag_name }}" | |
| MACOS_URL="https://github.com/wendylabsinc/wendy-agent/releases/download/${TAG_NAME}/wendy-cli-darwin-arm64-${VERSION}.tar.gz" | |
| MACOS_SHA=$(curl -fsSL "$MACOS_URL" | sha256sum | awk '{print $1}') | |
| LINUX_ARM_URL="https://github.com/wendylabsinc/wendy-agent/releases/download/${TAG_NAME}/wendy-cli-linux-arm64-${VERSION}.tar.gz" | |
| LINUX_ARM_SHA=$(curl -fsSL "$LINUX_ARM_URL" | sha256sum | awk '{print $1}') | |
| LINUX_X86_URL="https://github.com/wendylabsinc/wendy-agent/releases/download/${TAG_NAME}/wendy-cli-linux-amd64-${VERSION}.tar.gz" | |
| LINUX_X86_SHA=$(curl -fsSL "$LINUX_X86_URL" | sha256sum | awk '{print $1}') | |
| echo "URLs and SHA256s:" | |
| echo " macOS ARM64: ${MACOS_URL} -> ${MACOS_SHA}" | |
| echo " Linux ARM64: ${LINUX_ARM_URL} -> ${LINUX_ARM_SHA}" | |
| echo " Linux x86_64: ${LINUX_X86_URL} -> ${LINUX_X86_SHA}" | |
| echo "macos_url=${MACOS_URL}" >> $GITHUB_OUTPUT | |
| echo "macos_sha=${MACOS_SHA}" >> $GITHUB_OUTPUT | |
| echo "linux_arm_url=${LINUX_ARM_URL}" >> $GITHUB_OUTPUT | |
| echo "linux_arm_sha=${LINUX_ARM_SHA}" >> $GITHUB_OUTPUT | |
| echo "linux_x86_url=${LINUX_X86_URL}" >> $GITHUB_OUTPUT | |
| echo "linux_x86_sha=${LINUX_X86_SHA}" >> $GITHUB_OUTPUT | |
| # Nightly: update wendy-nightly.rb and push directly to main | |
| - name: Bump nightly formula | |
| if: needs.determine-version.outputs.is_release != 'true' | |
| run: | | |
| set -euo pipefail | |
| cd tap | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| FORMULA="Formula/wendy-nightly.rb" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-darwin-arm64[^\"]*|${{ steps.checksums.outputs.macos_url }}|" "$FORMULA" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-linux-arm64[^\"]*|${{ steps.checksums.outputs.linux_arm_url }}|" "$FORMULA" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-linux-amd64[^\"]*|${{ steps.checksums.outputs.linux_x86_url }}|" "$FORMULA" | |
| sed -i "/wendy-cli-darwin-arm64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.macos_sha }}\"|" "$FORMULA" | |
| sed -i "/wendy-cli-linux-arm64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.linux_arm_sha }}\"|" "$FORMULA" | |
| sed -i "/wendy-cli-linux-amd64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.linux_x86_sha }}\"|" "$FORMULA" | |
| # Update bottle root_url version | |
| sed -i "s|wendy-nightly-[^\"]*|wendy-nightly-${VERSION}|" "$FORMULA" | |
| # Verify all URLs and checksums were actually updated | |
| echo "Verifying formula was updated correctly..." | |
| grep -q "wendy-cli-darwin-arm64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update macOS URL in formula"; exit 1; } | |
| grep -q "wendy-cli-linux-arm64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update Linux ARM64 URL in formula"; exit 1; } | |
| grep -q "wendy-cli-linux-amd64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update Linux AMD64 URL in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.macos_sha }}" "$FORMULA" || { echo "::error::Failed to update macOS SHA256 in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.linux_arm_sha }}" "$FORMULA" || { echo "::error::Failed to update Linux ARM64 SHA256 in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.linux_x86_sha }}" "$FORMULA" || { echo "::error::Failed to update Linux AMD64 SHA256 in formula"; exit 1; } | |
| echo "Updated nightly formula:" | |
| grep -A 1 "url\|sha256" "$FORMULA" | head -20 | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add "$FORMULA" | |
| git commit -m "wendy-nightly: update to ${VERSION}" | |
| git push origin main | |
| # Stable: update wendy.rb via PR | |
| - name: Bump stable formula | |
| if: needs.determine-version.outputs.is_release == 'true' && needs.determine-version.outputs.is_prerelease == 'false' | |
| run: | | |
| set -euo pipefail | |
| cd tap | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| BRANCH="ci/bump-wendy-${VERSION}" | |
| FORMULA="Formula/wendy.rb" | |
| git checkout -b "$BRANCH" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-darwin-arm64[^\"]*|${{ steps.checksums.outputs.macos_url }}|" "$FORMULA" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-linux-arm64[^\"]*|${{ steps.checksums.outputs.linux_arm_url }}|" "$FORMULA" | |
| sed -i "s|https://github.com/wendylabsinc/wendy-agent/releases/download/[^/]*/wendy-cli-linux-amd64[^\"]*|${{ steps.checksums.outputs.linux_x86_url }}|" "$FORMULA" | |
| sed -i "/wendy-cli-darwin-arm64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.macos_sha }}\"|" "$FORMULA" | |
| sed -i "/wendy-cli-linux-arm64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.linux_arm_sha }}\"|" "$FORMULA" | |
| sed -i "/wendy-cli-linux-amd64.*tar\.gz/,/sha256/ s|sha256 \"[^\"]*\"|sha256 \"${{ steps.checksums.outputs.linux_x86_sha }}\"|" "$FORMULA" | |
| # Update bottle root_url version | |
| sed -i "s|wendy-[0-9][^\"]*|wendy-${VERSION}|" "$FORMULA" | |
| # Verify all URLs and checksums were actually updated | |
| echo "Verifying formula was updated correctly..." | |
| grep -q "wendy-cli-darwin-arm64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update macOS URL in formula"; exit 1; } | |
| grep -q "wendy-cli-linux-arm64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update Linux ARM64 URL in formula"; exit 1; } | |
| grep -q "wendy-cli-linux-amd64-${VERSION}" "$FORMULA" || { echo "::error::Failed to update Linux AMD64 URL in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.macos_sha }}" "$FORMULA" || { echo "::error::Failed to update macOS SHA256 in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.linux_arm_sha }}" "$FORMULA" || { echo "::error::Failed to update Linux ARM64 SHA256 in formula"; exit 1; } | |
| grep -q "${{ steps.checksums.outputs.linux_x86_sha }}" "$FORMULA" || { echo "::error::Failed to update Linux AMD64 SHA256 in formula"; exit 1; } | |
| echo "Updated stable formula:" | |
| grep -A 1 "url\|sha256" "$FORMULA" | head -20 | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| git add "$FORMULA" | |
| git commit -m "wendy: bump to ${VERSION}" | |
| git push -u origin "$BRANCH" | |
| - name: Create PR | |
| if: needs.determine-version.outputs.is_release == 'true' && needs.determine-version.outputs.is_prerelease == 'false' | |
| env: | |
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| gh pr create \ | |
| --repo wendylabsinc/homebrew-tap \ | |
| --head "ci/bump-wendy-${VERSION}" \ | |
| --base main \ | |
| --title "wendy: bump to ${VERSION}" \ | |
| --label pr-pull \ | |
| --body "Automated bump from release ${VERSION} | |
| This PR updates the wendy formula to version ${VERSION}. | |
| All platforms use pre-built Go binaries." | |
| publish-aur: | |
| name: Publish AUR Packages | |
| runs-on: ubuntu-latest | |
| needs: [determine-version, release] | |
| if: needs.determine-version.outputs.is_release == 'true' && needs.determine-version.outputs.is_prerelease == 'false' | |
| strategy: | |
| matrix: | |
| include: | |
| - pkgname: wendy | |
| pkgbuild_path: packaging/arch/wendy/PKGBUILD | |
| x86_64_artifact: wendy-cli-linux-amd64 | |
| aarch64_artifact: wendy-cli-linux-arm64 | |
| - pkgname: wendy-agent | |
| pkgbuild_path: packaging/arch/wendy-agent/PKGBUILD | |
| x86_64_artifact: wendy-agent-linux-amd64 | |
| aarch64_artifact: wendy-agent-linux-arm64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Calculate checksums from release | |
| id: checksums | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| TAG_NAME="${{ needs.determine-version.outputs.tag_name }}" | |
| # Download and calculate SHA256 for x86_64 | |
| X86_64_URL="https://github.com/wendylabsinc/wendy-agent/releases/download/${TAG_NAME}/${{ matrix.x86_64_artifact }}-${VERSION}.tar.gz" | |
| echo "Downloading $X86_64_URL" | |
| X86_64_SHA=$(curl -fsSL "$X86_64_URL" | sha256sum | awk '{print $1}') | |
| echo "x86_64_sha=${X86_64_SHA}" >> $GITHUB_OUTPUT | |
| # Download and calculate SHA256 for aarch64 | |
| AARCH64_URL="https://github.com/wendylabsinc/wendy-agent/releases/download/${TAG_NAME}/${{ matrix.aarch64_artifact }}-${VERSION}.tar.gz" | |
| echo "Downloading $AARCH64_URL" | |
| AARCH64_SHA=$(curl -fsSL "$AARCH64_URL" | sha256sum | awk '{print $1}') | |
| echo "aarch64_sha=${AARCH64_SHA}" >> $GITHUB_OUTPUT | |
| echo "Checksums:" | |
| echo " x86_64: ${X86_64_SHA}" | |
| echo " aarch64: ${AARCH64_SHA}" | |
| - name: Update PKGBUILD | |
| run: | | |
| VERSION="${{ needs.determine-version.outputs.version }}" | |
| TAG_NAME="${{ needs.determine-version.outputs.tag_name }}" | |
| PKGBUILD="${{ matrix.pkgbuild_path }}" | |
| # Update version and tag | |
| sed -i "s/^_pkgver=.*/_pkgver=${VERSION}/" "$PKGBUILD" | |
| sed -i "s/^_pkgtag=.*/_pkgtag=${TAG_NAME}/" "$PKGBUILD" | |
| # Update checksums | |
| sed -i "s/sha256sums_x86_64=.*/sha256sums_x86_64=('${{ steps.checksums.outputs.x86_64_sha }}')/" "$PKGBUILD" | |
| sed -i "s/sha256sums_aarch64=.*/sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64_sha }}')/" "$PKGBUILD" | |
| echo "Updated PKGBUILD:" | |
| cat "$PKGBUILD" | |
| - name: Generate .SRCINFO | |
| uses: docker://archlinux:latest | |
| with: | |
| entrypoint: /bin/bash | |
| args: | | |
| -c " | |
| pacman -Sy --noconfirm base-devel shadow | |
| cd $(dirname ${{ matrix.pkgbuild_path }}) | |
| if ! id -u builder >/dev/null 2>&1; then | |
| useradd -m builder | |
| fi | |
| chown -R builder:builder . | |
| su builder -s /bin/bash -c 'makepkg --printsrcinfo > .SRCINFO' | |
| cat .SRCINFO | |
| " | |
| - name: Publish to AUR | |
| uses: KSXGitHub/github-actions-deploy-aur@v3.0.1 | |
| with: | |
| pkgname: ${{ matrix.pkgname }} | |
| pkgbuild: ${{ matrix.pkgbuild_path }} | |
| commit_username: ${{ secrets.AUR_USERNAME }} | |
| commit_email: ${{ secrets.AUR_EMAIL }} | |
| ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} | |
| commit_message: "Update to ${{ needs.determine-version.outputs.version }}" | |
| publish-winget: | |
| name: Publish to Winget | |
| runs-on: windows-latest | |
| needs: [determine-version, release] | |
| if: needs.determine-version.outputs.is_release == 'true' && needs.determine-version.outputs.is_prerelease == 'false' | |
| steps: | |
| - name: Install wingetcreate | |
| run: | | |
| iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe | |
| - name: Update Winget package | |
| run: | | |
| $version = "${{ needs.determine-version.outputs.version }}" | |
| $tag = "${{ needs.determine-version.outputs.tag_name }}" | |
| $base = "https://github.com/wendylabsinc/wendy-agent/releases/download/$tag" | |
| $token = "${{ secrets.WINGET_GITHUB_TOKEN }}" | |
| $amd64 = "$base/wendy-cli-windows-amd64-$version.msi" | |
| $arm64 = "$base/wendy-cli-windows-arm64-$version.msi" | |
| # Try update first; if the package doesn't exist yet, fall back to new | |
| .\wingetcreate.exe update WendyLabs.Wendy ` | |
| --version $version ` | |
| --urls $amd64 $arm64 ` | |
| --submit ` | |
| --token $token | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Host "Update failed, attempting initial submission with 'new'..." | |
| .\wingetcreate.exe new $amd64 $arm64 ` | |
| --version $version ` | |
| --id WendyLabs.Wendy ` | |
| --name Wendy ` | |
| --publisher "Wendy Labs" ` | |
| --submit ` | |
| --token $token | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Error "Winget package submission failed (update and new both failed) with exit code $LASTEXITCODE." | |
| exit $LASTEXITCODE | |
| } | |
| } | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Error "Winget package publication failed with exit code $LASTEXITCODE." | |
| exit $LASTEXITCODE | |
| } |