name: (CD) Publish docker + s3 on: workflow_call: inputs: projects: required: true type: string jobs: publish-dist: strategy: fail-fast: false matrix: app: ${{ fromJSON(inputs.projects) }} name: ${{ matrix.app }} runs-on: ubuntu-22.04 timeout-minutes: 25 steps: - name: Check out code uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Init variables run: | echo IS_PR=false >> $GITHUB_ENV echo IS_MAINNET_RELEASE=false >> $GITHUB_ENV echo IS_TESTNET_RELEASE=false >> $GITHUB_ENV echo IS_IPFS_RELEASE=false >> $GITHUB_ENV echo IS_S3_RELEASE=false >> $GITHUB_ENV echo IS_DEV_IMAGE=false >> $GITHUB_ENV - name: Is dev image if: ${{ contains(github.ref, 'develop') && github.event_name == 'push' && matrix.app == 'trading' }} run: | echo IS_DEV_IMAGE=true >> $GITHUB_ENV - name: Is PR if: ${{ github.event_name == 'pull_request' }} run: | echo IS_PR=true >> $GITHUB_ENV - name: Is mainnet release if: ${{ contains(github.ref, 'release/mainnet') && !contains(github.ref, 'mirror') }} run: | echo IS_MAINNET_RELEASE=true >> $GITHUB_ENV - name: Is testnet release if: ${{ contains(github.ref, 'release/testnet') }} run: | echo IS_TESTNET_RELEASE=true >> $GITHUB_ENV - name: Is IPFS Release if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( env.IS_MAINNET_RELEASE == 'true' || env.IS_TESTNET_RELEASE == 'true' ) }} run: | echo IS_IPFS_RELEASE=true >> $GITHUB_ENV - name: Is S3 Release if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }} run: | echo IS_S3_RELEASE=true >> $GITHUB_ENV - name: Set up QEMU id: quemu uses: docker/setup-qemu-action@v2 - name: Available platforms run: echo ${{ steps.qemu.outputs.platforms }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log in to the Container registry (ghcr) if: ${{ env.IS_PR == 'true' }} uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Log in to the Container registry (docker hub) uses: docker/login-action@v2 if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }} with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Setup node uses: actions/setup-node@v3 with: node-version-file: '.nvmrc' # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions cache: yarn - name: Cache node modules uses: actions/cache@v3 with: path: node_modules key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }} # https://docs.github.com/en/actions/learn-github-actions/contexts - name: Define dist variables if: ${{ github.event_name == 'push' }} run: | python3 tools/ci/define-dist-variables.py --github-ref="${{ github.ref }}" --app="${{ matrix.app }}" - name: Verify script result if: ${{ github.event_name == 'push' }} run: | echo "BUCKET_NAME=${{ env.BUCKET_NAME }}" echo "ENV_NAME=${{ env.ENV_NAME }}" - name: Build local dist run: | envCmd="" if [[ ! -z "${{ env.ENV_NAME }}" ]]; then envCmd="yarn env-cmd -f ./apps/${{ matrix.app }}/.env.${{ env.ENV_NAME }}" fi if [ "${{ matrix.app }}" = "trading" ]; then $envCmd yarn nx export trading || (yarn install && $envCmd yarn nx export trading) DIST_LOCATION=dist/apps/trading/exported elif [ "${{ matrix.app }}" = "ui-toolkit" ]; then NODE_ENV=production yarn nx run ui-toolkit:build-storybook DIST_LOCATION=dist/storybook/ui-toolkit elif [ "${{ matrix.app }}" = "static" ]; then yarn nx build static || (yarn install && yarn nx build static) else $envCmd yarn nx build ${{ matrix.app }} || (yarn install && $envCmd yarn nx build ${{ matrix.app }}) fi if [[ -z "$DIST_LOCATION" ]]; then DIST_LOCATION=dist/apps/${{ matrix.app }} fi mv $DIST_LOCATION dist-result tree dist-result - name: Build and export to local Docker id: docker_build uses: docker/build-push-action@v3 with: context: . file: docker/node-outside-docker.Dockerfile load: true build-args: | APP=${{ matrix.app }} ENV_NAME=${{ env.ENV_NAME }} tags: | ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local - name: Image digest if: ${{ env.IS_PR == 'true' }} run: echo ${{ steps.docker_build.outputs.digest }} - name: Sanity check docker image run: | echo "Check ipfs-hash" docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash echo "List html directory" docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html' - name: Publish dist as docker image (ghcr) uses: docker/build-push-action@v3 continue-on-error: true id: ghcr-push if: ${{ env.IS_PR == 'true' }} with: context: . file: docker/node-outside-docker.Dockerfile push: true build-args: | APP=${{ matrix.app }} ENV_NAME=${{ env.ENV_NAME }} tags: | ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }} - name: Publish dist as docker image (docker hub) uses: docker/build-push-action@v3 continue-on-error: true id: dockerhub-push if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }} with: context: . file: docker/node-outside-docker.Dockerfile push: true build-args: | APP=${{ matrix.app }} ENV_NAME=${{ env.ENV_NAME }} tags: | vegaprotocol/${{ matrix.app }}:${{ github.sha }} vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || '' }} - name: Publish dist as docker image (ghcr - retry) uses: docker/build-push-action@v3 if: ${{ steps.ghcr-push.outcome == 'failure' }} with: context: . file: docker/node-outside-docker.Dockerfile push: true build-args: | APP=${{ matrix.app }} ENV_NAME=${{ env.ENV_NAME }} tags: | ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }} - name: Publish dist as docker image (docker hub - retry) uses: docker/build-push-action@v3 if: ${{ steps.dockerhub-push.outcome == 'failure' }} with: context: . file: docker/node-outside-docker.Dockerfile push: true build-args: | APP=${{ matrix.app }} ENV_NAME=${{ env.ENV_NAME }} tags: | vegaprotocol/${{ matrix.app }}:${{ github.sha }} vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || '' }} # bucket creation in github.com/vegaprotocol/terraform//frontend - name: Publish dist to s3 uses: jakejarvis/s3-sync-action@master # s3 releases are not happening for trading on mainnet - it's IPFS if: ${{ env.IS_S3_RELEASE == 'true' }} with: args: --acl private --follow-symlinks --delete env: AWS_S3_BUCKET: ${{ env.BUCKET_NAME }} AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_REGION: 'eu-west-1' SOURCE_DIR: 'dist-result' - name: Install aws CLI if: ${{ env.IS_S3_RELEASE == 'true' }} uses: unfor19/install-aws-cli-action@master - name: Perform cache invalidation if: ${{ env.IS_S3_RELEASE == 'true' }} env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} AWS_REGION: 'eu-west-1' run: | echo "Looking for distribution for bucket: ${{ env.BUCKET_NAME }}" id=$(aws cloudfront list-distributions | jq -Mrc '.DistributionList.Items | .[] | select(.DefaultCacheBehavior.TargetOriginId == "${{ env.BUCKET_NAME }}") | .Id') echo "Found id is: ${id}" aws cloudfront create-invalidation --distribution-id $id --paths "/*" - name: Add preview label uses: actions-ecosystem/action-add-labels@v1 if: ${{ env.IS_PR == 'true' }} with: labels: ${{ matrix.app }}-preview number: ${{ github.event.number }} - name: Trigger fleek deployment # release to ipfs happens only on mainnet (represented by main branch) for trading if: ${{ env.IS_IPFS_RELEASE == 'true' }} run: | if [[ "${{ env.IS_MAINNET_RELEASE }}" = "true" ]]; then # display info about app curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \ https://api.fleek.co/graphql # trigger new deployment as base image is always set to vegaprotocol/trading:mainnet curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \ https://api.fleek.co/graphql elif [[ "${{ env.IS_TESTNET_RELEASE }}" = "true" ]]; then # display info about app curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "query{getSiteById(siteId:\"79baaeca-1952-4ae7-a256-f668cfc1d68e\"){id latestDeploy{id status}}}"}' \ https://api.fleek.co/graphql # trigger new deployment as base image is always set to vegaprotocol/trading:mainnet curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \ -H "Content-Type: application/json" \ -d '{"query": "mutation{triggerDeploy(siteId:\"79baaeca-1952-4ae7-a256-f668cfc1d68e\"){id status}}"}' \ https://api.fleek.co/graphql fi - name: Check out ipfs-redirect if: ${{ env.IS_IPFS_RELEASE == 'true' }} uses: actions/checkout@v3 with: repository: 'vegaprotocol/ipfs-redirect' path: 'ipfs-redirect' fetch-depth: '0' token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} - name: Update interstitial page to point to the new console if: ${{ env.IS_IPFS_RELEASE == 'true' }} env: GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} run: | # set CID curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz tar -xzf kubo.tgz export PATH="$PATH:$PWD/kubo" which ipfs new_hash=$(cat ${{ matrix.app }}-ipfs-hash) new_cid=$(ipfs cid format -v 1 -b base32 $new_hash) ( cd ipfs-redirect # configure git git status cat .git/config git config --global user.email "vega-ci-bot@vega.xyz" git config --global user.name "vega-ci-bot" # update CID files if [[ "${{ env.IS_MAINNET_RELEASE }}" = "true" ]]; then echo $new_hash > cidv0-mainnet.txt echo $new_cid > cidv1-mainnet.txt git add cidv0-mainnet.txt cidv1-mainnet.txt elif [[ "${{ env.IS_TESTNET_RELEASE }}" = "true" ]]; then echo $new_hash > cidv0-fairground.txt echo $new_cid > cidv1-fairground.txt git add cidv0-fairground.txt cidv1-fairground.txt fi # create commit commit_msg="Automated hash update from ${{ github.ref }}" git commit -m "$commit_msg" git push -u origin "main" )