Skip to content

Node Build

Node Build #1150

Workflow file for this run

name: Node Build
on:
workflow_dispatch:
schedule:
- cron: '0 21 * * *'
pull_request:
branches:
- '**'
push:
branches:
- main
- release/v*
jobs:
prerequisite:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm checks
backend:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter backend build:deps
- run: NODE_OPTIONS="--max-old-space-size=4096" pnpm --filter backend test:ci
- name: AsyncAPI extension
run: |
echo "{\"extends\":[\"spectral:oas\",\"spectral:asyncapi\"]}" >> .spectral.json
- name: Validate Open API specs
run: |
npx @stoplight/spectral-cli lint ./packages/backend/src/openapi/specs/*.yaml
frontend:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter frontend typecheck
- run: pnpm --filter frontend build
auth:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter auth build:deps
- run: pnpm --filter auth test
- name: AsyncAPI extension
run: |
echo "{\"extends\":[\"spectral:oas\",\"spectral:asyncapi\"]}" >> .spectral.json
- name: Validate Open API specs
run: |
npx @stoplight/spectral-cli lint ./packages/auth/src/openapi/specs/*.yaml
token-introspection:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter token-introspection test
- name: AsyncAPI extension
run: |
echo "{\"extends\":[\"spectral:oas\",\"spectral:asyncapi\"]}" >> .spectral.json
- name: Validate Open API specs
run: |
npx @stoplight/spectral-cli lint ./packages/token-introspection/src/openapi/specs/*.yaml
mock-account-servicing-entity:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm --filter mock-account-servicing-entity build
- run: pnpm --filter mock-account-servicing-entity typecheck
graphql:
runs-on: ubuntu-latest
needs: prerequisite
strategy:
matrix:
package: [auth, backend]
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- name: generate ${{ matrix.package }} graphql
run: pnpm --filter ${{ matrix.package }} generate
- name: verify changed files
uses: tj-actions/verify-changed-files@v19
id: verify-changed-files
with:
files: |
**/generated/graphql.*
- name: fail if GraphQL was generated
if: steps.verify-changed-files.outputs.files_changed == 'true'
run: exit 1
codeql-analyze:
runs-on: ubuntu-latest
needs: prerequisite
timeout-minutes: 5
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
config:
- './.github/codeql/source.yml'
- './.github/codeql/tests.yml'
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ${{ matrix.config }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
integration-test:
runs-on: ubuntu-22.04
needs: prerequisite
timeout-minutes: 5
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup environment
uses: ./.github/workflows/rafiki/env-setup
- name: Setup hosts
run: |
echo "127.0.0.1 cloud-nine-wallet-test-backend" | sudo tee -a /etc/hosts
echo "127.0.0.1 cloud-nine-wallet-test-auth" | sudo tee -a /etc/hosts
echo "127.0.0.1 happy-life-bank-test-backend" | sudo tee -a /etc/hosts
echo "127.0.0.1 happy-life-bank-test-auth" | sudo tee -a /etc/hosts
- name: Build dependencies
run: pnpm --filter integration build:deps
- name: Run tests
run: pnpm --filter integration run-tests
node-build:
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [auth, backend, frontend, token-introspection, mock-account-servicing-entity, graphql, codeql-analyze, integration-test]
steps:
- uses: actions/checkout@v4
- uses: ./.github/workflows/rafiki/env-setup
- run: pnpm build
version-generator:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version-generator.outputs.NEW_VERSION }}
tagPushed: ${{ steps.version-generator.outputs.SHOULD_PUSH_TAG }}
dockerPush: ${{ steps.version-generator.outputs.PUSH_DOCKER_IMAGE }}
generateRelease: ${{ steps.version-generator.outputs.GENERATE_RELEASE }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Configure git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
- id: version-generator
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
SHOULD_PUSH_TAG=false
PUSH_DOCKER_IMAGE=false
GENERATE_RELEASE=false
if [ "${{ github.event_name == 'schedule' }}" = true ]; then
PUSH_DOCKER_IMAGE=true
NEW_VERSION="nightly"
elif [ "${{ github.event_name == 'workflow_dispatch' }}" = true ]; then
NEW_VERSION="manual"
elif [ "${{ startsWith(github.ref_name, 'release/v')}}" = true ]; then
PUSH_DOCKER_IMAGE=true
SHOULD_PUSH_TAG=true
GENERATE_RELEASE=true
VERSION_PREFIX=$(echo "${{ github.ref_name }}" | sed 's|release/||')
read major minor patch pre_release <<< $(echo "$VERSION_PREFIX" | awk -F'[.v-]' '{print $2, $3, $4, $5}')
version_search="v$major.$minor.*"
if [ -n "$pre_release" ]; then
version_search="$version_search-$pre_release"
fi
echo "VERSION_SEARCH: $version_search"
VERSION_PREFIX=$(git tag -l $version_search --sort=-taggerdate | head -n 1)
if [ -n "$VERSION_PREFIX" ]; then
read major minor patch pre_release <<< $(echo "$VERSION_PREFIX" | awk -F'[.v-]' '{print $2, $3, $4, $5}')
patch=$((patch + 1))
fi
NEW_VERSION="v${major}.${minor}.${patch}"
if [ -n "$pre_release" ]; then
NEW_VERSION="$NEW_VERSION-${pre_release}"
fi
else
NEW_VERSION=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9_.-]/_/g')
if [[ ! "$NEW_VERSION" =~ ^[a-zA-Z0-9] ]]; then
NEW_VERSION="tag_$NEW_VERSION"
fi
fi
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "New version will be: $NEW_VERSION"
echo "SHOULD_PUSH_TAG=$SHOULD_PUSH_TAG" >> $GITHUB_OUTPUT
echo "Will tag be pushed? $SHOULD_PUSH_TAG"
echo "PUSH_DOCKER_IMAGE=$PUSH_DOCKER_IMAGE" >> $GITHUB_OUTPUT
echo "Will docker image be pushed? $PUSH_DOCKER_IMAGE"
echo "GENERATE_RELEASE=$GENERATE_RELEASE" >> $GITHUB_OUTPUT
echo "Will generate release noted? $GENERATE_RELEASE"
if [ "$SHOULD_PUSH_TAG" = true ]; then
git tag -fa $NEW_VERSION -m "$NEW_VERSION"
git push -f origin $NEW_VERSION
fi
docker-build:
runs-on: ubuntu-latest
needs: version-generator
timeout-minutes: 10
env:
GH_TOKEN: ${{ github.token }}
strategy:
matrix:
platform:
- arch: linux/amd64
name: amd64
- arch: linux/arm64
name: arm64
package:
- auth
- backend
- frontend
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build
uses: docker/build-push-action@v5
with:
push: false
platforms: ${{ matrix.platform.arch }}
file: packages/${{ matrix.package }}/Dockerfile.prod
tags: ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}:${{ needs.version-generator.outputs.version }}
outputs: type=docker,dest=/tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
- name: Save docker image to cache
uses: actions/cache@v4
with:
path: /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
key: ${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}
docker-grype:
name: Docker Grype Scan
needs: [version-generator, docker-build]
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
platform:
- arch: linux/amd64
name: amd64
- arch: linux/arm64
name: arm64
package:
- auth
- backend
- frontend
steps:
- name: Fetch docker image from cache
uses: actions/cache/restore@v4
with:
path: /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
key: ${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}
fail-on-cache-miss: true
- name: Docker list
run: |
docker images
- name: Scan docker image
uses: anchore/scan-action@v3
with:
image: /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
fail-build: true
only-fixed: true
severity-cutoff: high
output-format: table
docker-trivy:
name: Docker Trivy Scan
needs: [version-generator, docker-build]
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
platform:
- arch: linux/amd64
name: amd64
- arch: linux/arm64
name: arm64
package:
- auth
- backend
- frontend
steps:
- name: Fetch docker image from cache
uses: actions/cache/restore@v4
with:
path: /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
key: ${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}
fail-on-cache-miss: true
- name: Download Trivy
run: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /tmp
- name: Scan docker image
run: |
docker images
/tmp/trivy image --ignore-unfixed --format table --vuln-type os,library --exit-code 1 --severity HIGH --input /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
push:
name: Push to registry
needs: [version-generator, docker-grype, docker-trivy, version-generator, node-build]
runs-on: ubuntu-latest
if: needs.version-generator.outputs.dockerPush == 'true'
strategy:
matrix:
platform:
- arch: linux/amd64
name: amd64
- arch: linux/arm64
name: arm64
package:
- auth
- backend
- frontend
steps:
- name: Fetch docker image from cache
uses: actions/cache/restore@v4
with:
path: /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
key: ${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}
fail-on-cache-miss: true
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Load image into Docker
run: |
docker load --input /tmp/${{ github.sha }}-${{ matrix.package }}-${{ matrix.platform.name }}-${{ needs.version-generator.outputs.version }}.tar
- name: List docker images
run: docker images
- name: Push to registry
run: |
docker push ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}:${{ needs.version-generator.outputs.version }}
generate-release:
runs-on: ubuntu-latest
needs: [push, version-generator]
if: needs.version-generator.outputs.generateRelease == 'true'
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Generate CHANGELOG data
id: changelog
uses: requarks/changelog-action@v1
with:
token: ${{ github.token }}
tag: ${{ needs.version-generator.outputs.version }}
- name: Create Release
uses: ncipollo/[email protected]
with:
allowUpdates: true
draft: false
makeLatest: true
prerelease: endsWith(needs.version-generator.outputs.version, '-alpha')
name: ${{ needs.version-generator.outputs.version }}
body: ${{ steps.changelog.outputs.changes }}
tag: ${{ needs.version-generator.outputs.version }}
token: ${{ github.token }}