Skip to content

Merge pull request #43 from getlarge/repo-sync/ticketing-exercises/main #147

Merge pull request #43 from getlarge/repo-sync/ticketing-exercises/main

Merge pull request #43 from getlarge/repo-sync/ticketing-exercises/main #147

Workflow file for this run

name: 'ticketing CI'
on:
push:
branches:
- main
paths-ignore:
- README.md
- docs
- '**/CHANGELOG.md'
# auto-generated
- 'apps/**/openapi.json'
- 'apps/**/package*.json'
- 'libs/ng/shared/data-access/src/lib/generated/**'
- CHALLENGES.md
- exercises
- assets
pull_request:
branches:
- main
types:
- ready_for_review
- opened
- reopened
- synchronize
paths-ignore:
- README.md
- docs
- '**/CHANGELOG.md'
# auto-generated
- 'apps/**/openapi.json'
- 'apps/**/package*.json'
- CHALLENGES.md
- exercises
- assets
release:
types:
- published
- edited
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-ci
cancel-in-progress: true
env:
NODE_VERSION: 20.x
CI_WORKFLOW: ci.yaml
CD_WORKFLOW: cd.yaml
BUILD_FOLDER: dist
BUILD_ARTIFACTS: build
COVERAGE_FOLDER: coverage
COVERAGE_ARTIFACTS: coverage
COVERAGE_APPS_UNIT_TESTS_ARTIFACTS: libs-unit-coverage
COVERAGE_APPS_E2E_TESTS_ARTIFACTS: apps-e2e-coverage
COVERAGE_LIBS_UNIT_TESTS_ARTIFACTS: apps-unit-coverage
COVERAGE_APPS_UNIT_TESTS_FOLDER: coverage/apps/unit
COVERAGE_APPS_E2E_TESTS_FOLDER: coverage/apps/e2e
COVERAGE_LIBS_UNIT_TESTS_FOLDER: coverage/libs
NX_CLOUD_DISTRIBUTED_EXECUTION: true
NX_DISTRIBUTED_TASK_EXECUTION: true
NX_VERBOSE_LOGGING: true
NX_CLOUD_DISTRIBUTED_EXECUTION_STOP_AGENTS_ON_FAILURE: false
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
NX_MAX_AGENTS: ${{ vars.NX_MAX_AGENTS || 8 }}
STEP_SET_FETCH_REF: 'Set fetch-ref'
STEP_SETUP_PROJECT: 'Setup node, checkout and install project dependencies'
# test jobs env. variables
NODE_ENV: ${{ vars.NODE_ENV || 'local' }}
LOG_LEVEL: ${{ vars.LOG_LEVEL || 'warn' }}
GLOBAL_API_PREFIX: api
JWT_ISSUER: ${{ secrets.JWT_ISSUER }}
JWT_ALGORITHM: ${{ secrets.JWT_ALGORITHM }}
JWT_EXPIRES_IN: ${{ secrets.JWT_EXPIRES_IN }}
JWT_PUBLIC_KEY: ${{ secrets.JWT_PUBLIC_KEY }}
JWT_PRIVATE_KEY: ${{ secrets.JWT_PRIVATE_KEY }}
SESSION_KEY: ${{ secrets.SESSION_KEY }}
STRIPE_PUBLISHABLE_KEY: ${{ secrets.STRIPE_PUBLISHABLE_KEY }}
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_SECRET_KEY }}
STRIPE_ENDPOINT_SECRET: ${{ secrets.STRIPE_ENDPOINT_SECRET }}
PROXY_SERVER_URLS: http://localhost
FRONTEND_URL: http://localhost
AUTH_SERVICE_PORT: 3000
EXPIRATION_SERVICE_PORT: 3030
ORDERS_SERVICE_PORT: 3020
PAYMENTS_SERVICE_PORT: 3040
TICKETS_SERVICE_PORT: 3010
FRONTEND_PORT: 4200
ORY_BASE_PATH: ${{ secrets.ORY_BASE_PATH }}
ORY_API_KEY: ${{ secrets.ORY_API_KEY }}
ORY_ACTION_API_KEY: ${{ secrets.ORY_ACTION_API_KEY }}
RMQ_URL: http://localhost:5672
MONGODB_URI: mongodb://localhost:27017
REDIS_URL: redis://localhost:6379
jobs:
# INIT
init:
runs-on: ubuntu-latest
if: github.event_name == 'release' || github.event_name == 'push' || !github.event.pull_request.draft
timeout-minutes: 10
steps:
- name: ${{ env.STEP_SET_FETCH_REF }}
id: fetch-ref
uses: haya14busa/action-cond@v1
with:
cond: ${{ github.ref == 'refs/head/main' }}
if_true: ${{ github.ref }}
if_false: ${{ github.event.pull_request.head.ref }}
# Needed as long as we use local actions
- uses: actions/checkout@v4
with:
ref: ${{ steps.fetch-ref.outputs.value }}
# init dependencies cache so that next jobs can start faster
- name: ${{ env.STEP_SETUP_PROJECT }}
id: setup
uses: ./.github/actions/checkout-and-yarn
with:
fetch-depth: 0
fetch-ref: ${{ steps.fetch-ref.outputs.value }}
node-version: ${{ env.NODE_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get branch names
id: branch-name
uses: tj-actions/branch-names@v7
- name: Get current version
id: package-version
uses: martinbeentjes/[email protected]
- name: Derive appropriate SHAs for base and head for `nx affected` commands
id: set-shas
uses:
nrwl/nx-set-shas@v4
# get commits count and increment by 1 for safety
- name: Find depth of NX_BASE
id: commit-depth
run: |
depth=$(git rev-list HEAD ^${{ steps.set-shas.outputs.base }} --count)
depth=$((depth + 1))
echo "BASE_DEPTH=$depth" >> $GITHUB_ENV
echo "depth=$depth" >> $GITHUB_OUTPUT
# set value to current version on release event or to an autogenerated tag
- name: Set tag
id: tag
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
echo "value=$(echo v${{ steps.package-version.outputs.current-version }})" >> $GITHUB_OUTPUT
fi
- name: List affected apps since previous workflow run
id: check-apps
run: echo "affected=$(yarn affected:apps --base=${{ steps.set-shas.outputs.base }} --plain)" >> $GITHUB_OUTPUT
- name: List affected libs since previous workflow run
id: check-libs
run: echo "affected=$(yarn affected:libs --base=${{ steps.set-shas.outputs.base }} --plain)" >> $GITHUB_OUTPUT
# check if any app is affected between this commit and the previous successful workflow run commit
- name: Check if any app was affected since previous workflow run
id: has-apps-affected
run: echo "value=$([[ -z '${{ steps.check-apps.outputs.affected }}' ]] && echo 'false' || echo 'true')" >> $GITHUB_OUTPUT
# check if any lib is affected between this commit and the previous successful workflow run commit
- name: Check if any lib was affected since previous workflow run
id: has-libs-affected
run: echo "value=$([[ -z '${{ steps.check-libs.outputs.affected }}' ]] && echo 'false' || echo 'true')" >> $GITHUB_OUTPUT
# check if any project is affected between this commit and the previous successful workflow run commit
- name: Check if any project was affected
id: has-projects-affected
run: |
if [[ "${{ steps.check-apps.outputs.affected }}" == "" && "${{ steps.check-libs.outputs.affected }}" == "" ]]; then
echo "value=false" >> $GITHUB_OUTPUT
else
echo "value=true" >> $GITHUB_OUTPUT
fi
# Run comparisons between latest successful workflow commit and current commit
- name: Check if OpenAPI specs have changed
id: open-api
run: echo "has-changed=$(yarn git:check-diff --silent -- -b ${{ steps.set-shas.outputs.base }} -p 'apps/**/openapi.json')" >> $GITHUB_OUTPUT
- name: Check if package.json has changed
id: package-json
run: echo "has-changed=$(yarn git:check-diff --silent -- -b ${{ steps.set-shas.outputs.base }} -p 'package.json')" >> $GITHUB_OUTPUT
- name: Check if regenerate job should be run
id: regenerate
run: |
if [[ "${{ steps.branch-name.outputs.current_branch }}" != 'main' ]] && \
[[ ${{ steps.open-api.outputs.has-changed }} =~ "true" ]] || \
[[ ${{ steps.package-json.outputs.has-changed }} =~ "true" ]]; then
echo "should-run=true" >> $GITHUB_OUTPUT
else
echo "should-run=false" >> $GITHUB_OUTPUT
fi
# dynamically set number of Nx agents to start
- name: Count number of Nx Cloud agents required
id: nx-cloud-agents
env:
AFFECTED_APPS: ${{ steps.check-apps.outputs.affected || '' }}
MAX_AGENTS: ${{ env.NX_MAX_AGENTS }}
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
count=$(node --eval "
const maxAgents = +process.env.MAX_AGENTS;
const count = Math.round(maxAgents);
console.log(count);"
)
else
count=$(yarn get:apps | node --eval "
const apps = require('fs').readFileSync(0).toString().trim().split(',');
const affectedApps = process.env.AFFECTED_APPS.split(',').map(e => e.trim()) || []
const maxAgents = +process.env.MAX_AGENTS;
const count = Math.round(maxAgents * (affectedApps.length / apps.length)) || 1;
console.log(count);"
)
fi
echo "count=$count" >> $GITHUB_OUTPUT
echo "matrix=$(echo $count | node --eval "
const length = parseInt(require('fs').readFileSync(0).toString().trim());
const result = JSON.stringify([...Array(length)].map((e, i) => i + 1));
console.log(result);"
)" >> $GITHUB_OUTPUT
- name: Show outputs
run: |
echo "event name: ${{ github.event_name }}"
echo "affected apps: ${{ steps.check-apps.outputs.affected }}"
echo "affected libs: ${{ steps.check-libs.outputs.affected }}"
echo "current-branch: ${{ steps.branch-name.outputs.current_branch }}"
echo "should-update-models: ${{ steps.open-api.outputs.has-changed }}"
echo "should-update-packages: ${{ steps.package-json.outputs.has-changed }}"
echo "should-run-regenerate: ${{ steps.regenerate.outputs.should-run }}"
- name: Create job summary
run: |
echo "## CI initialized! :rocket: " >> $GITHUB_STEP_SUMMARY
echo "- base commit SHA: ${{ steps.set-shas.outputs.base }}" >> $GITHUB_STEP_SUMMARY
echo "- head commit SHA: ${{ steps.set-shas.outputs.head }}" >> $GITHUB_STEP_SUMMARY
echo "- base commit depth: ${{ steps.commit-depth.outputs.depth }}" >> $GITHUB_STEP_SUMMARY
echo "- current branch: ${{ steps.branch-name.outputs.current_branch }}" >> $GITHUB_STEP_SUMMARY
echo "- current version: ${{ steps.package-version.outputs.current-version }}" >> $GITHUB_STEP_SUMMARY
echo "- tag: ${{ steps.tag.outputs.value }}" >> $GITHUB_STEP_SUMMARY
echo "- affected apps: ${{ steps.check-apps.outputs.affected }}" >> $GITHUB_STEP_SUMMARY
echo "- affected libs: ${{ steps.check-libs.outputs.affected }}" >> $GITHUB_STEP_SUMMARY
echo "- Nx agents count: ${{ steps.nx-cloud-agents.outputs.count }}" >> $GITHUB_STEP_SUMMARY
outputs:
fetch-ref: ${{ steps.fetch-ref.outputs.value }}
base: ${{ steps.set-shas.outputs.base }}
head: ${{ steps.set-shas.outputs.head }}
base-depth: ${{ steps.commit-depth.outputs.depth}}
current-branch: ${{ steps.branch-name.outputs.current_branch }}
should-update-models: ${{ steps.open-api.outputs.has-changed }}
should-update-packages: ${{ steps.package-json.outputs.has-changed }}
should-run-regenerate: ${{ steps.regenerate.outputs.should-run }}
deps-cache-hit: ${{ steps.setup.outputs.cache-hit }}
affected-apps: ${{ steps.check-apps.outputs.affected }}
affected-libs: ${{ steps.check-libs.outputs.affected }}
projects-affected: ${{ steps.has-projects-affected.outputs.value }}
agents-count: ${{ steps.nx-cloud-agents.outputs.count }}
agents-matrix: ${{ steps.nx-cloud-agents.outputs.matrix }}
job-status: ${{ job.status }}
# REGENERATE
regenerate:
needs: init
runs-on: ubuntu-latest
if: |
needs.init.outputs.should-run-regenerate == 'true'
&& needs.init.outputs.current-branch != 'main'
&& github.event_name != 'release'
&& (github.event_name == 'push' || !github.event.pull_request.draft)
timeout-minutes: 5
env:
NX_BASE: ${{ needs.init.outputs.base }}
NX_HEAD: ${{ needs.init.outputs.head }}
BASE_DEPTH: ${{ needs.init.outputs.base-depth }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ needs.init.outputs.fetch-ref }}
- name: ${{ env.STEP_SETUP_PROJECT }}
id: setup
uses: ./.github/actions/checkout-and-yarn
with:
fetch-depth: 0
fetch-ref: ${{ needs.init.outputs.fetch-ref }}
node-version: ${{ env.NODE_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Regenerate frontend models
if: needs.init.outputs.should-update-models == 'true'
run: yarn ng:openapi
- name: Run prettier
if: needs.init.outputs.should-update-models == 'true'
run: npx nx format:write --projects=shared-ng-open-api
- name: Add, commit and push generated models
if: needs.init.outputs.should-update-models == 'true'
id: commit-ng-models
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'chore: regenerate frontend models [skip ci]'
file_pattern: 'libs/ng/shared/open-api/src/lib/generated/*'
commit_options: '--no-verify'
- if: steps.commit-ng-models.outputs.changes_detected == 'true'
run: echo "BASE_DEPTH=$((${{ env.BASE_DEPTH }} + 1))" >> $GITHUB_ENV
- name: Cancel workflow on failure
if: failure()
uses: andymckay/[email protected]
outputs:
base-depth: ${{ env.BASE_DEPTH }}
job-status: ${{ job.status }}
# AGENTS
agents:
runs-on: ubuntu-latest
needs: [init, regenerate]
if: |
!failure() && !cancelled() &&
needs.init.outputs.projects-affected == 'true' &&
(github.event_name == 'release' || github.event_name == 'push' || !github.event.pull_request.draft)
name: Agent
timeout-minutes: 15
env:
NX_CLOUD_DISTRIBUTED_EXECUTION_AGENT_COUNT: ${{ needs.init.outputs.agents-count }}
services:
mongo:
image: mongo
ports:
- 27017:27017
strategy:
matrix:
# number of agents proportional to number of affected projects
agent: ${{ fromJSON(needs.init.outputs.agents-matrix) }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.init.outputs.fetch-ref }}
- name: ${{ env.STEP_SETUP_PROJECT }}
id: setup
uses: ./.github/actions/checkout-and-yarn
with:
fetch-ref: ${{ needs.init.outputs.fetch-ref }}
node-version: ${{ env.NODE_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Start Nx Agent ${{ matrix.agent }}
run: npx nx-cloud start-agent
main:
runs-on: ubuntu-latest
needs: [init, regenerate]
if: |
!failure() && !cancelled() &&
needs.init.outputs.projects-affected == 'true' &&
(github.event_name == 'release' || github.event_name == 'push' || !github.event.pull_request.draft)
services:
rabbitmq:
image: ghcr.io/getlarge/ticketing/rabbitmq:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
env:
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS:
'-rabbit auth_backends [rabbit_auth_backend_internal,rabbit_auth_backend_cache]
-rabbitmq_auth_backend_cache cached_backend rabbit_auth_backend_http
-rabbitmq_auth_backend_cache cache_ttl 5000
-rabbitmq_auth_backend_http http_method post
-rabbitmq_auth_backend_http user_path "http://172.17.0.1:3000/user"
-rabbitmq_auth_backend_http vhost_path "http://172.17.0.1:3000/vhost"
-rabbitmq_auth_backend_http resource_path "http://172.17.0.1:3000/resource"
-rabbitmq_auth_backend_http topic_path "http://172.17.0.1:3000/topic"'
options: >-
--health-cmd "rabbitmq-diagnostics status"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5672:5672
- 15672:15672
auth-mongo:
image: mongo
ports:
- 27017:27017
orders-mongo:
image: mongo
ports:
- 27018:27017
tickets-mongo:
image: mongo
ports:
- 27019:27017
payments-mongo:
image: mongo
ports:
- 27020:27017
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.init.outputs.fetch-ref }}
- name: Compute Git fetch depth
id: fetch-depth
run: echo "value=${{ needs.regenerate.outputs.base-depth || needs.init.outputs.base-depth }}" >> $GITHUB_OUTPUT
- name: ${{ env.STEP_SETUP_PROJECT }}
id: setup
uses: ./.github/actions/checkout-and-yarn
with:
# fetch-depth: ${{ steps.fetch-depth.outputs.value }}
fetch-depth: 0
fetch-ref: ${{ needs.init.outputs.fetch-ref }}
node-version: ${{ env.NODE_VERSION }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v4
- run: npx nx-cloud start-ci-run
- name: Get Nx apps to build
id: build-apps
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
echo "list=$(yarn get:apps)" >> $GITHUB_OUTPUT
else
echo "list=$(yarn affected:apps | tr -d ' ')" >> $GITHUB_OUTPUT
fi
- name: Run verifications for affected apps
uses: jameshenry/parallel-bash-commands@v1
with:
cmd1: yarn affected:lint --parallel=4 --exclude=workspace --verbose
cmd2: yarn affected:test --parallel=4 --exclude=workspace --ci --verbose
cmd3: npx nx run-many --target=build --parallel=4 --projects=${{ steps.build-apps.outputs.list }} --verbose
# running e2e tests in parallel create conflicts in DB
# cmd4: NX_CLOUD_DISTRIBUTED_EXECUTION=false yarn affected:e2e:backend --ci --verbose
- name: Stop Nx agents
if: always()
run: npx nx-cloud stop-all-agents
# - name: Run Code PushUp
# run: npx code-pushup autorun --upload.apiKey=${{ secrets.CODE_PUSHUP_API_KEY }}
# - name: Upload Code PushUp report
# uses: actions/upload-artifact@v4
# with:
# name: code-pushup-report
# path: .code-pushup
# retention-days: 5
- name: Upload build output
uses: actions/upload-artifact@v4
with:
name: ${{ env.BUILD_ARTIFACTS }}
path: ${{ env.BUILD_FOLDER }}
retention-days: 5
- name: Check libs coverage reports existence
id: check-libs-coverage
uses: andstor/file-existence-action@v3
with:
files: ${{ env.COVERAGE_LIBS_UNIT_TESTS_FOLDER }}
- name: Upload libs unit tests coverage reports
if: steps.check-libs-coverage.outputs.files_exists == 'true'
uses: actions/upload-artifact@v4
with:
name: ${{ env.COVERAGE_LIBS_UNIT_TESTS_ARTIFACTS }}
path: ${{ env.COVERAGE_LIBS_UNIT_TESTS_FOLDER }}
retention-days: 1
- name: Check apps coverage reports existence
id: check-apps-coverage
uses: andstor/file-existence-action@v3
with:
files: ${{ env.COVERAGE_APPS_UNIT_TESTS_FOLDER }}
- name: Upload apps unit tests coverage reports
if: steps.check-apps-coverage.outputs.files_exists == 'true'
uses: actions/upload-artifact@v4
with:
name: ${{ env.COVERAGE_APPS_UNIT_TESTS_ARTIFACTS }}
path: ${{ env.COVERAGE_APPS_UNIT_TESTS_FOLDER }}
retention-days: 1
- name: Check coverage reports existence
uses: andstor/file-existence-action@v3
id: check-coverage
with:
files: ${{ env.COVERAGE_APPS_E2E_TESTS_FOLDER }}
- name: Upload apps e2e tests coverage reports
if: ${{ steps.check-coverage.outputs.files_exists == 'true' }}
uses: actions/upload-artifact@v4
with:
name: ${{ env.COVERAGE_APPS_E2E_TESTS_ARTIFACTS }}
path: ${{ env.COVERAGE_APPS_E2E_TESTS_FOLDER }}
retention-days: 1
- name: Cancel workflow on failure
if: failure()
uses: andymckay/[email protected]
outputs:
has-apps-coverage: ${{ steps.check-apps-coverage.outputs.files_exists }}
has-libs-coverage: ${{ steps.check-libs-coverage.outputs.files_exists }}
fetch-ref: ${{ needs.init.outputs.fetch-ref }}