From a599936c4b5cfc81d00f7bc9d3c67ddff48f5f52 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Sun, 10 Nov 2024 18:57:31 +1300 Subject: [PATCH 1/4] ci: `docs-preview-deploy.yml` - Remove third job condition This condition was added as an additional guard but was preventing the workflow from running when PRs were from forked repos. --- .github/workflows/docs-preview-deploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index 02dc4183..e7ca9f12 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -22,7 +22,6 @@ jobs: if: | github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' - && contains(github.event.workflow_run.pull_requests.*.head.sha, github.event.workflow_run.head_sha) steps: # ======================== # From b960efad748dbf6fdfe7be2e864eca431296cbf5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:49:29 +1300 Subject: [PATCH 2/4] chore(deps): Bump anchore/scan-action from 5.2.0 to 5.2.1 (#4260) Bumps [anchore/scan-action](https://github.com/anchore/scan-action) from 5.2.0 to 5.2.1. - [Release notes](https://github.com/anchore/scan-action/releases) - [Changelog](https://github.com/anchore/scan-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/anchore/scan-action/compare/v5.2.0...v5.2.1) --- updated-dependencies: - dependency-name: anchore/scan-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/generic_vulnerability-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml index b96d8ea5..5b597d87 100644 --- a/.github/workflows/generic_vulnerability-scan.yml +++ b/.github/workflows/generic_vulnerability-scan.yml @@ -55,7 +55,7 @@ jobs: provenance: false - name: 'Run the Anchore Grype scan action' - uses: anchore/scan-action@v5.2.0 + uses: anchore/scan-action@v5.2.1 id: scan with: image: mailserver-testing:ci From 6b4627ceab44c65d04ae25926aab05956ca2bafb Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Fri, 15 Nov 2024 13:00:40 +1300 Subject: [PATCH 3/4] ci(docs-preview): Refactor workflows (#4262) **Overview of changes:** - Runner bumped from Ubuntu 22.04 => 24.04 - Revised inline documentation for maintainers. - The output of `build-docs.sh` is now grouped in the steps action log, and now hides the noise from pulling the image via `docker run`. - Removed the separate `tar` steps with ZSTD as there is only a directory to archive with recent changes to this workflow. The `upload` + `download` actions are sufficient. - The `workflow_run` job has had the PR context restore step extracted to a separate job to minimize noise. - `actions-netlify` is still effectively the same functionality. - `github-token` is no longer configured as it doesn't appear needed with the functions disabled. - Opt-out of the GH deployments feature which is not needed. --- .github/workflows/docs-preview-deploy.yml | 161 +++++++++++-------- .github/workflows/docs-preview-prepare.yml | 61 ++++--- .github/workflows/scripts/docs/build-docs.sh | 3 +- 3 files changed, 133 insertions(+), 92 deletions(-) diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index e7ca9f12..40b5cbd2 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -1,133 +1,164 @@ name: 'Documentation (run)' on: + # This workflow runs off the primary branch which provides access to the `secrets` context: workflow_run: workflows: ['Documentation (PR)'] types: - completed -# Note: If limiting concurrency is required for this workflow: -# 1. Add an additional job prior to `preview` to get the PR number make it an output. -# 2. Assign that new job as a `needs` dependency for the `preview` job. -# It is still required for `preview` job to download the artifact so that it can access the preview build files. +permissions: + # Required by `actions/download-artifact`: + actions: read + # Required by `marocchino/sticky-pull-request-comment`: + pull-requests: write + # Required by `myrotvorets/set-commit-status-action`: + statuses: write -# This workflow runs off the primary branch and has access to secrets as expected. jobs: - preview: - name: 'Deploy Preview' - runs-on: ubuntu-22.04 + # This could have been another step in the `deploy-preview` job and used `GITHUB_ENV` instead of `GITHUB_OUTPUT`. + # It was split out into a separate job for a cleaner overview of `deploy-preview` ENV inputs and to minimize noise + # from that job related to this workaround (_that is incompatible with PRs from forks_). + pr-context: + name: 'Restore PR Context' + runs-on: ubuntu-24.04 + outputs: + PR_HEADSHA: ${{ steps.set-pr-context.outputs.PR_HEADSHA }} + PR_NUMBER: ${{ steps.set-pr-context.outputs.PR_NUMBER }} # Requires a PR event triggered `docs-preview-prepare.yml` workflow run that was successful + ensure the head SHA belongs to an associated PR: - # NOTE: A multi-line `if` GHA expression must avoid wrapping with `${{ }}`, otherwise it is unintentionally parsed as a string: - # https://github.com/nikitastupin/pwnhub/blob/main/writings/if-condition.md + # NOTE: + # - The `contains` condition checks for event context that is not available when the PR is from a fork. An alternative method would be needed: + # https://stackoverflow.com/questions/59077079/how-to-get-pull-request-number-within-github-actions-workflow/79017997#79017997 + # - A multi-line `if` GHA expression must avoid wrapping with `${{ }}`, otherwise it is unintentionally parsed as a string: + # https://github.com/nikitastupin/pwnhub/blob/main/writings/if-condition.md if: | github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' + && contains(github.event.workflow_run.pull_requests.*.head.sha, github.event.workflow_run.head_sha) steps: - - # ======================== # - # Restore workflow context # - # ======================== # - - # Retrieve the build artifact uploaded from the `docs-preview-prepare.yml` workflow run (that triggered this deployment workflow): - - name: 'Download build artifact' - uses: actions/download-artifact@v4 - with: - name: preview-build - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - - - name: 'Extract build artifact' - run: tar -xf artifact.tar.zst - - # The `workflow_run` metadata contains an array of `pull_requests`, get the `workflow_run` equivalent of `github.event.pull_request.number`. - # There should only be one PR item in the array, verify that it shares the same `head_sha` (latest commit of PR). - # NOTE: Careful when using GHA context expressions that may have untrusted input here. The expressions are evaluated before the script content itself is run: - # https://github.com/docker-mailserver/docker-mailserver/pull/4247#discussion_r1827067475 + # NOTE: + # - The `workflow_run` metadata contains an array of `pull_requests`: + # 1. Take the `workflow_run` equivalent of `github.event.pull_request.number`. + # 2. There should only be one PR item in the array, verify that it shares the same `head_sha` (latest commit of PR). + # - Careful when using GHA context expressions that may have untrusted input here. The expressions are evaluated before the script content itself is run: + # https://github.com/docker-mailserver/docker-mailserver/pull/4247#discussion_r1827067475 - name: 'Get PR number' + id: set-pr-context env: head_sha: ${{ github.event.workflow_run.head_sha }} pull_requests: ${{ tojson(github.event.workflow_run.pull_requests) }} run: | PR_NUMBER=$(jq -r '[.[] | select(.head.sha == "${{ env.head_sha }}")][0].number' <<< "${pull_requests}") { - echo "PR_NUMBER=${PR_NUMBER}" echo 'PR_HEADSHA=${{ env.head_sha }}' - } >> "${GITHUB_ENV}" + echo "PR_NUMBER=${PR_NUMBER}" + } >> "${GITHUB_OUTPUT}" + + deploy-preview: + name: 'Deploy Preview' + runs-on: ubuntu-24.04 + needs: [pr-context] + env: + # NOTE: Keep this in sync with the equivalent ENV in `docs-preview-prepare.yml`: + BUILD_DIR: docs/site/ + # PR head SHA (latest commit): + PR_HEADSHA: ${{ needs.pr-context.outputs.PR_HEADSHA }} + PR_NUMBER: ${{ needs.pr-context.outputs.PR_NUMBER }} + # Deploy URL preview prefix (the site name for this prefix is managed at Netlify): + PREVIEW_SITE_PREFIX: pullrequest-${{ needs.pr-context.outputs.PR_NUMBER }} + steps: + - name: 'Retrieve and extract the built docs preview' + uses: actions/download-artifact@v4 + with: + name: preview-build + path: ${{ env.BUILD_DIR }} + # These are needed due this approach relying on `workflow_run`, so that it can access the build artifact: + # (uploaded from the associated `docs-preview-prepare.yml` workflow run) + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} # ==================== # # Deploy preview build # # ==================== # - # Manage workflow deployment status. `enable-commit-status` from `nwtgck/actions-netlify` would handle this, - # but presently does not work correctly via split workflow. It is useful in a split workflow as the 1st stage - # no longer indicates if the entire workflow/deployment was successful. - - name: 'Commit Status: Set Workflow Status as Pending' + # Manage workflow deployment status (Part 1/2): + # NOTE: + # - `workflow_run` trigger does not appear on the PR/commit checks status, only the initial prepare workflow triggered. + # This adds our own status check for this 2nd half of the workflow starting as `pending`, followed by `success` / `failure` at the end. + # - `enable-commit-status` from `nwtgck/actions-netlify` would have handled this, + # but the context `github.sha` that action tries to use references the primary branch commit that this workflow runs from, not the relevant PR commit. + - name: 'Commit Status (1/2) - Set Workflow Status as Pending' uses: myrotvorets/set-commit-status-action@v2.0.1 with: token: ${{ secrets.GITHUB_TOKEN }} status: pending - # Should match `env.PR_HEADSHA` when triggered by `pull_request` event workflow, - # Avoids failure of ENV being unavailable if job fails early: - sha: ${{ github.event.workflow_run.head_sha }} + sha: ${{ env.PR_HEADSHA }} context: 'Deploy Preview (pull_request => workflow_run)' - name: 'Send preview build to Netlify' uses: nwtgck/actions-netlify@v3.0 - id: preview + id: preview-netlify timeout-minutes: 1 env: NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} - NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} - # Keep these two ENV in sync with the `docs-preview-prepare.yml` workflow: - BUILD_DIR: docs/site - NETLIFY_SITE_PREFIX: pullrequest-${{ env.PR_NUMBER }} + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} with: - github-token: ${{ secrets.GITHUB_TOKEN }} - # Fail the job early if credentials are missing / invalid: + # Fail the job when the required Netlify credentials are missing from ENV: fails-without-credentials: true - # Sets/creates the Netlify deploy URL prefix. - # Uses the PR number for uniqueness: - alias: ${{ env.NETLIFY_SITE_PREFIX }} + # Set/create the Netlify deploy URL prefix: + alias: ${{ env.PREVIEW_SITE_PREFIX }} # Only publish the contents of the build output: publish-dir: ${{ env.BUILD_DIR }} # Custom message for the deploy log on Netlify: - deploy-message: 'Preview Build (PR #${{ env.PR_NUMBER }} @ commit: ${{ env.PR_HEADSHA }})' + deploy-message: 'Preview Build (PR #${{ env.PR_NUMBER }} @ commit: ${{ env.PR_HEADSHA }}' - # Note: Split workflow incorrectly references latest primary branch commit for deployment. - # Assign to non-default Deployment Environment for better management: - github-deployment-environment: documentation-previews - github-deployment-description: 'Preview deploy for documentation PRs' - - # Note - PR context used by this action is incorrect. These features are broken with split workflow: - # https://github.com/nwtgck/actions-netlify/issues/545 # Disable unwanted action defaults: - # Disable adding deploy comment on pre-merge commit (Github creates this for PR diff): + # This input does not fallback to the GITHUB_TOKEN taken from context, nor log that it will skip extra features of the action when this input is not set: + # https://github.com/nwtgck/actions-netlify/issues/1219 + # github-token: ${{ secrets.GITHUB_TOKEN }} + # NOTE: These features won't work correctly when the triggered workflow is not run from the PR branch due to assumed `pull_request` context: + # https://github.com/nwtgck/actions-netlify/issues/545 + # Disable adding a comment to the commit belonging to context `github.sha` about the successful deployment (redundant and often wrong commit): enable-commit-comment: false - # Disable adding a "Netlify - Netlify deployment" check status: + # Disable adding a "Netlify - Netlify deployment" PR check status (workflow job status is sufficient): enable-commit-status: false - # Disable. We provide a custom PR comment in the next action: + # Disable adding a comment about successful deployment status to the PR. + # Prefer `marocchino/sticky-pull-request-comment` instead (more flexible and allows custom message): enable-pull-request-comment: false + # Opt-out of deployment feature: + # NOTE: + # - When affected by `nwtgck/actions-netlify/issues/545`, the deployments published reference the wrong commit and thus information. + # - While the feature creates or assigns a deployment to associate the build with, it is unrelated to the related environments feature (secrets/vars): + # https://github.com/nwtgck/actions-netlify/issues/538#issuecomment-833983970 + # https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/viewing-deployment-history + # https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment + enable-github-deployment: false + # Assign to non-default Deployment Environment for better management: + # github-deployment-environment: documentation-previews + # github-deployment-description: 'Preview deploy for documentation PRs' # If a `netlify.toml` config is ever needed, enable this: # netlify-config-path: ./docs/netlify.toml - # If ever switching from Github Pages, enable this conditionally (false by default): + # If ever switching from Github Pages, enable this only when not deploying a preview build (false by default): # production-deploy: false - - name: 'Comment on PR: Add/Update deployment status' + - name: 'Comment on PR with preview link' uses: marocchino/sticky-pull-request-comment@v2 with: number: ${{ env.PR_NUMBER }} header: preview-comment recreate: true message: | - [Documentation preview for this PR](${{ steps.preview.outputs.deploy-url }}) is ready! :tada: + [Documentation preview for this PR](${{ steps.preview-netlify.outputs.deploy-url }}) is ready! :tada: Built with commit: ${{ env.PR_HEADSHA }} - - name: 'Commit Status: Update deployment status' + # Manage workflow deployment status (Part 2/2): + - name: 'Commit Status (2/2) - Update deployment status' uses: myrotvorets/set-commit-status-action@v2.0.1 - # Always run this step regardless of job failing early: + # Always run this step regardless of the job failing early: if: ${{ always() }} + # Custom status descriptions: env: DEPLOY_SUCCESS: Successfully deployed preview. DEPLOY_FAILURE: Failed to deploy preview. diff --git a/.github/workflows/docs-preview-prepare.yml b/.github/workflows/docs-preview-prepare.yml index bf7ad135..40b586e0 100644 --- a/.github/workflows/docs-preview-prepare.yml +++ b/.github/workflows/docs-preview-prepare.yml @@ -7,59 +7,68 @@ on: - '.github/workflows/scripts/docs/build-docs.sh' - '.github/workflows/docs-preview-prepare.yml' -# If the workflow for a PR is triggered multiple times, previous existing runs will be canceled. -# eg: Applying multiple suggestions from a review directly via the Github UI. -# Instances of the 2nd phase of this workflow (via `workflow_run`) presently lack concurrency limits due to added complexity. +# If this workflow is triggered while already running for the PR, cancel any earlier running instances: +# Instances of the 2nd phase of this workflow (via `workflow_run`) lack any concurrency limits due to added complexity. concurrency: group: deploypreview-pullrequest-${{ github.event.pull_request.number }} cancel-in-progress: true +env: + # Build output directory (created by the mkdocs-material container, keep this in sync with `build-docs.sh`): + BUILD_DIR: docs/site/ + # These two are only needed to construct `PREVIEW_URL`: + PREVIEW_SITE_NAME: dms-doc-previews + PREVIEW_SITE_PREFIX: pullrequest-${{ github.event.pull_request.number }} + # `pull_request` workflow is unreliable alone: Non-collaborator contributions lack access to secrets for security reasons. # A separate workflow (docs-preview-deploy.yml) handles the deploy after the potentially untrusted code is first run in this workflow. # See: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ permissions: + # Required by `actions/checkout` for git checkout: contents: read jobs: prepare-preview: name: 'Build Preview' - runs-on: ubuntu-22.04 - env: - BUILD_DIR: docs/site - NETLIFY_SITE_PREFIX: pullrequest-${{ github.event.pull_request.number }} - NETLIFY_SITE_NAME: dms-doc-previews + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - - name: 'Build with mkdocs-material via Docker' - working-directory: docs - env: - PREVIEW_URL: 'https://${NETLIFY_SITE_PREFIX}--${NETLIFY_SITE_NAME}.netlify.app/' - NETLIFY_BRANDING: 'Deploys by Netlify' - run: | - # Adjust mkdocs.yml for preview build - sed -i "s|^site_url:.*|site_url: '${PREVIEW_URL}'|" mkdocs.yml + # ================== # + # Build docs preview # + # ================== # - # Insert sponsor branding into page content (Provider OSS plan requirement): - # Upstream does not provide a nicer maintainable way to do this.. - # Prepends HTML to copyright text and then aligns to the right side. + - name: 'Build with mkdocs-material via Docker' + working-directory: docs/ + env: + PREVIEW_URL: 'https://${{ env.PREVIEW_SITE_PREFIX }}--${{ env.PREVIEW_SITE_NAME }}.netlify.app/' + run: | + # Adjust `mkdocs.yml` for the preview build requirements: + # - Replace production `site_url` with the preview URL (only affects the canonical link: https://en.wikipedia.org/wiki/Canonical_link_element#HTML) + # - Prepend Netlify logo link to `copyright` content + sed -i "s|^site_url:.*|site_url: '${{ env.PREVIEW_URL }}'|" mkdocs.yml + + # Insert branding into page content (Netlify OSS plan requirement): + # - `mkdocs-material` does not provide a better way to do this. + # - Prepends HTML to the copyright text and then aligns the logo to the right-side of the page. + NETLIFY_BRANDING='Deploys by Netlify' sed -i "s|^copyright: '|copyright: '${NETLIFY_BRANDING}|" mkdocs.yml - # Need to override a CSS media query for parent element to always be full width: + # Override a CSS media query for the parent element to always be full width: echo '.md-footer-copyright { width: 100%; }' >> content/assets/css/customizations.css - ../.github/workflows/scripts/docs/build-docs.sh + # Build and prepare for upload: + echo "::group::Build (stdout)" + bash ../.github/workflows/scripts/docs/build-docs.sh + echo "::endgroup::" # ============================== # # Volley over to secure workflow # # ============================== # - # Minimize risk of upload failure by bundling files to a single compressed archive (tar + zstd). - - name: 'Prepare artifact for transfer' - run: tar --zstd -cf artifact.tar.zst ${{ env.BUILD_DIR }} - + # Archives directory `path` into a ZIP file: - name: 'Upload artifact for workflow transfer' uses: actions/upload-artifact@v4 with: name: preview-build - path: artifact.tar.zst + path: ${{ env.BUILD_DIR }} retention-days: 1 diff --git a/.github/workflows/scripts/docs/build-docs.sh b/.github/workflows/scripts/docs/build-docs.sh index 5d1cab52..d4384b5e 100755 --- a/.github/workflows/scripts/docs/build-docs.sh +++ b/.github/workflows/scripts/docs/build-docs.sh @@ -7,8 +7,9 @@ set -ex # `build --strict` ensures the build fails when any warnings are omitted. docker run \ --rm \ + --quiet \ --user "$(id -u):$(id -g)" \ - --volume "${PWD}:/docs" \ + --volume "./:/docs" \ --name "build-docs" \ squidfunk/mkdocs-material:9.5 build --strict From 02f1894f74b629d74dbcb8faac2908c2e95c5237 Mon Sep 17 00:00:00 2001 From: Brennan Kinney <5098581+polarathene@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:37:34 +1300 Subject: [PATCH 4/4] ci(docs-preview): Acquire PR context via `gh` CLI (#4267) --- .github/workflows/docs-preview-deploy.yml | 62 +++++++++++------------ CHANGELOG.md | 1 + 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/.github/workflows/docs-preview-deploy.yml b/.github/workflows/docs-preview-deploy.yml index 40b5cbd2..ccb9c5f2 100644 --- a/.github/workflows/docs-preview-deploy.yml +++ b/.github/workflows/docs-preview-deploy.yml @@ -1,4 +1,4 @@ -name: 'Documentation (run)' +name: 'Documentation (Deploy)' on: # This workflow runs off the primary branch which provides access to the `secrets` context: @@ -10,49 +10,45 @@ on: permissions: # Required by `actions/download-artifact`: actions: read - # Required by `marocchino/sticky-pull-request-comment`: + # Required by `set-pr-context`: + contents: read + # Required by `marocchino/sticky-pull-request-comment` (write) + `set-pr-context` (read): pull-requests: write # Required by `myrotvorets/set-commit-status-action`: statuses: write jobs: - # This could have been another step in the `deploy-preview` job and used `GITHUB_ENV` instead of `GITHUB_OUTPUT`. - # It was split out into a separate job for a cleaner overview of `deploy-preview` ENV inputs and to minimize noise - # from that job related to this workaround (_that is incompatible with PRs from forks_). + # NOTE: This is handled as pre-requisite job to minimize the noise from acquiring these two outputs needed for `deploy-preview` ENV: pr-context: - name: 'Restore PR Context' + name: 'Acquire PR Context' runs-on: ubuntu-24.04 outputs: - PR_HEADSHA: ${{ steps.set-pr-context.outputs.PR_HEADSHA }} - PR_NUMBER: ${{ steps.set-pr-context.outputs.PR_NUMBER }} - # Requires a PR event triggered `docs-preview-prepare.yml` workflow run that was successful + ensure the head SHA belongs to an associated PR: - # NOTE: - # - The `contains` condition checks for event context that is not available when the PR is from a fork. An alternative method would be needed: - # https://stackoverflow.com/questions/59077079/how-to-get-pull-request-number-within-github-actions-workflow/79017997#79017997 - # - A multi-line `if` GHA expression must avoid wrapping with `${{ }}`, otherwise it is unintentionally parsed as a string: - # https://github.com/nikitastupin/pwnhub/blob/main/writings/if-condition.md - if: | - github.event.workflow_run.conclusion == 'success' - && github.event.workflow_run.event == 'pull_request' - && contains(github.event.workflow_run.pull_requests.*.head.sha, github.event.workflow_run.head_sha) + PR_HEADSHA: ${{ steps.set-pr-context.outputs.head-sha }} + PR_NUMBER: ${{ steps.set-pr-context.outputs.number }} + if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }} steps: - # NOTE: - # - The `workflow_run` metadata contains an array of `pull_requests`: - # 1. Take the `workflow_run` equivalent of `github.event.pull_request.number`. - # 2. There should only be one PR item in the array, verify that it shares the same `head_sha` (latest commit of PR). - # - Careful when using GHA context expressions that may have untrusted input here. The expressions are evaluated before the script content itself is run: - # https://github.com/docker-mailserver/docker-mailserver/pull/4247#discussion_r1827067475 - - name: 'Get PR number' + - name: 'Get PR context' id: set-pr-context env: - head_sha: ${{ github.event.workflow_run.head_sha }} - pull_requests: ${{ tojson(github.event.workflow_run.pull_requests) }} + # Token is required for the GH CLI: + GH_TOKEN: ${{ github.token }} + # Best practice for scripts is to reference via ENV at runtime. Avoid using GHA context expressions in the script content directly: + # https://github.com/docker-mailserver/docker-mailserver/pull/4247#discussion_r1827067475 + PR_TARGET_REPO: ${{ github.repository }} + # If the PR is from a fork, prefix it with `:`, otherwise only the PR branch name is relevant: + PR_BRANCH: |- + ${{ + (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) + && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) + || github.event.workflow_run.head_branch + }} + # Use the GH CLI to query the PR branch, which provides the PR number and head SHA to assign as outputs: + # (`--jq` formats JSON to `key=value` pairs and renames `headRefOid` to `head-sha`) run: | - PR_NUMBER=$(jq -r '[.[] | select(.head.sha == "${{ env.head_sha }}")][0].number' <<< "${pull_requests}") - { - echo 'PR_HEADSHA=${{ env.head_sha }}' - echo "PR_NUMBER=${PR_NUMBER}" - } >> "${GITHUB_OUTPUT}" + gh pr view --repo "${PR_TARGET_REPO}" "${PR_BRANCH}" \ + --json 'number,headRefOid' \ + --jq '"number=\(.number)\nhead-sha=\(.headRefOid)"' \ + >> "${GITHUB_OUTPUT}" deploy-preview: name: 'Deploy Preview' @@ -165,6 +161,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} status: ${{ job.status == 'success' && 'success' || 'failure' }} - sha: ${{ github.event.workflow_run.head_sha }} + sha: ${{ env.PR_HEADSHA }} context: 'Deploy Preview (pull_request => workflow_run)' description: ${{ job.status == 'success' && env.DEPLOY_SUCCESS || env.DEPLOY_FAILURE }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 28a97c32..0ba86566 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ All notable changes to this project will be documented in this file. The format ### CI - Workflow for `CONTRIBUTORS.md` updates removed. `CONTRIBUTORS.md` file and dependencies removed. ([#4141](https://github.com/docker-mailserver/docker-mailserver/pull/4141)) +- Refactored the workflows for generating documentation previews on PRs to be more secure ([#4267](https://github.com/docker-mailserver/docker-mailserver/pull/4267), [#4264](https://github.com/docker-mailserver/docker-mailserver/pull/4264), [#4262](https://github.com/docker-mailserver/docker-mailserver/pull/4262), [#4247](https://github.com/docker-mailserver/docker-mailserver/pull/4247), [#4244](https://github.com/docker-mailserver/docker-mailserver/pull/4244)) ## [v14.0.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v14.0.0)