name: Release binaries description: | Build, sign, and publish release binaries for a Vikunja sub-project. Derives every per-project path, cache key, artifact name, and S3 target from the `project` input. Callers only need to provide the project name, the raw `git describe` value, and pass through the GPG/S3 secrets as inputs (composite actions can't read the `secrets` context directly). inputs: project: description: 'Which project to build: "vikunja" or "veans".' required: true release-version: description: | Raw git describe value (e.g. v1.2.3 or v2.3.0-408-ge053d317). Always passed through to the build so the binary embeds the precise commit. Filenames and the S3 directory use "unstable" instead whenever github.ref_type isn't "tag". required: true # Secrets — composite actions can't read the `secrets` context directly, so # the caller threads them through as inputs. gpg-passphrase: required: true gpg-sign-key: required: true s3-access-key-id: required: true s3-secret-access-key: required: true s3-endpoint: required: true s3-bucket: required: true s3-region: required: true runs: using: composite steps: - name: Set project paths shell: bash env: PROJECT: ${{ inputs.project }} RELEASE_VERSION_INPUT: ${{ inputs.release-version }} VERSION_OR_UNSTABLE: ${{ github.ref_type == 'tag' && inputs.release-version || 'unstable' }} run: | set -euo pipefail case "$PROJECT" in vikunja|veans) ;; *) echo "::error::Unknown project '$PROJECT'. Expected 'vikunja' or 'veans'." >&2 exit 1 ;; esac case "$PROJECT" in vikunja) output_dir="." dist_prefix="dist" ;; veans) output_dir="veans" dist_prefix="veans/dist" ;; esac { echo "PROJECT=$PROJECT" echo "RELEASE_VERSION=$RELEASE_VERSION_INPUT" echo "VERSION_OR_UNSTABLE=$VERSION_OR_UNSTABLE" echo "XGO_OUT_NAME=${PROJECT}-${VERSION_OR_UNSTABLE}" echo "OUTPUT_DIR=$output_dir" echo "DIST_PREFIX=$dist_prefix" echo "S3_TARGET_PATH=/${PROJECT}/${VERSION_OR_UNSTABLE}" echo "ARTIFACT_BINARIES_NAME=${PROJECT}_bins" echo "ARTIFACT_ZIPS_NAME=${PROJECT}_bin_packages" } >> "$GITHUB_ENV" - name: Download Mage binary uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: mage_bin - name: Make mage-static executable shell: bash run: chmod +x ./mage-static - name: Download frontend dist (vikunja only) if: inputs.project == 'vikunja' uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: frontend_dist path: frontend/dist - name: Generate config.yml.sample (vikunja only) if: inputs.project == 'vikunja' shell: bash run: ./mage-static generate:config-yaml 1 - name: Install upx shell: bash run: | set -euo pipefail wget -q https://github.com/upx/upx/releases/download/v5.0.0/upx-5.0.0-amd64_linux.tar.xz echo 'b32abf118d721358a50f1aa60eacdbf3298df379c431c3a86f139173ab8289a1 upx-5.0.0-amd64_linux.tar.xz' > upx-5.0.0-amd64_linux.tar.xz.sha256 sha256sum -c upx-5.0.0-amd64_linux.tar.xz.sha256 tar xf upx-5.0.0-amd64_linux.tar.xz sudo mv upx-5.0.0-amd64_linux/upx /usr/local/bin - name: Setup xgo cache uses: useblacksmith/cache@c5fe29eb0efdf1cf4186b9f7fcbbcbc0cf025662 # v5.1.0 with: path: /home/runner/.xgo-cache key: xgo-${{ inputs.project }}-${{ hashFiles('**/go.sum') }} restore-keys: | xgo-${{ inputs.project }}- - name: Install mage for the build module shell: bash run: go install github.com/magefile/mage@v1.17.2 - name: Build release artifacts shell: bash env: RELEASE_VERSION: ${{ env.RELEASE_VERSION }} XGO_OUT_NAME: ${{ env.XGO_OUT_NAME }} PROJECT: ${{ env.PROJECT }} run: | set -euo pipefail export PATH="$PATH:$(go env GOPATH)/bin" cd build && mage release:build "$PROJECT" - name: GPG setup uses: kolaente/action-gpg@eb0fd8f16fe9b499f060f659092c470cb9f76eb7 # main with: gpg-passphrase: ${{ inputs.gpg-passphrase }} gpg-sign-key: ${{ inputs.gpg-sign-key }} - name: Sign zips shell: bash env: DIST_PREFIX: ${{ env.DIST_PREFIX }} RELEASE_GPG_PASSPHRASE: ${{ inputs.gpg-passphrase }} run: | set -euo pipefail zip_dir="${DIST_PREFIX}/zip" echo "=== GPG agent status ===" gpg-connect-agent 'keyinfo --list' /bye || true echo "=== GPG secret keys ===" gpg -K --with-keygrip echo "=== GPG public keys ===" gpg --list-keys echo "=== Signing files in $zip_dir ===" ls -hal "$zip_dir"/* for file in "$zip_dir"/*; do gpg -v \ --default-key 7D061A4AA61436B40713D42EFF054DACD908493A \ -b --batch --yes \ --passphrase "$RELEASE_GPG_PASSPHRASE" \ --pinentry-mode loopback \ --sign "$file" done - name: Upload zips to S3 uses: kolaente/s3-action@7f58dddd682b2f93a6c6799c9f68e7a38f2da558 # main with: s3-access-key-id: ${{ inputs.s3-access-key-id }} s3-secret-access-key: ${{ inputs.s3-secret-access-key }} s3-endpoint: ${{ inputs.s3-endpoint }} s3-bucket: ${{ inputs.s3-bucket }} s3-region: ${{ inputs.s3-region }} target-path: ${{ env.S3_TARGET_PATH }} files: ${{ env.DIST_PREFIX }}/zip/* strip-path-prefix: ${{ env.DIST_PREFIX }}/zip/ - name: Store binaries uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: ${{ env.ARTIFACT_BINARIES_NAME }} path: ./${{ env.DIST_PREFIX }}/binaries/* - name: Store binary packages if: github.ref_type == 'tag' uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: ${{ env.ARTIFACT_ZIPS_NAME }} path: ./${{ env.DIST_PREFIX }}/zip/*