diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index e25e2ba03e0..19f5fa490d6 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -17,14 +17,6 @@ jobs: secrets: GU_ARTIFACTS_ROLE_ARN: ${{ secrets.GU_ARTIFACTS_ROLE_ARN }} - container: - permissions: - packages: write - needs: [production-container] - uses: ./.github/workflows/container.yml - with: - production-image-digest: ${{ needs.production-container.outputs.imageDigest }} - prettier: if: github.ref != 'refs/heads/main' uses: ./.github/workflows/prettier.yml @@ -58,7 +50,7 @@ jobs: id-token: write contents: read pull-requests: write # required by riff-raff action - needs: [container, islands, prettier, jest, lint, playwright] + needs: [production-container, islands, prettier, jest, lint, playwright] # We don't need a riff-raff deployment for merge_group events. # `!cancelled()` forces this job to be evaluated even when some of the # `needs` jobs are skipped (the checks are skipped on push to main), and @@ -71,6 +63,7 @@ jobs: github.event_name == 'push' uses: ./.github/workflows/publish.yml with: - container-image: ${{ needs.container.outputs.container-image }} + production-image-digest: ${{ needs.production-container.outputs.imageDigest }} secrets: GU_RIFF_RAFF_ROLE_ARN: ${{ secrets.GU_RIFF_RAFF_ROLE_ARN }} + GU_ARTIFACTS_ROLE_ARN: ${{ secrets.GU_ARTIFACTS_ROLE_ARN }} diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml deleted file mode 100644 index c64e04de92a..00000000000 --- a/.github/workflows/container.yml +++ /dev/null @@ -1,61 +0,0 @@ -# Commercial also use this container image for their E2E tests -# Commercial rely on a container image built from the main branch with the tag 'main' -on: - workflow_call: - inputs: - production-image-digest: - description: 'Digest of image pushed to AWS ECR to run on AWS ECS. Gets used by `cdk synth`.' - required: true - type: string - outputs: - container-image: - description: 'The generated container image path' - value: ${{ jobs.image.outputs.container-image }} - -jobs: - image: - runs-on: ubuntu-latest - - permissions: - packages: write - - outputs: - container-image: ${{ steps.push.outputs.registry-path }} - - steps: - - name: Checkout repository - uses: actions/checkout@v7 - - - name: Set up Node environment - uses: ./.github/actions/setup-node-env - - - name: Add commit hash for PRout - working-directory: dotcom-rendering - run: | - echo 'export const GIT_COMMIT_HASH = "${{ github.sha }}";' > src/server/prout.ts - - - name: Generate production bundle - env: - IMAGE_DIGEST: ${{ inputs.production-image-digest }} - run: make riffraff-bundle - working-directory: dotcom-rendering - - - name: Build Container Image - id: build_image - uses: redhat-actions/buildah-build@v3 - with: - image: dotcom-rendering - # Commercial rely on a container image built from the main branch with the tag 'main' - tags: ${{ github.sha }} ${{ github.ref == 'refs/heads/main' && 'main' || '' }} - context: ./ - containerfiles: ./dotcom-rendering/Containerfile - - - name: Push Image To GHCR - uses: redhat-actions/push-to-registry@v2.8 - id: push - with: - image: ${{ steps.build_image.outputs.image }} - tags: ${{ steps.build_image.outputs.tags }} - registry: ghcr.io/guardian - username: ${{ github.actor }} - password: ${{ github.token }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0c868bf8870..d3b9fba52ce 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,53 +1,114 @@ on: workflow_call: inputs: - container-image: - description: 'Image used by DCR service' + production-image-digest: + description: 'Digest of DCR image in AWS ECR' required: true type: string secrets: GU_RIFF_RAFF_ROLE_ARN: required: true + GU_ARTIFACTS_ROLE_ARN: + required: true permissions: # Allow GitHub to request an OIDC JWT ID token, and to comment on pull requests as required by guardian/actions-riff-raff id-token: write pull-requests: write + contents: read jobs: riffraff: runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Set up Node environment + uses: ./.github/actions/setup-node-env + + # TODO abstract this into a reusable GitHub Action e.g. https://github.com/guardian/actions-publish-image + - name: AWS ECR configure credentials + uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0 + with: + role-to-assume: ${{ secrets.GU_ARTIFACTS_ROLE_ARN }} + aws-region: eu-west-1 + mask-aws-account-id: 'true' + + # TODO abstract this into a reusable GitHub Action e.g. https://github.com/guardian/actions-publish-image + - name: AWS ECR login + id: ecr-login + uses: aws-actions/amazon-ecr-login@03f1aad4c6c7ffd436567f42f9384779290529bd # v2.1.7 + with: + mask-password: 'true' + + # Clear AWS credentials (stored in environment variables) to avoid leaking them to any subsequent steps + # See https://github.com/aws-actions/configure-aws-credentials/issues/1308 + # TODO abstract this into a reusable GitHub Action e.g. https://github.com/guardian/actions-publish-image + - name: AWS ECR clear credentials + if: always() + shell: bash + run: | + echo "AWS_ACCESS_KEY_ID=''" >>"$GITHUB_ENV" + echo "AWS_SECRET_ACCESS_KEY=''" >>"$GITHUB_ENV" + echo "AWS_SESSION_TOKEN=''" >>"$GITHUB_ENV" + echo "AWS_DEFAULT_REGION=''" >>"$GITHUB_ENV" + echo "AWS_REGION=''" >>"$GITHUB_ENV" + + # TODO abstract this into a reusable GitHub Action e.g. https://github.com/guardian/actions-publish-image + - name: AWS ECR pull image + id: ecr-pull + env: + REGISTRY: ${{ steps.ecr-login.outputs.registry }} + run: | + IMAGE="$REGISTRY/guardian/dotcom-rendering@${{ inputs.production-image-digest }}" + docker pull $IMAGE + echo "IMAGE=$IMAGE" >> "$GITHUB_OUTPUT" + # Annoyingly we can't _easily_ access an Images filesystem without creating a container from the image. # we don't necessarily have to start the container, but we do need to create it. - - name: Create DCR Container - id: create-container - run: echo "CONTAINER_ID=$(docker create ${{ inputs.container-image }})" >> "$GITHUB_OUTPUT" - - name: Move container files into GHA Workspace - run: docker cp ${{ steps.create-container.outputs.CONTAINER_ID }}:/opt/app/dotcom-rendering/dotcom-rendering/. ${{ github.workspace }} + - name: Copy container files into GHA Workspace + working-directory: dotcom-rendering + run: | + CONTAINER_ID=$(docker create ${{ steps.ecr-pull.outputs.IMAGE }}) + docker cp $CONTAINER_ID:/app/. dist + + - name: CDK synth + env: + IMAGE_DIGEST: ${{ inputs.production-image-digest }} + working-directory: dotcom-rendering + run: make cdk-synth + + - name: Construct EC2 artifacts + working-directory: dotcom-rendering + run: make riffraff-bundle # We want to avoid uploading the uncompressed files to our riffraff bucket # so we create our tarball outside the folder, then delete the contents of # the folder, and finally move the tarball into the folder. - name: Compress article-rendering app server files + working-directory: dotcom-rendering/target run: | tar -zcf article-rendering.tar.gz article-rendering rm -r article-rendering/* mv article-rendering.tar.gz article-rendering/ - name: Compress facia-rendering app server files + working-directory: dotcom-rendering/target run: | tar -zcf facia-rendering.tar.gz facia-rendering rm -r facia-rendering/* mv facia-rendering.tar.gz facia-rendering/ - name: Compress tag-page-rendering app server files + working-directory: dotcom-rendering/target run: | tar -zcf tag-page-rendering.tar.gz tag-page-rendering rm -r tag-page-rendering/* mv tag-page-rendering.tar.gz tag-page-rendering/ - name: Compress interactive-rendering app server files + working-directory: dotcom-rendering/target run: | tar -zcf interactive-rendering.tar.gz interactive-rendering rm -r interactive-rendering/* @@ -60,23 +121,23 @@ jobs: githubToken: ${{ secrets.GITHUB_TOKEN }} roleArn: ${{ secrets.GU_RIFF_RAFF_ROLE_ARN }} projectName: dotcom:rendering-all - configPath: riff-raff.yaml + configPath: dotcom-rendering/target/riff-raff.yaml contentDirectories: | article-rendering-cfn: - - article-rendering-cfn + - dotcom-rendering/target/article-rendering-cfn article-rendering: - - article-rendering + - dotcom-rendering/target/article-rendering facia-rendering-cfn: - - facia-rendering-cfn + - dotcom-rendering/target/facia-rendering-cfn facia-rendering: - - facia-rendering + - dotcom-rendering/target/facia-rendering tag-page-rendering-cfn: - - tag-page-rendering-cfn + - dotcom-rendering/target/tag-page-rendering-cfn tag-page-rendering: - - tag-page-rendering + - dotcom-rendering/target/tag-page-rendering interactive-rendering-cfn: - - interactive-rendering-cfn + - dotcom-rendering/target/interactive-rendering-cfn interactive-rendering: - - interactive-rendering + - dotcom-rendering/target/interactive-rendering frontend-static: - - frontend-static + - dotcom-rendering/target/frontend-static diff --git a/dotcom-rendering/Containerfile b/dotcom-rendering/Containerfile deleted file mode 100644 index b068323d4d4..00000000000 --- a/dotcom-rendering/Containerfile +++ /dev/null @@ -1,15 +0,0 @@ -# This container is used in our CICD pipelines for running E2E and regression tests. -# Keep the Node version in sync with `.nvmrc` -FROM node:24 - -WORKDIR /opt/app/dotcom-rendering/dotcom-rendering - -# Expects the file layout created by `make riffraff-bundle` -COPY ./dotcom-rendering/target /opt/app/dotcom-rendering/dotcom-rendering - -EXPOSE 9000 - -ENV DISABLE_LOGGING_AND_METRICS=true -ENV NODE_ENV=production - -ENTRYPOINT ["node", "article-rendering/dist/server.js"] diff --git a/dotcom-rendering/makefile b/dotcom-rendering/makefile index fedba8c0d90..9efdaef539c 100644 --- a/dotcom-rendering/makefile +++ b/dotcom-rendering/makefile @@ -25,7 +25,7 @@ cdk-synth: cdk-diff: @pnpm cdk diff --path-metadata false --version-reporting false --profile frontend -riffraff-bundle: clean-dist build cdk-synth +riffraff-bundle: $(call log, "creating riffraff bundle") @node ./scripts/deploy/build-riffraff-bundle.mjs diff --git a/dotcom-rendering/scripts/check-node-versions.mjs b/dotcom-rendering/scripts/check-node-versions.mjs index 7ef57e2d98f..3520b61bed5 100644 --- a/dotcom-rendering/scripts/check-node-versions.mjs +++ b/dotcom-rendering/scripts/check-node-versions.mjs @@ -39,11 +39,6 @@ const requiredNodeVersionMatches = pattern: /^FROM dhi\.io\/node:(\d+)/m, matchLevel: 'major', }, - { - filepath: 'Containerfile', - pattern: /^FROM node:(\d+)/m, - matchLevel: 'major', - }, { filepath: 'scripts/deploy/riff-raff.yaml', pattern: /^ +Recipe: dotcom-rendering.*-node-(\d+).*?$/m, diff --git a/dotcom-rendering/src/server/prout.ts b/dotcom-rendering/src/server/prout.ts index 7101edc50c0..40dac9386cd 100644 --- a/dotcom-rendering/src/server/prout.ts +++ b/dotcom-rendering/src/server/prout.ts @@ -1,2 +1,2 @@ -// this should get overwritten in CI (see .github/workflows/container.yml) +// this should get overwritten in CI (see .github/workflows/container-production.yml) export const GIT_COMMIT_HASH = 'LOCAL';