Skip to content

v1.3.5

v1.3.5 #19

Workflow file for this run

name: Release Build
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: 'Version to build (e.g., v1.3.5)'
required: true
default: 'v1.3.5'
permissions:
contents: read
jobs:
# Matrix jobs cannot expose job outputs; docker/release text need a stable VERSION from one job.
resolve-version:
name: Resolve version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.VERSION }}
steps:
- name: Set version from release or workflow input
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "VERSION=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "VERSION=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
fi
build:
name: Build Release Binaries
needs: [resolve-version]
runs-on: ubuntu-latest
env:
# Static cross-compiled binaries (pure Go SQLite driver); matches Dockerfile and local release scripts.
CGO_ENABLED: "0"
strategy:
matrix:
include:
# Linux
- goos: linux
goarch: amd64
platform: linux-amd64
# linux/arm64: also use on Termux (Android). GOOS=linux + CGO_ENABLED=0 static ELF is the usual
# portable choice; GOOS=android cross-builds often require CGO/NDK and are a poor fit for CI.
- goos: linux
goarch: arm64
platform: linux-arm64
# Windows
- goos: windows
goarch: amd64
platform: windows-amd64
ext: .exe
# macOS
- goos: darwin
goarch: amd64
platform: darwin-amd64
- goos: darwin
goarch: arm64
platform: darwin-arm64
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version: '1.25.13'
- name: Get build metadata
id: metadata
run: |
echo "BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
echo "GIT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Build client
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
go build \
-ldflags "-X github.com/Cod-e-Codes/marchat/shared.ClientVersion=${{ needs.resolve-version.outputs.version }} \
-X github.com/Cod-e-Codes/marchat/shared.ServerVersion=${{ needs.resolve-version.outputs.version }} \
-X github.com/Cod-e-Codes/marchat/shared.BuildTime=${{ steps.metadata.outputs.BUILD_TIME }} \
-X github.com/Cod-e-Codes/marchat/shared.GitCommit=${{ steps.metadata.outputs.GIT_COMMIT }}" \
-o "build/marchat-client-${{ matrix.platform }}${{ matrix.ext }}" \
./client
- name: Build server
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
go build \
-ldflags "-X github.com/Cod-e-Codes/marchat/shared.ClientVersion=${{ needs.resolve-version.outputs.version }} \
-X github.com/Cod-e-Codes/marchat/shared.ServerVersion=${{ needs.resolve-version.outputs.version }} \
-X github.com/Cod-e-Codes/marchat/shared.BuildTime=${{ steps.metadata.outputs.BUILD_TIME }} \
-X github.com/Cod-e-Codes/marchat/shared.GitCommit=${{ steps.metadata.outputs.GIT_COMMIT }}" \
-o "build/marchat-server-${{ matrix.platform }}${{ matrix.ext }}" \
./cmd/server
- name: Create release archive
run: |
cd build
zip "../marchat-${{ needs.resolve-version.outputs.version }}-${{ matrix.platform }}.zip" \
"marchat-client-${{ matrix.platform }}${{ matrix.ext }}" \
"marchat-server-${{ matrix.platform }}${{ matrix.ext }}"
- name: Upload release artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: marchat-${{ matrix.platform }}
path: |
marchat-${{ needs.resolve-version.outputs.version }}-${{ matrix.platform }}.zip
upload-assets:
name: Upload GitHub Release Assets
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
needs: [build]
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Download all artifacts
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: release-artifacts
# softprops/action-gh-release is still node20 in action.yml; gh CLI avoids the forced-node24 annotation.
- name: Upload zips to GitHub Release
if: ${{ github.event_name != 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG="${{ github.event.release.tag_name }}"
REPO="${{ github.repository }}"
mapfile -t zips < <(find release-artifacts -type f -name '*.zip' | sort)
if [ "${#zips[@]}" -eq 0 ]; then
echo "No .zip files under release-artifacts"
exit 1
fi
gh release upload "$TAG" "${zips[@]}" --clobber --repo "$REPO"
- name: Delete Uploaded Artifacts
if: ${{ github.event_name != 'workflow_dispatch' }}
uses: geekyeggo/delete-artifact@176a747ab7e287e3ff4787bf8a148716375ca118 # v6.0.0
with:
name: |
marchat-linux-amd64
marchat-linux-arm64
marchat-windows-amd64
marchat-darwin-amd64
marchat-darwin-arm64
docker:
name: Build and Push Docker Image
runs-on: ubuntu-latest
needs: [build, resolve-version]
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Log in to Docker Hub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PAT }}
- name: Get metadata
id: meta
run: |
echo "BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
echo "GIT_COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Build and push Docker image
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
provenance: false
context: .
platforms: linux/amd64,linux/arm64
push: true
build-args: |
VERSION=${{ needs.resolve-version.outputs.version }}
BUILD_TIME=${{ steps.meta.outputs.BUILD_TIME }}
GIT_COMMIT=${{ steps.meta.outputs.GIT_COMMIT }}
tags: |
codecodesxyz/marchat:${{ needs.resolve-version.outputs.version }}
codecodesxyz/marchat:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Append Docker image info to GitHub Release
if: ${{ github.event_name != 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ needs.resolve-version.outputs.version }}
run: |
set -euo pipefail
TAG="${{ github.event.release.tag_name }}"
REPO="${{ github.repository }}"
EXISTING="$(gh release view "$TAG" --repo "$REPO" --json body -q '(.body // "")')"
{
printf '%s\n\n' "$EXISTING"
printf '%s\n\n' '## Docker Image'
printf '%s\n\n' 'A multi-architecture Docker image (linux/amd64, linux/arm64) is available on Docker Hub:'
printf '%s\n' '```bash'
printf 'docker pull codecodesxyz/marchat:%s\n' "$VERSION"
printf '%s\n' '# or use latest tag'
printf '%s\n' 'docker pull codecodesxyz/marchat:latest'
printf '%s\n' '```'
} > /tmp/marchat-release-body.md
gh release edit "$TAG" --repo "$REPO" --notes-file /tmp/marchat-release-body.md
# Pushes updated manifests to your tap, bucket, winget-pkgs fork (opens PR to Microsoft), and AUR.
# Each step no-ops when its secret is unset. Requires PACKAGING_GITHUB_PAT for Git-hosted targets.
publish-downstream-packages:
name: Publish downstream package manifests
runs-on: ubuntu-latest
needs: [upload-assets]
if: github.event_name == 'release'
permissions:
contents: read
steps:
- name: Checkout release tag
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.release.tag_name }}
fetch-depth: 1
- name: Render manifests from release zips
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
if [ -n "${{ github.event.release.published_at }}" ]; then
export RELEASE_DATE_UTC="$(echo '${{ github.event.release.published_at }}' | cut -dT -f1)"
fi
chmod +x packaging/ci/render-release-manifests.sh
packaging/ci/render-release-manifests.sh
- name: Push Homebrew tap
env:
TOKEN: ${{ secrets.PACKAGING_GITHUB_PAT }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
OWNER: ${{ github.repository_owner }}
run: |
set -euo pipefail
if [ -z "${TOKEN:-}" ]; then echo "Skip Homebrew: PACKAGING_GITHUB_PAT unset"; exit 0; fi
VER="${RELEASE_TAG#v}"
DEFAULT="$(GH_TOKEN="${TOKEN}" gh api "repos/${OWNER}/homebrew-marchat" --jq .default_branch)"
git clone --depth 1 "https://x-access-token:${TOKEN}@github.com/${OWNER}/homebrew-marchat.git" /tmp/homebrew-marchat
cp packaging-out/marchat.rb /tmp/homebrew-marchat/Formula/marchat.rb
cd /tmp/homebrew-marchat
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add Formula/marchat.rb
if git diff --cached --quiet; then echo "Homebrew: no changes"; exit 0; fi
git commit -m "marchat ${VER}"
git push origin "HEAD:${DEFAULT}"
- name: Push Scoop bucket
env:
TOKEN: ${{ secrets.PACKAGING_GITHUB_PAT }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
OWNER: ${{ github.repository_owner }}
run: |
set -euo pipefail
if [ -z "${TOKEN:-}" ]; then echo "Skip Scoop: PACKAGING_GITHUB_PAT unset"; exit 0; fi
VER="${RELEASE_TAG#v}"
DEFAULT="$(GH_TOKEN="${TOKEN}" gh api "repos/${OWNER}/scoop-marchat" --jq .default_branch)"
git clone --depth 1 "https://x-access-token:${TOKEN}@github.com/${OWNER}/scoop-marchat.git" /tmp/scoop-marchat
cp packaging-out/marchat.json /tmp/scoop-marchat/bucket/marchat.json
cd /tmp/scoop-marchat
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add bucket/marchat.json
if git diff --cached --quiet; then echo "Scoop: no changes"; exit 0; fi
git commit -m "marchat ${VER}"
git push origin "HEAD:${DEFAULT}"
- name: Open winget-pkgs PR
env:
TOKEN: ${{ secrets.PACKAGING_GITHUB_PAT }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
OWNER: ${{ github.repository_owner }}
REPO_FULL: ${{ github.repository }}
run: |
set -euo pipefail
if [ -z "${TOKEN:-}" ]; then echo "Skip winget: PACKAGING_GITHUB_PAT unset"; exit 0; fi
VER="${RELEASE_TAG#v}"
BRANCH="marchat-${VER}"
BASE_BRANCH="$(GH_TOKEN="${TOKEN}" gh api repos/microsoft/winget-pkgs --jq .default_branch)"
git clone --depth 1 "https://x-access-token:${TOKEN}@github.com/${OWNER}/winget-pkgs.git" /tmp/winget-pkgs
cd /tmp/winget-pkgs
git checkout -B "${BRANCH}"
DEST="manifests/c/Cod-e-Codes/Marchat/${VER}"
mkdir -p "${DEST}"
cp "${GITHUB_WORKSPACE}/packaging-out/winget/"*.yaml "${DEST}/"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add "${DEST}"
if git diff --cached --quiet; then echo "winget: no changes"; exit 0; fi
git commit -m "Marchat: ${VER}"
git push -u origin "${BRANCH}" --force
EXISTING="$(GH_TOKEN="${TOKEN}" gh pr list --repo microsoft/winget-pkgs --head "${OWNER}:${BRANCH}" --json number --jq 'length')"
if [ "${EXISTING}" != "0" ]; then echo "winget: PR already open for ${OWNER}:${BRANCH}"; exit 0; fi
BODY_FILE="$(mktemp)"
{
echo "Automated PR for **${REPO_FULL}** release **${RELEASE_TAG}**."
echo
echo "Manifests match published release zips (workflow publish-downstream-packages)."
} > "${BODY_FILE}"
GH_TOKEN="${TOKEN}" gh pr create \
--repo microsoft/winget-pkgs \
--head "${OWNER}:${BRANCH}" \
--base "${BASE_BRANCH}" \
--title "Marchat: version ${VER}" \
--body-file "${BODY_FILE}"
- name: Push AUR package
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
if [ -z "${AUR_SSH_PRIVATE_KEY:-}" ]; then echo "Skip AUR: AUR_SSH_PRIVATE_KEY unset"; exit 0; fi
VER="${RELEASE_TAG#v}"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur_marchat_ci
chmod 600 ~/.ssh/aur_marchat_ci
ssh-keyscan -H aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null || true
export GIT_SSH_COMMAND="ssh -i ~/.ssh/aur_marchat_ci -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new"
# Clone over HTTPS (anonymous read). SSH is only required for push and would fail clone if the key is wrong/unregistered.
git clone https://aur.archlinux.org/marchat-bin.git /tmp/marchat-aur
git -C /tmp/marchat-aur remote set-url origin ssh://aur@aur.archlinux.org/marchat-bin.git
cp "${GITHUB_WORKSPACE}/packaging-out/aur/PKGBUILD" /tmp/marchat-aur/PKGBUILD
cp "${GITHUB_WORKSPACE}/packaging-out/aur/.SRCINFO" /tmp/marchat-aur/.SRCINFO
cd /tmp/marchat-aur
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add PKGBUILD .SRCINFO
if git diff --cached --quiet; then echo "AUR: no changes"; exit 0; fi
git commit -m "release ${VER}"
git push origin HEAD