fix(backend): await signature verification (#3175) #1939
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }}-${{ matrix.platform.name }}:${{ 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: | |
- uses: actions/checkout@v4 | |
- 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: | |
- uses: actions/checkout@v4 | |
- 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 --db-repository ghcr.io/aquasecurity/trivy-db,public.ecr.aws/aquasecurity/trivy-db --java-db-repository ghcr.io/aquasecurity/trivy-java-db,public.ecr.aws/aquasecurity/trivy-java-db --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 }}-${{ matrix.platform.name }}:${{ needs.version-generator.outputs.version }} | |
push-manifest: | |
name: Push multi-arch manifest list | |
needs: [version-generator, push] | |
runs-on: ubuntu-latest | |
if: needs.version-generator.outputs.dockerPush == 'true' | |
strategy: | |
matrix: | |
package: | |
- auth | |
- backend | |
- frontend | |
steps: | |
- name: Login to GHCR | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ github.repository_owner }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Create manifest list | |
run: | | |
docker manifest create ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}:${{ needs.version-generator.outputs.version }} \ | |
--amend ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}-amd64:${{ needs.version-generator.outputs.version }} \ | |
--amend ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}-arm64:${{ needs.version-generator.outputs.version }} | |
- name: Push manifest list | |
run: | | |
docker manifest push ghcr.io/${{ github.repository_owner }}/rafiki-${{ matrix.package }}:${{ needs.version-generator.outputs.version }} | |
generate-release: | |
runs-on: ubuntu-latest | |
needs: [push-manifest, 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 }} | |
includeRefIssues: false | |
- name: Create Release | |
uses: ncipollo/release-action@v1.14.0 | |
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 }} |