Merge branch 'master' into docs/smtp-bind-fix-snippet-titles

This commit is contained in:
Brennan Kinney 2024-11-20 16:38:08 +13:00 committed by GitHub
commit 884bb90b7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 139 additions and 102 deletions

View File

@ -1,140 +1,166 @@
name: 'Documentation (run)' name: 'Documentation (Deploy)'
on: on:
# This workflow runs off the primary branch which provides access to the `secrets` context:
workflow_run: workflow_run:
workflows: ['Documentation (PR)'] workflows: ['Documentation (PR)']
types: types:
- completed - completed
# Note: If limiting concurrency is required for this workflow: permissions:
# 1. Add an additional job prior to `preview` to get the PR number make it an output. # Required by `actions/download-artifact`:
# 2. Assign that new job as a `needs` dependency for the `preview` job. actions: read
# It is still required for `preview` job to download the artifact so that it can access the preview build files. # 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
# This workflow runs off the primary branch and has access to secrets as expected.
jobs: jobs:
preview: # NOTE: This is handled as pre-requisite job to minimize the noise from acquiring these two outputs needed for `deploy-preview` ENV:
name: 'Deploy Preview' pr-context:
runs-on: ubuntu-22.04 name: 'Acquire PR Context'
# Requires a PR event triggered `docs-preview-prepare.yml` workflow run that was successful + ensure the head SHA belongs to an associated PR: runs-on: ubuntu-24.04
# NOTE: A multi-line `if` GHA expression must avoid wrapping with `${{ }}`, otherwise it is unintentionally parsed as a string: outputs:
# https://github.com/nikitastupin/pwnhub/blob/main/writings/if-condition.md PR_HEADSHA: ${{ steps.set-pr-context.outputs.head-sha }}
if: | PR_NUMBER: ${{ steps.set-pr-context.outputs.number }}
github.event.workflow_run.conclusion == 'success' if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }}
&& github.event.workflow_run.event == 'pull_request'
&& contains(github.event.workflow_run.pull_requests.*.head.sha, github.event.workflow_run.head_sha)
steps: steps:
- name: 'Get PR context'
id: set-pr-context
env:
# 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 `<owner-login>:`, 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: |
gh pr view --repo "${PR_TARGET_REPO}" "${PR_BRANCH}" \
--json 'number,headRefOid' \
--jq '"number=\(.number)\nhead-sha=\(.headRefOid)"' \
>> "${GITHUB_OUTPUT}"
# ======================== # deploy-preview:
# Restore workflow context # name: 'Deploy Preview'
# ======================== # runs-on: ubuntu-24.04
needs: [pr-context]
# Retrieve the build artifact uploaded from the `docs-preview-prepare.yml` workflow run (that triggered this deployment workflow): env:
- name: 'Download build artifact' # 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 uses: actions/download-artifact@v4
with: with:
name: preview-build 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 }} github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }} 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
- name: 'Get PR number'
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}"
# ==================== # # ==================== #
# Deploy preview build # # Deploy preview build #
# ==================== # # ==================== #
# Manage workflow deployment status. `enable-commit-status` from `nwtgck/actions-netlify` would handle this, # Manage workflow deployment status (Part 1/2):
# but presently does not work correctly via split workflow. It is useful in a split workflow as the 1st stage # NOTE:
# no longer indicates if the entire workflow/deployment was successful. # - `workflow_run` trigger does not appear on the PR/commit checks status, only the initial prepare workflow triggered.
- name: 'Commit Status: Set Workflow Status as Pending' # 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 uses: myrotvorets/set-commit-status-action@v2.0.1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
status: pending status: pending
# Should match `env.PR_HEADSHA` when triggered by `pull_request` event workflow, sha: ${{ env.PR_HEADSHA }}
# Avoids failure of ENV being unavailable if job fails early:
sha: ${{ github.event.workflow_run.head_sha }}
context: 'Deploy Preview (pull_request => workflow_run)' context: 'Deploy Preview (pull_request => workflow_run)'
- name: 'Send preview build to Netlify' - name: 'Send preview build to Netlify'
uses: nwtgck/actions-netlify@v3.0 uses: nwtgck/actions-netlify@v3.0
id: preview id: preview-netlify
timeout-minutes: 1 timeout-minutes: 1
env: env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} 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 }}
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} # Fail the job when the required Netlify credentials are missing from ENV:
# Fail the job early if credentials are missing / invalid:
fails-without-credentials: true fails-without-credentials: true
# Sets/creates the Netlify deploy URL prefix. # Set/create the Netlify deploy URL prefix:
# Uses the PR number for uniqueness: alias: ${{ env.PREVIEW_SITE_PREFIX }}
alias: ${{ env.NETLIFY_SITE_PREFIX }}
# Only publish the contents of the build output: # Only publish the contents of the build output:
publish-dir: ${{ env.BUILD_DIR }} publish-dir: ${{ env.BUILD_DIR }}
# Custom message for the deploy log on Netlify: # 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 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 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 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 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: # If a `netlify.toml` config is ever needed, enable this:
# netlify-config-path: ./docs/netlify.toml # 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 # 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 uses: marocchino/sticky-pull-request-comment@v2
with: with:
number: ${{ env.PR_NUMBER }} number: ${{ env.PR_NUMBER }}
header: preview-comment header: preview-comment
recreate: true recreate: true
message: | 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 }} 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 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() }} if: ${{ always() }}
# Custom status descriptions:
env: env:
DEPLOY_SUCCESS: Successfully deployed preview. DEPLOY_SUCCESS: Successfully deployed preview.
DEPLOY_FAILURE: Failed to deploy preview. DEPLOY_FAILURE: Failed to deploy preview.
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status == 'success' && 'success' || 'failure' }} status: ${{ job.status == 'success' && 'success' || 'failure' }}
sha: ${{ github.event.workflow_run.head_sha }} sha: ${{ env.PR_HEADSHA }}
context: 'Deploy Preview (pull_request => workflow_run)' context: 'Deploy Preview (pull_request => workflow_run)'
description: ${{ job.status == 'success' && env.DEPLOY_SUCCESS || env.DEPLOY_FAILURE }} description: ${{ job.status == 'success' && env.DEPLOY_SUCCESS || env.DEPLOY_FAILURE }}

