name: release on: push: tags: - 'v*' workflow_dispatch: inputs: tag: description: 'Release tag (e.g. v1.2.3). If empty, uses current ref name.' required: false type: string build_targets: description: 'Space-separated GOOS/GOARCH targets. Leave empty to use Makefile defaults.' required: false type: string channel_variants: description: 'Space-separated package variants. Leave empty to use full none and all single-channel variants.' required: false type: string permissions: contents: write jobs: prepare-release: runs-on: ubuntu-latest outputs: raw_tag: ${{ steps.prepare.outputs.raw_tag }} version: ${{ steps.prepare.outputs.version }} targets_json: ${{ steps.prepare.outputs.targets_json }} channel_variants: ${{ steps.prepare.outputs.channel_variants }} steps: - name: Checkout uses: actions/checkout@v4 - name: Resolve release inputs id: prepare shell: bash run: | set -euo pipefail if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ inputs.tag }}" ]; then raw_tag="${{ inputs.tag }}" elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then raw_tag="${GITHUB_REF_NAME}" else raw_tag="$(git describe --tags --always --dirty 2>/dev/null || echo dev)" fi build_targets="${{ inputs.build_targets || '' }}" channel_variants="${{ inputs.channel_variants || '' }}" if [ -z "$build_targets" ]; then build_targets="linux/amd64 linux/arm64 linux/riscv64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64" fi if [ -z "$channel_variants" ]; then channel_variants="full none telegram discord feishu maixcam qq dingtalk whatsapp" fi version="${raw_tag#v}" targets_json="$(python3 -c 'import json, sys; print(json.dumps(sys.argv[1].split()))' "$build_targets")" echo "raw_tag=$raw_tag" >> "$GITHUB_OUTPUT" echo "version=$version" >> "$GITHUB_OUTPUT" echo "targets_json=$targets_json" >> "$GITHUB_OUTPUT" echo "channel_variants=$channel_variants" >> "$GITHUB_OUTPUT" echo "Build version: $version (from $raw_tag)" echo "Targets: $build_targets" echo "Variants: $channel_variants" build-and-package: needs: prepare-release runs-on: ubuntu-latest strategy: fail-fast: false matrix: target: ${{ fromJson(needs.prepare-release.outputs.targets_json) }} steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' cache-dependency-path: webui/package-lock.json - name: Install packaging tools run: | sudo apt-get update sudo apt-get install -y zip - name: Resolve matrix target id: target shell: bash run: | set -euo pipefail target="${{ matrix.target }}" goos="${target%/*}" goarch="${target#*/}" echo "goos=$goos" >> "$GITHUB_OUTPUT" echo "goarch=$goarch" >> "$GITHUB_OUTPUT" echo "artifact_name=release-$goos-$goarch" >> "$GITHUB_OUTPUT" - name: Build and package matrix artifacts shell: bash run: | set -euo pipefail make clean make package-all \ VERSION="${{ needs.prepare-release.outputs.version }}" \ BUILD_TARGETS="${{ matrix.target }}" \ CHANNEL_PACKAGE_VARIANTS="${{ needs.prepare-release.outputs.channel_variants }}" rm -f build/checksums.txt - name: Upload matrix artifacts uses: actions/upload-artifact@v4 with: name: ${{ steps.target.outputs.artifact_name }} path: | build/*.tar.gz build/*.zip if-no-files-found: error publish-release: needs: - prepare-release - build-and-package runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' steps: - name: Download packaged artifacts uses: actions/download-artifact@v4 with: pattern: release-* merge-multiple: true path: build - name: List downloaded artifacts run: find build -maxdepth 2 -type f | sort - name: Generate checksums shell: bash run: | set -euo pipefail cd build if command -v sha256sum >/dev/null 2>&1; then sha256sum *.tar.gz *.zip > checksums.txt else shasum -a 256 *.tar.gz *.zip > checksums.txt fi cat checksums.txt - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ needs.prepare-release.outputs.raw_tag }} name: ${{ needs.prepare-release.outputs.raw_tag }} generate_release_notes: true files: | build/*.tar.gz build/*.zip build/checksums.txt