Skip to content

fix(ci): create GitHub Release on tag push #98

fix(ci): create GitHub Release on tag push

fix(ci): create GitHub Release on tag push #98

Workflow file for this run

# ─── Floci Dash — CI ───
#
# Runs on every push/PR to main.
# - TypeScript typecheck
# - Unit tests (fast, no dependencies)
# - Integration tests (Floci runs as a service container)
# - Coverage report uploaded as artifact
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
services:
floci:
image: floci/floci:latest
ports:
- 9878:4566
env:
FLOCI_SERVICES: s3,dynamodb,sqs,sns,lambda,iam,ec2,rds,secretsmanager,eventbridge,cloudwatch,logs
options: >-
--health-cmd "curl -sf http://localhost:4566/_floci/health"
--health-interval 5s
--health-timeout 5s
--health-retries 30
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js 22
uses: actions/setup-node@v5
with:
node-version: 22
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: TypeScript typecheck
run: make typecheck
- name: Unit tests + coverage (no Floci needed)
run: make test-cov
- name: Integration tests (against Floci service container)
run: make integration-test
env:
FLOCI_URL: http://localhost:9878
- name: Upload coverage report
uses: actions/upload-artifact@v7
with:
name: coverage
path: coverage/
retention-days: 7
- name: Upload to Codecov
uses: codecov/codecov-action@v7
with:
directory: coverage/
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
# ── Build each platform natively (no QEMU emulation) ──
build:
needs: test
if: github.ref == 'refs/heads/main'
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract platform slug
id: slug
run: echo "slug=$(echo '${{ matrix.platform }}' | tr '/' '-')" >> $GITHUB_OUTPUT
# ── Dashboard-only image ──
- name: Build dashboard-only (by digest)
id: build-dash
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ matrix.platform }}
outputs: type=image,name=ghcr.io/ofsazib/floci-dash,push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=dash-${{ steps.slug.outputs.slug }}
cache-to: type=gha,scope=dash-${{ steps.slug.outputs.slug }},mode=max
provenance: false
# ── Combined image (Floci + Dashboard) ──
- name: Build combined (by digest)
id: build-combined
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile.combined
platforms: ${{ matrix.platform }}
outputs: type=image,name=ghcr.io/ofsazib/floci-dash,push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=combined-${{ steps.slug.outputs.slug }}
cache-to: type=gha,scope=combined-${{ steps.slug.outputs.slug }},mode=max
provenance: false
- name: Export digests
run: |
mkdir -p /tmp/digests
echo "${{ steps.build-dash.outputs.digest }}" > /tmp/digests/dash-${{ steps.slug.outputs.slug }}.txt
echo "${{ steps.build-combined.outputs.digest }}" > /tmp/digests/combined-${{ steps.slug.outputs.slug }}.txt
- name: Upload digest artifacts
uses: actions/upload-artifact@v4
with:
name: digests-${{ steps.slug.outputs.slug }}
path: /tmp/digests/*.txt
retention-days: 1
# ── Merge per-platform digests into multi-arch manifests ──
merge:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Download all digest artifacts
uses: actions/download-artifact@v4
with:
pattern: digests-*
merge-multiple: true
path: /tmp/digests
- name: Read digests
id: digests
run: |
echo "dash-amd64=$(cat /tmp/digests/dash-linux-amd64.txt)" >> $GITHUB_OUTPUT
echo "dash-arm64=$(cat /tmp/digests/dash-linux-arm64.txt)" >> $GITHUB_OUTPUT
echo "combined-amd64=$(cat /tmp/digests/combined-linux-amd64.txt)" >> $GITHUB_OUTPUT
echo "combined-arm64=$(cat /tmp/digests/combined-linux-arm64.txt)" >> $GITHUB_OUTPUT
- name: Generate version tag
id: version
run: echo "tag=0.0.${{ github.run_number }}" >> $GITHUB_OUTPUT
# ── Dashboard-only manifest ──
- name: Create multi-arch manifest — dashboard-only
run: |
for tag in "${{ steps.version.outputs.tag }}" "latest"; do
docker buildx imagetools create \
-t "ghcr.io/ofsazib/floci-dash:$tag" \
"ghcr.io/ofsazib/floci-dash@${{ steps.digests.outputs.dash-amd64 }}" \
"ghcr.io/ofsazib/floci-dash@${{ steps.digests.outputs.dash-arm64 }}"
done
# ── Combined manifest ──
- name: Create multi-arch manifest — combined
run: |
for tag in "${{ steps.version.outputs.tag }}-combined" "latest-combined"; do
docker buildx imagetools create \
-t "ghcr.io/ofsazib/floci-dash:$tag" \
"ghcr.io/ofsazib/floci-dash@${{ steps.digests.outputs.combined-amd64 }}" \
"ghcr.io/ofsazib/floci-dash@${{ steps.digests.outputs.combined-arm64 }}"
done