View File

@ -7,59 +7,68 @@ on:
- '.github/workflows/scripts/docs/build-docs.sh' - '.github/workflows/scripts/docs/build-docs.sh'
- '.github/workflows/docs-preview-prepare.yml' - '.github/workflows/docs-preview-prepare.yml'
# If the workflow for a PR is triggered multiple times, previous existing runs will be canceled. # If this workflow is triggered while already running for the PR, cancel any earlier running instances:
# eg: Applying multiple suggestions from a review directly via the Github UI. # Instances of the 2nd phase of this workflow (via `workflow_run`) lack any concurrency limits due to added complexity.
# Instances of the 2nd phase of this workflow (via `workflow_run`) presently lack concurrency limits due to added complexity.
concurrency: concurrency:
group: deploypreview-pullrequest-${{ github.event.pull_request.number }} group: deploypreview-pullrequest-${{ github.event.pull_request.number }}
cancel-in-progress: true 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. # `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. # 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/ # See: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
permissions: permissions:
# Required by `actions/checkout` for git checkout:
contents: read contents: read
jobs: jobs:
prepare-preview: prepare-preview:
name: 'Build Preview' name: 'Build Preview'
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
env:
BUILD_DIR: docs/site
NETLIFY_SITE_PREFIX: pullrequest-${{ github.event.pull_request.number }}
NETLIFY_SITE_NAME: dms-doc-previews
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: 'Build with mkdocs-material via Docker' # ================== #
working-directory: docs # Build docs preview #
env: # ================== #
PREVIEW_URL: 'https://${NETLIFY_SITE_PREFIX}--${NETLIFY_SITE_NAME}.netlify.app/'
NETLIFY_BRANDING: '<a href="https://www.netlify.com/"><img alt="Deploys by Netlify" src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" style="float: right;"></a>'
run: |
# Adjust mkdocs.yml for preview build
sed -i "s|^site_url:.*|site_url: '${PREVIEW_URL}'|" mkdocs.yml
# Insert sponsor branding into page content (Provider OSS plan requirement): - name: 'Build with mkdocs-material via Docker'
# Upstream does not provide a nicer maintainable way to do this.. working-directory: docs/
# Prepends HTML to copyright text and then aligns to the right side. 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='<a href="https://www.netlify.com/"><img alt="Deploys by Netlify" src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" style="float: right;"></a>'
sed -i "s|^copyright: '|copyright: '${NETLIFY_BRANDING}|" mkdocs.yml 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 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 # # Volley over to secure workflow #
# ============================== # # ============================== #
# Minimize risk of upload failure by bundling files to a single compressed archive (tar + zstd). # Archives directory `path` into a ZIP file:
- name: 'Prepare artifact for transfer'
run: tar --zstd -cf artifact.tar.zst ${{ env.BUILD_DIR }}
- name: 'Upload artifact for workflow transfer' - name: 'Upload artifact for workflow transfer'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: preview-build name: preview-build
path: artifact.tar.zst path: ${{ env.BUILD_DIR }}
retention-days: 1 retention-days: 1

View File

@ -55,7 +55,7 @@ jobs:
provenance: false provenance: false
- name: 'Run the Anchore Grype scan action' - name: 'Run the Anchore Grype scan action'
uses: anchore/scan-action@v5.2.0 uses: anchore/scan-action@v5.2.1
id: scan id: scan
with: with:
image: mailserver-testing:ci image: mailserver-testing:ci

View File

@ -7,8 +7,9 @@ set -ex
# `build --strict` ensures the build fails when any warnings are omitted. # `build --strict` ensures the build fails when any warnings are omitted.
docker run \ docker run \
--rm \ --rm \
--quiet \
--user "$(id -u):$(id -g)" \ --user "$(id -u):$(id -g)" \
--volume "${PWD}:/docs" \ --volume "./:/docs" \
--name "build-docs" \ --name "build-docs" \
squidfunk/mkdocs-material:9.5 build --strict squidfunk/mkdocs-material:9.5 build --strict

View File

@ -59,6 +59,7 @@ All notable changes to this project will be documented in this file. The format
### CI ### CI
- Workflow for `CONTRIBUTORS.md` updates removed. `CONTRIBUTORS.md` file and dependencies removed. ([#4141](https://github.com/docker-mailserver/docker-mailserver/pull/4141)) - 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) ## [v14.0.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v14.0.0)