Skip to content

ci: nx-cloud feature toggle #203

ci: nx-cloud feature toggle

ci: nx-cloud feature toggle #203

name: Pull request (nx-cloud enabled)
on:
pull_request:
types:
- opened
- synchronize
- labeled
workflow_dispatch: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
permissions:
contents: read
pull-requests: read
actions: read
env:
NODE_OPTIONS: --max-old-space-size=8192
COMPOSE_HTTP_TIMEOUT: 180
GITHUB_ACTIONS_CACHE_URL: https://cache.dev01.devland.is/
MAX_JOBS: 3
MAX_TASKS_PER_AGENT: 10
MAX_AGENTS: 8
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
NX_BRANCH: ${{ github.head_ref || github.ref_name }}
NX_VERBOSE_LOGGING: true
SKIP_NODEJS_CACHE: ${{ contains(github.event.pull_request.labels.*.name, 'skip-nodejs-cache') }}
NX_CLOUD_DISTRIBUTED_EXECUTION: true
NX_CLOUD_DISTRIBUTED_EXECUTION_STOP_AGENTS_ON_FAILURE: true
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
jobs:
pre-checks:
name: Check if job should run
runs-on: ec2-runners
container:
image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
outputs:
should-run: ${{ steps.check.outputs.should-run }}
steps:
- name: check if nx-cloud label is set
id: check
run: |
echo github.head_ref: ${{ github.head_ref }}
echo github.ref_name: ${{ github.ref_name }}
echo NX_BRANCH: ${NX_BRANCH}
USE_NX_CLOUD=$(echo '${{ toJson(github.event.pull_request.labels) }}' | jq '.[] | select(.name == "nx-cloud")? | any' | grep -q true && echo "true" || echo "false")
echo "should-run=$USE_NX_CLOUD" >> $GITHUB_OUTPUT
prepare:
runs-on: ec2-runners
container:
image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
# GitHub's default timeout is 360 minutes
timeout-minutes: 360
outputs:
node-modules-hash: ${{ steps.calculate_node_modules_hash.outputs.node-modules-hash }}
generated-files-cache-key: ${{ steps.calculate_generated_files_cache_key.outputs.generated-files-cache-key }}
matrix: ${{ steps.set-matrix.outputs.matrix }}
affected: ${{ steps.set-matrix.outputs.affected }}
nx-base: ${{ steps.set-sha.outputs.base }}
nx-head: ${{ steps.set-sha.outputs.head }}
needs:
- pre-checks
if: needs.pre-checks.outputs.should-run == 'true'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Keep PR run event
uses: actions/upload-artifact@v2
with:
name: pr-event
path: event.json
retention-days: 60
- name: Find sha for NX
id: set-sha
uses: nrwl/nx-set-shas@v3
with:
error-on-no-successful-workflow: 'true' # break hard
last-successful-event: 'pull-request'
workflow-id: 'pullrequest' # use legacy workflow to get more chance of hits
- name: Export sha for NX
id: export-sha
run: |
BASE_SHA=${{ steps.set-sha.outputs.base }}
HEAD_SHA=${{ steps.set-sha.outputs.head }}
echo "{\"base_sha\": \"$BASE_SHA\", \"head_sha\":\"$HEAD_SHA\"}" > event.json
- uses: actions/setup-node@v3
with:
node-version: '18.8.0'
- name: Calculate cache key for node_modules
id: calculate_node_modules_hash
run: |
PACKAGE_JSON_HASH=$(cat package.json | jq '{resolutions,dependencies,devDependencies}' | sha1sum -t | cut -f1 -d" ")
echo "PACKAGE_JSON_HASH: $PACKAGE_JSON_HASH"
NODE_MODULES_HASH=${{ runner.os }}-${{ hashFiles('yarn.lock') }}-$PACKAGE_JSON_HASH
echo "node-modules-hash: $NODE_MODULES_HASH"
echo "node-modules-hash=$NODE_MODULES_HASH" >> $GITHUB_OUTPUT
- name: Calculate cache keys for generated files
id: calculate_generated_files_cache_key
run: |
export HASH=${{ hashFiles('scripts/schemas.js', 'libs/cms/src/lib/generated/contentfulTypes.d.ts', 'apps/air-discount-scheme/web/i18n/withLocale.tsx', 'apps/air-discount-scheme/web/components/AppLayout/AppLayout.tsx', 'apps/air-discount-scheme/web/components/Header/Header.tsx', 'apps/air-discount-scheme/web/screens/**.tsx', 'apps/**/codegen.yml', 'libs/**/codegen.yml', 'apps/**/*.model.ts', 'libs/**/*.model.ts', 'apps/**/*.enum.ts', 'libs/**/*.enum.ts', 'apps/**/queries/**/*.tsx?', 'libs/**/queries/**/*.tsx?', 'libs/**/mutations/**/*.tsx?', 'libs/**/fragments/**/*.tsx?' , 'apps/**/*.resolver.ts', 'libs/**/*.resolver.ts', 'apps/**/*.service.ts', 'libs/**/*.service.ts', 'apps/**/*.dto.ts', 'libs/**/*.dto.ts', 'apps/**/*.input.ts', 'libs/**/*.input.ts', 'apps/**/*.module.ts', 'libs/**/*.module.ts', 'apps/**/*.controller.ts', 'libs/**/*.controller.ts', 'apps/**/*.union.ts', 'libs/**/*.union.ts', 'apps/**/*.graphql.ts', 'apps/judicial-system/**/*.graphql', 'libs/**/*.graphql.ts', 'libs/**/*.graphql') }}
GENERATED_FILES_CACHE_KEY=${{ runner.os }}-$HASH-files-generated
echo "GENERATED_FILES_CACHE_KEY: $GENERATED_FILES_CACHE_KEY"
echo "generated-files-cache-key=$GENERATED_FILES_CACHE_KEY" >> $GITHUB_OUTPUT
- name: Cache for NodeJS dependencies - host OS
id: node-modules
continue-on-error: true
uses: ./.github/actions/cache
with:
path: node_modules
key: ${{ steps.calculate_node_modules_hash.outputs.node-modules-hash }}-yarn
- name: Check cache success
run: '[[ "${{ steps.node-modules.outputs.success }}" != "false" ]] || exit 1'
- name: Cache for generated files
id: generated-files-cache
continue-on-error: true
uses: ./.github/actions/cache
with:
path: generated_files.tar.gz
key: ${{ steps.calculate_generated_files_cache_key.outputs.generated-files-cache-key }}
- name: Check cache success
run: '[[ "${{ steps.generated-files-cache.outputs.success }}" != "false" ]] || exit 1'
- name: Building NodeJS dependencies
if: steps.node-modules.outputs.cache-hit != 'true' || env.SKIP_NODEJS_CACHE == 'true'
run: ./scripts/ci/10_prepare-host-deps.sh
- name: Generate schemas
if: steps.generated-files-cache.outputs.cache-hit != 'true'
run: |
node --version
tar zcvf generated_files.tar.gz $(./scripts/ci/get-files-touched-by.sh yarn schemas --skip-cache | xargs realpath --relative-to $(pwd))
- name: Calculate NX agent count
id: set-matrix
shell: bash
# Turn the number-of-agents input into a JSON structure which is compatible with a Github job matrix strategy
run: |
NX_AFFECTED_PROJECTS_COUNT=$(npx nx print-affected --base=$BASE --head=$HEAD --select=projects | tr ',' ' ' | wc -w)
AGENTS_COUNT=$(node ./scripts/ci/_num_agents.js $NX_AFFECTED_PROJECTS_COUNT $MAX_AGENTS ${MAX_TASKS_PER_AGENT:-$MAX_JOBS} | jq -r '.chunksCount')
AGENTS_JSON_ARRAY=$(node -e "console.log(JSON.stringify(Array.from(new Array($AGENTS_COUNT)).map((_, i) => i + 1)));")
echo "affected projects count: $NX_AFFECTED_PROJECTS_COUNT"
echo "agents count: $AGENTS_COUNT"
echo "agents json: $AGENTS_JSON_ARRAY"
echo "matrix=$AGENTS_JSON_ARRAY" >> $GITHUB_OUTPUT
echo "affected=$NX_AFFECTED_PROJECTS_COUNT" >> $GITHUB_OUTPUT
nx-cloud-agent:
needs:
- prepare
env:
BASE: ${{ needs.prepare.outputs.nx-base }}
HEAD: ${{ needs.prepare.outputs.nx-head }}
runs-on: ec2-runners
container:
image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
timeout-minutes: 30
strategy:
matrix:
agent:
- ${{fromJson(needs.prepare.outputs.matrix)}}
defaults:
run:
working-directory: ${{ github.workspace }}
shell: bash
if: needs.prepare.outputs.affected > 0
steps:
- uses: actions/checkout@v3
- name: Setup yarn
run: npm install -g yarn
- name: Cache for NodeJS dependencies - host OS
id: node-modules
continue-on-error: true
uses: ./.github/actions/cache
with:
path: node_modules
key: ${{ needs.prepare.outputs.node-modules-hash }}-yarn
- name: Check cache success
run: '[[ "${{ steps.node-modules.outputs.success }}" != "false" ]] || exit 1'
- name: Cache for generated files
id: generated-files-cache
continue-on-error: true
uses: ./.github/actions/cache
with:
path: generated_files.tar.gz
key: ${{ needs.prepare.outputs.generated-files-cache-key }}
- name: Check cache success
run: '[[ "${{ steps.generated-files-cache.outputs.success }}" != "false" ]] || exit 1'
- name: Untar generated files
run: tar zxvf generated_files.tar.gz
- name: Start Nx Agent ${{ matrix.agent }}
run: npx nx-cloud start-agent
env:
NX_AGENT_NAME: ${{matrix.agent}}
nx-cloud-main:
needs:
- prepare
env:
NX_BASE: ${{ needs.prepare.outputs.nx-base }}
NX_HEAD: ${{ needs.prepare.outputs.nx-head }}
runs-on: ec2-runners
container:
image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
timeout-minutes: 30
defaults:
run:
working-directory: ${{ github.workspace }}
shell: bash
if: needs.prepare.outputs.affected > 0
steps:
- uses: actions/checkout@v3
name: Checkout [Pull Request]
if: ${{ github.event_name == 'pull_request' }}
with:
fetch-depth: 0
- name: Setup yarn
run: npm install -g yarn
- name: Cache for NodeJS dependencies - host OS
id: node-modules
continue-on-error: true
uses: ./.github/actions/cache
with:
path: node_modules
key: ${{ needs.prepare.outputs.node-modules-hash }}-yarn
- name: Check cache success
run: '[[ "${{ steps.node-modules.outputs.success }}" != "false" ]] || exit 1'
- name: Cache for generated files
id: generated-files-cache
continue-on-error: true
uses: ./.github/actions/cache
with:
path: generated_files.tar.gz
key: ${{ needs.prepare.outputs.generated-files-cache-key }}
- name: Check cache success
run: '[[ "${{ steps.generated-files-cache.outputs.success }}" != "false" ]] || exit 1'
- name: Untar generated files
run: tar zxvf generated_files.tar.gz
- name: Start NX ci run
run: npx nx-cloud start-ci-run -stop-agents-after=build
- name: Run NX targets
run: |
source ./scripts/ci/_common.sh
pids=()
npx nx affected -t lint --parallel=$MAX_JOBS & pids+=($!)
npx nx affected -t test --parallel=$MAX_JOBS & pids+=($!)
npx nx affected -t build --parallel=$MAX_JOBS --configuration=production & pids+=($!)
for pid in ${pids[*]}; do
if ! wait $pid; then
exit 1
fi
done
exit 0
- name: Stop all running agents for this CI run
if: ${{ always() }}
run: npx nx-cloud stop-all-agents
# check-matrix:
# runs-on: ec2-runners
# container:
# image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
# needs: [nx]
# outputs:
# matrix: ${{ steps.matrix.outputs.matrix }}
# steps:
# - uses: actions/download-artifact@v3
# - run: |
# echo "Check matrix"
# matrix="$(cat */matrix | jq -c --slurp .)"
# echo "matrix: $matrix"
# echo "::set-output name=matrix::$matrix"
# id: matrix
# TODO: trying to dynamically get the the matrix result output, unfinished
# success:
# if: always()
# name: 'Success ${{ matrix.includes.nx-target }}'
# runs-on: ec2-runners
# needs:
# - check-matrix
# container:
# image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest
# strategy:
# fail-fast: false
# matrix:
# target: ${{ fromJSON(needs.check-matrix.outputs.nx-target) }}
# steps:
# - name: Check nx success
# run: '[[ ${{ toJSON(needs.nx.result) }} != "failure" ]] || exit 1'
# - name: Announce success
# run: echo "${{ toJSON(needs.nx) }} is successful"