mirror of
https://github.com/KeygraphHQ/juice-shop.git
synced 2026-11-09 17:20:22 -10:00
359 lines
16 KiB
YAML
359 lines
16 KiB
YAML
name: "CI/CD Pipeline"
|
|
on:
|
|
push:
|
|
branches-ignore:
|
|
- l10n_develop
|
|
- gh-pages
|
|
paths-ignore:
|
|
- '*.md'
|
|
- 'LICENSE'
|
|
- 'monitoring/grafana-dashboard.json'
|
|
- 'screenshots/**'
|
|
tags-ignore:
|
|
- '*'
|
|
pull_request:
|
|
paths-ignore:
|
|
- '*.md'
|
|
- 'LICENSE'
|
|
- 'data/static/i18n/*.json'
|
|
- 'frontend/src/assets/i18n/*.json'
|
|
env:
|
|
NODE_DEFAULT_VERSION: 22
|
|
NODE_OPTIONS: "--max_old_space_size=4096"
|
|
CYCLONEDX_NPM_VERSION: '^2.0.0||^3.0.0'
|
|
jobs:
|
|
lint:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js 22"
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ env.NODE_DEFAULT_VERSION }}
|
|
- name: "Install application minimalistically"
|
|
run: |
|
|
npm install --ignore-scripts
|
|
cd frontend
|
|
npm install --ignore-scripts --legacy-peer-deps
|
|
- name: "Lint source code"
|
|
run: npm run lint
|
|
- name: "Lint customization configs"
|
|
run: >
|
|
npm run lint:config -- -f ./config/7ms.yml &&
|
|
npm run lint:config -- -f ./config/addo.yml &&
|
|
npm run lint:config -- -f ./config/bodgeit.yml &&
|
|
npm run lint:config -- -f ./config/ctf.yml &&
|
|
npm run lint:config -- -f ./config/default.yml &&
|
|
npm run lint:config -- -f ./config/fbctf.yml &&
|
|
npm run lint:config -- -f ./config/juicebox.yml &&
|
|
npm run lint:config -- -f ./config/mozilla.yml &&
|
|
npm run lint:config -- -f ./config/oss.yml &&
|
|
npm run lint:config -- -f ./config/quiet.yml &&
|
|
npm run lint:config -- -f ./config/tutorial.yml &&
|
|
npm run lint:config -- -f ./config/unsafe.yml
|
|
coding-challenge-rsn:
|
|
runs-on: windows-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js 22"
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ env.NODE_DEFAULT_VERSION }}
|
|
- name: "Install application"
|
|
run: npm install
|
|
- name: "Check coding challenges for accidental code discrepancies"
|
|
run: npm run rsn
|
|
test:
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest] # FIXME: Removed "windows-latest" due to 'Error: ENOENT: no such file or directory, open' error breaking at least on Node 20.0 constantly
|
|
node-version: [20, 22, 24]
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js ${{ matrix.node-version }}"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ matrix.node-version }}
|
|
- name: "Install application"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
run: npm install
|
|
- name: "Execute unit tests"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0
|
|
with:
|
|
timeout_minutes: 15
|
|
max_attempts: 3
|
|
command: npm test
|
|
- name: "Copy unit test coverage data"
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22'
|
|
run: |
|
|
cp build/reports/coverage/frontend-tests/lcov.info frontend-lcov.info
|
|
cp build/reports/coverage/server-tests/lcov.info server-lcov.info
|
|
sed -i s/SF:/SF:frontend\\//g frontend-lcov.info
|
|
shell: bash
|
|
- name: "Upload unit test coverage data"
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22'
|
|
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0
|
|
with:
|
|
name: unit-test-lcov
|
|
path: |
|
|
frontend-lcov.info
|
|
server-lcov.info
|
|
api-test:
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
matrix:
|
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
node-version: [20, 22, 24]
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js ${{ matrix.node-version }}"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ matrix.node-version }}
|
|
- name: "Install application"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
run: npm install
|
|
- name: "Execute integration tests"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0
|
|
env:
|
|
NODE_ENV: test
|
|
with:
|
|
timeout_minutes: 5
|
|
max_attempts: 3
|
|
command: npm run frisby
|
|
- name: "Copy API test coverage data"
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22'
|
|
run: cp build/reports/coverage/api-tests/lcov.info api-lcov.info
|
|
- name: "Upload API test coverage data"
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22'
|
|
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0
|
|
with:
|
|
name: api-test-lcov
|
|
path: |
|
|
api-lcov.info
|
|
coverage-report:
|
|
needs: [test, api-test]
|
|
runs-on: ubuntu-latest
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push'
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Download unit test coverage data"
|
|
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4.1.8
|
|
with:
|
|
name: unit-test-lcov
|
|
- name: "Download API test coverage data"
|
|
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 #v4.1.8
|
|
with:
|
|
name: api-test-lcov
|
|
- name: "Publish coverage to Coveralls"
|
|
uses: coverallsapp/github-action@v2
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
files: frontend-lcov.info server-lcov.info api-lcov.info
|
|
custom-config-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js 22"
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ env.NODE_DEFAULT_VERSION }}
|
|
- name: "Install application"
|
|
if: github.repository == 'juice-shop/juice-shop' || (github.repository != 'juice-shop/juice-shop' && matrix.os == 'ubuntu-latest' && matrix.node-version == '22')
|
|
run: npm install
|
|
- name: "Execute server tests for each custom configuration"
|
|
uses: nick-invision/retry@7152eba30c6575329ac0576536151aca5a72780e #v3.0.0
|
|
with:
|
|
timeout_minutes: 30
|
|
max_attempts: 3
|
|
command: >
|
|
NODE_ENV=7ms npm run test:server &&
|
|
NODE_ENV=addo npm run test:server &&
|
|
NODE_ENV=bodgeit npm run test:server &&
|
|
NODE_ENV=ctf npm run test:server &&
|
|
NODE_ENV=fbctf npm run test:server &&
|
|
NODE_ENV=juicebox npm run test:server &&
|
|
NODE_ENV=mozilla npm run test:server &&
|
|
NODE_ENV=oss npm run test:server &&
|
|
NODE_ENV=quiet npm run test:server &&
|
|
NODE_ENV=tutorial npm run test:server &&
|
|
NODE_ENV=unsafe npm run test:server
|
|
e2e:
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest]
|
|
browser: [chrome] # FIXME Switch back to [chrome, firefox] after debugging extreme flakiness of Firefox on CI/CD
|
|
fail-fast: false
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js 22"
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ env.NODE_DEFAULT_VERSION }}
|
|
- name: "Install CLI tools"
|
|
run: npm install -g @angular/cli
|
|
- name: "Install application"
|
|
run: npm install
|
|
- name: "Execute end-to-end tests on Ubuntu"
|
|
if: ${{ matrix.os == 'ubuntu-latest' }}
|
|
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b #v6.7.8
|
|
with:
|
|
install: false
|
|
browser: ${{ matrix.browser }}
|
|
start: npm start
|
|
wait-on: http://localhost:3000
|
|
record: true
|
|
group: ${{ matrix.browser }} @ ${{ matrix.os }}
|
|
env:
|
|
SOLUTIONS_WEBHOOK: ${{ secrets.E2E_SOLUTIONS_WEBHOOK }}
|
|
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
- name: "Execute end-to-end tests on Mac"
|
|
if: ${{ matrix.os == 'macos-latest' }}
|
|
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b #v6.7.8
|
|
with:
|
|
install: false
|
|
browser: ${{ matrix.browser }}
|
|
start: npm start
|
|
wait-on: http://localhost:3000
|
|
record: true
|
|
group: ${{ matrix.browser }} @ ${{ matrix.os }}
|
|
env:
|
|
CYPRESS_CACHE_FOLDER: /Users/runner/Library/Caches/Cypress
|
|
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
smoke-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Use Node.js 22"
|
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af #v4.1.0
|
|
with:
|
|
node-version: ${{ env.NODE_DEFAULT_VERSION }}
|
|
- name: "Install CLI tools"
|
|
run: |
|
|
npm install -g @cyclonedx/cyclonedx-npm@$CYCLONEDX_NPM_VERSION
|
|
npm install -g grunt-cli
|
|
- name: "Set packaging options for Grunt"
|
|
run: |
|
|
echo "PCKG_OS_NAME=linux" >> $GITHUB_ENV
|
|
echo "PCKG_NODE_VERSION=18" >> $GITHUB_ENV
|
|
echo "PCKG_CPU_ARCH=x64" >> $GITHUB_ENV
|
|
- name: "Package application"
|
|
run: |
|
|
npm install --production
|
|
npm run package:ci
|
|
- name: "Unpack application archive"
|
|
run: |
|
|
cd dist
|
|
tar -zxf juice-shop-*.tgz
|
|
- name: "Execute smoke test"
|
|
run: |
|
|
cd dist/juice-shop_*
|
|
npm start &
|
|
cd ../..
|
|
chmod +x test/smoke/smoke-test.sh
|
|
test/smoke/smoke-test.sh http://localhost:3000
|
|
docker-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Execute smoke test on Docker"
|
|
run: docker compose -f docker-compose.test.yml up --exit-code-from sut
|
|
docker:
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master')
|
|
needs: [test, api-test, e2e, custom-config-test, docker-test]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Set up QEMU"
|
|
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf #v3.2.0
|
|
- name: "Set up Docker Buildx"
|
|
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 #v3.8.0
|
|
- name: "Login to DockerHub"
|
|
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 #v3.3.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
- name: "Set tag & labels for ${{ github.ref }}"
|
|
run: |
|
|
if [ "$GITHUB_REF" == "refs/heads/master" ]; then
|
|
echo "DOCKER_TAG=latest" >> $GITHUB_ENV
|
|
else
|
|
echo "DOCKER_TAG=snapshot" >> $GITHUB_ENV
|
|
fi
|
|
echo "VCS_REF=`git rev-parse --short HEAD`" >> $GITHUB_ENV
|
|
echo "BUILD_DATE=`date -u +”%Y-%m-%dT%H:%M:%SZ”`" >> $GITHUB_ENV
|
|
- name: "Build and push for AMD64 and ARM64 processors"
|
|
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 #v6.1.0
|
|
with:
|
|
context: .
|
|
file: ./Dockerfile
|
|
platforms: linux/amd64,linux/arm64
|
|
push: true
|
|
tags: |
|
|
bkimminich/juice-shop:${{ env.DOCKER_TAG }}
|
|
build-args: |
|
|
VCS_REF=${{ env.VCS_REF }}
|
|
BUILD_DATE=${{ env.BUILD_DATE }}
|
|
CYCLONEDX_NPM_VERSION=${{ env.CYCLONEDX_NPM_VERSION }}
|
|
heroku:
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master')
|
|
needs: [test, api-test, e2e, custom-config-test]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Check out Git repository"
|
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.2.2
|
|
- name: "Install Heroku CLI"
|
|
run: curl https://cli-assets.heroku.com/install.sh | sh
|
|
- name: "Set Heroku app & branch for ${{ github.ref }}"
|
|
run: |
|
|
if [ "$GITHUB_REF" == "refs/heads/master" ]; then
|
|
echo "HEROKU_APP=juice-shop" >> $GITHUB_ENV
|
|
echo "HEROKU_BRANCH=master" >> $GITHUB_ENV
|
|
else
|
|
echo "HEROKU_APP=juice-shop-staging" >> $GITHUB_ENV
|
|
echo "HEROKU_BRANCH=develop" >> $GITHUB_ENV
|
|
fi
|
|
- name: "Deploy ${{ github.ref }} to Heroku"
|
|
uses: akhileshns/heroku-deploy@581dd286c962b6972d427fcf8980f60755c15520 #v3.13.15
|
|
with:
|
|
heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
|
|
heroku_app_name: ${{ env.HEROKU_APP }}
|
|
heroku_email: [email protected]
|
|
branch: ${{ env.HEROKU_BRANCH }}
|
|
notify-slack:
|
|
if: github.repository == 'juice-shop/juice-shop' && github.event_name == 'push' && (success() || failure())
|
|
needs:
|
|
- docker
|
|
- heroku
|
|
- lint
|
|
- coding-challenge-rsn
|
|
- smoke-test
|
|
- coverage-report
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: "Slack workflow notification"
|
|
uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a #v1.3.0
|
|
with:
|
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
|
slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}
|