Skip to content

Fix/package-updates #1234

Fix/package-updates

Fix/package-updates #1234

Workflow file for this run

name: CI / Docker Release
on:
push:
branches: ['main']
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
release:
description: 'Create a new versioned release (Docker + npm)'
required: false
type: boolean
default: false
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
permissions:
contents: read
name: Lint Codebase
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter for code
run: pnpm run lint
- name: Run linter for documentation
run: pnpm run doc:lint
- name: Run license check (backend, production)
working-directory: apps/backend
run: pnpm dlx license-checker --production --onlyAllow "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;0BSD;ISC"
- name: Run license check (client, production)
working-directory: apps/client
run: pnpm dlx license-checker --production --onlyAllow "MIT;Apache-2.0;BSD-2-Clause;BSD-3-Clause;0BSD;ISC"
build-sdk-core:
name: Build SDK Core
permissions:
contents: read
runs-on: ubuntu-latest
needs: [lint]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Build SDK Core
run: pnpm --filter @eudiplo/sdk-core build
build-backend:
name: Build Backend
permissions:
contents: read
runs-on: ubuntu-latest
needs: [lint]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter
run: pnpm run lint
- name: Build backend
run: pnpm --filter @eudiplo/backend build
build-client:
name: Build Client
permissions:
contents: read
runs-on: ubuntu-latest
needs: [lint]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter
run: pnpm run lint
- name: Build sdk core
run: pnpm --filter @eudiplo/sdk-core build
- name: Build client
run: pnpm --filter @eudiplo/client build
build-webhook:
name: Build Webhook
permissions:
contents: read
runs-on: ubuntu-latest
needs: [lint]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter
run: pnpm run lint
- name: Build webhook
run: pnpm --filter test-rp build
build-doc:
name: Build Documentation
permissions:
contents: read
runs-on: ubuntu-latest
needs: [lint]
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter
run: pnpm run lint
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Python dependencies
run: pip install -r requirements.txt
- name: Build documentation
env:
MASTER_SECRET: ci-docs-build-secret-minimum-32-chars
AUTH_CLIENT_ID: ci-docs-client
AUTH_CLIENT_SECRET: ci-docs-secret
ENCRYPTION_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
run: pnpm run doc:generate && pnpm run compodoc && mkdocs build --strict
- name: Upload built documentation
uses: actions/upload-artifact@v6
with:
name: generated-docs
path: site/
deploy-docs:
name: Deploy Documentation
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [build-doc]
runs-on: ubuntu-latest
permissions:
contents: write
pages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch full history for mike versioning
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Python dependencies
run: pip install -r requirements.txt
- name: Configure git for mike
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Build and deploy main branch docs
env:
MASTER_SECRET: ci-docs-build-secret-minimum-32-chars
AUTH_CLIENT_ID: ci-docs-client
AUTH_CLIENT_SECRET: ci-docs-secret
ENCRYPTION_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
run: |
pnpm run doc:generate
pnpm run compodoc
mike deploy --push --update-aliases main
mike set-default --push main
test-e2e:
permissions:
contents: read
name: E2E Tests
runs-on: ubuntu-latest
needs: [build-backend, build-client, build-webhook]
steps:
- uses: actions/checkout@v6
- name: Add entry to /etc/hosts
run: echo "127.0.0.1 host.testcontainers.internal" | sudo tee -a /etc/hosts
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Run linter
run: pnpm run lint
- name: setup test webhooks
run: |
nohup pnpm --filter test-rp dev &
- name: Run E2E tests
run: pnpm run --filter @eudiplo/backend test:e2e
env:
TESTCONTAINERS_HOST_OVERRIDE: host.testcontainers.internal
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage-e2e/coverage-final.json
flags: e2e-test
name: codecov-umbrella
fail_ci_if_error: false
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
report_type: test_results
- name: Upload OIDF test results
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v6
with:
name: oidf-test-results
path: apps/backend/logs/
docker-backend:
name: Build & Push Backend Docker Image
needs: [test-e2e]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Backend Docker image (for testing)
uses: docker/build-push-action@v6
with:
context: .
target: eudiplo
load: true
platforms: linux/amd64
tags: ghcr.io/openwallet-foundation-labs/eudiplo:main
build-args: VERSION=main
cache-from: type=gha
cache-to: type=gha,mode=max
# --- HEALTH TEST ---
- name: Run container (detached)
run: |
docker run -d \
--name eudiplo-test \
-p 8080:8080 \
-e MASTER_SECRET=ci-docker-test-secret-min-32-chars \
-e AUTH_CLIENT_ID=ci-docker-client \
-e AUTH_CLIENT_SECRET=ci-docker-secret \
-e ENCRYPTION_KEY=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
ghcr.io/openwallet-foundation-labs/eudiplo:main
- name: Wait for healthy
run: |
set -e
# Check if container is running
if ! docker ps -q -f name=eudiplo-test | grep -q .; then
echo "Container failed to start or exited immediately ❌"
echo ""
echo "=== Container Status ==="
docker ps -a -f name=eudiplo-test
echo ""
echo "=== Container Logs ==="
docker logs eudiplo-test 2>&1 || echo "No logs available"
exit 1
fi
# wait up to ~90s (45 * 2s) for HEALTHCHECK to pass
for i in $(seq 1 45); do
# Check if container is still running
if ! docker ps -q -f name=eudiplo-test | grep -q .; then
echo "Container stopped unexpectedly ❌"
echo ""
echo "=== Container Status ==="
docker ps -a -f name=eudiplo-test
echo ""
echo "=== Container Logs ==="
docker logs eudiplo-test 2>&1 || true
exit 1
fi
STATUS=$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' eudiplo-test)
if [ "$STATUS" = "healthy" ]; then
echo "Container is healthy ✅"
exit 0
fi
if [ "$STATUS" = "unhealthy" ]; then
echo "Container reported unhealthy ❌"
echo ""
echo "=== Health Check Log ==="
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' eudiplo-test || true
echo ""
echo "=== Container Logs ==="
docker logs eudiplo-test || true
exit 1
fi
sleep 2
done
echo "Timed out waiting for healthy ❌"
docker ps
echo ""
echo "=== Health Check Log ==="
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' eudiplo-test || true
echo ""
echo "=== Container Logs ==="
docker logs eudiplo-test || true
exit 1
- name: Stop test container
if: always()
run: docker rm -f eudiplo-test || true
- name: Log in to GitHub Container Registry
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Backend Docker image
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: docker/build-push-action@v6
with:
context: .
target: eudiplo
push: true
platforms: linux/amd64,linux/arm64
tags: ghcr.io/openwallet-foundation-labs/eudiplo:main
build-args: VERSION=main
cache-from: type=gha
cache-to: type=gha,mode=max
docker-client:
name: Build & Push Client Docker Image
needs: [build-client]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Client Docker image
uses: docker/build-push-action@v6
with:
context: .
target: client
platforms: linux/amd64,linux/arm64
push: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
tags: ghcr.io/openwallet-foundation-labs/eudiplo-client:main
cache-from: type=gha
cache-to: type=gha,mode=max
# =============================================================================
# NPM Pre-release (Main Branch Only)
# Publishes @eudiplo/sdk-core with a "main" tag as a pre-release version.
# =============================================================================
npm-prerelease:
name: Publish SDK Pre-release to npm
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: [build-sdk-core]
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: pnpm install
- name: Build SDK
run: pnpm --filter @eudiplo/sdk-core build
- name: Set pre-release version
working-directory: packages/eudiplo-sdk-core
run: |
# Get current version and append commit SHA for uniqueness
CURRENT_VERSION=$(node -p "require('./package.json').version")
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
PRE_VERSION="${CURRENT_VERSION}-main.${SHORT_SHA}"
echo "Publishing version: ${PRE_VERSION}"
npm version "${PRE_VERSION}" --no-git-tag-version
- name: Publish to npm with main tag
working-directory: packages/eudiplo-sdk-core
run: npm publish --tag main --access public --provenance
# =============================================================================
# Versioned Release (Manual Trigger Only)
# Creates a new semantic version, publishes Docker images with version tags,
# publishes npm package, and updates documentation.
# =============================================================================
release:
name: Create Versioned Release
if: github.event_name == 'workflow_dispatch' && inputs.release == true
needs: [test-e2e, docker-backend, docker-client]
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
pull-requests: write
actions: read
pages: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch full history for mike versioning
- uses: pnpm/action-setup@v4
name: Install pnpm
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: pnpm install
- name: Build SDK
run: pnpm --filter @eudiplo/sdk-core build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Run semantic-release
id: semantic_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
DOCKER_REGISTRY_USER: ${{ github.actor }}
DOCKER_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Running semantic-release..."
npx semantic-release
# Check if a new release was created by checking if a new tag was created
echo "Checking for new tags..."
git fetch --tags
NEW_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
echo "Latest tag found: $NEW_TAG"
if [ -n "$NEW_TAG" ]; then
echo "New release detected: $NEW_TAG"
echo "new_release=true" >> $GITHUB_OUTPUT
echo "version=$NEW_TAG" >> $GITHUB_OUTPUT
else
echo "No new release detected"
echo "new_release=false" >> $GITHUB_OUTPUT
fi
- name: Debug release detection
run: |
echo "New release: ${{ steps.semantic_release.outputs.new_release }}"
echo "Version: ${{ steps.semantic_release.outputs.version }}"
- name: Set up Python for docs
if: steps.semantic_release.outputs.new_release == 'true'
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Install Python dependencies for docs
if: steps.semantic_release.outputs.new_release == 'true'
run: pip install -r requirements.txt
- name: Copy env file for docs
if: steps.semantic_release.outputs.new_release == 'true'
run: cp .env.example .env
- name: Configure git for mike
if: steps.semantic_release.outputs.new_release == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Build and deploy release docs
if: steps.semantic_release.outputs.new_release == 'true'
env:
MASTER_SECRET: ci-docs-build-secret-minimum-32-chars
AUTH_CLIENT_ID: ci-docs-client
AUTH_CLIENT_SECRET: ci-docs-secret
ENCRYPTION_KEY: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
run: |
pnpm run doc:generate
pnpm run compodoc
# Deploy to latest and set as default
mike deploy --push --update-aliases latest
mike set-default --push latest