build #23495
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: build | |
on: | |
schedule: | |
- cron: '*/30 * * * *' | |
issue_comment: | |
types: [created] | |
workflow_dispatch: | |
push: | |
paths: | |
- '.github/workflows/build.yml' | |
- 'docker/hugo/**' | |
concurrency: | |
group: "docker" | |
cancel-in-progress: false | |
env: | |
PLATFORMS: linux/amd64,linux/arm64 | |
IMAGE_OWNER: hugomods | |
IMAGE_NAME: hugo | |
BRANCH_NAME: ${{ github.head_ref || github.ref_name }} | |
jobs: | |
build-and-push-image: | |
strategy: | |
fail-fast: false | |
matrix: | |
version: ['', 'std-'] # empty string and `std-` represent extended and standard version of Hugo. | |
prefix: | |
- '' | |
- 'base-' | |
- 'ci-' | |
- 'dart-sass-' | |
- 'dart-sass-base-' | |
- 'dart-sass-git-' | |
- 'dart-sass-go-' | |
- 'dart-sass-go-git-' | |
- 'dart-sass-node-' | |
- 'dart-sass-node-git-' | |
- 'exts-' | |
- 'git-' | |
- 'go-' | |
- 'go-git-' | |
- 'node-' | |
- 'node-git-' | |
- 'node-lts-' | |
# Tags placeholders: | |
# 0: the image owner. | |
# 1: the image name. | |
# 2: the Hugo version without leading v. | |
# 3: standard (std-) or extended (empty string) indicator. | |
include: | |
# Set `extended` as true while building extended version of Hugo. | |
- version: '' | |
extended: true | |
- version: '' | |
prefix: '' | |
dockerfile: Dockerfile | |
tags: | | |
{0}/{1}:latest | |
{0}/{1}:{2} | |
ghcr.io/{0}/{1}:latest | |
ghcr.io/{0}/{1}:{2} | |
- version: 'std-' | |
prefix: '' | |
dockerfile: Dockerfile | |
tags: | | |
{0}/{1}:std | |
{0}/{1}:std-{2} | |
ghcr.io/{0}/{1}:std | |
ghcr.io/{0}/{1}:std-{2} | |
{0}/{1}:reg | |
{0}/{1}:reg-{2} | |
ghcr.io/{0}/{1}:reg | |
ghcr.io/{0}/{1}:reg-{2} | |
- prefix: base- | |
dockerfile: Dockerfile-base | |
tags: | | |
{0}/{1}:{3}base | |
{0}/{1}:{3}base-{2} | |
ghcr.io/{0}/{1}:{3}base | |
ghcr.io/{0}/{1}:{3}base-{2} | |
- prefix: ci- | |
dockerfile: Dockerfile-ci | |
tags: | | |
{0}/{1}:{3}ci | |
{0}/{1}:{3}ci-{2} | |
ghcr.io/{0}/{1}:{3}ci | |
ghcr.io/{0}/{1}:{3}ci-{2} | |
- prefix: dart-sass- | |
dockerfile: Dockerfile-dart-sass | |
tags: | | |
{0}/{1}:{3}dart-sass | |
{0}/{1}:{3}dart-sass-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass | |
ghcr.io/{0}/{1}:{3}dart-sass-{2} | |
- prefix: dart-sass-base- | |
dockerfile: Dockerfile-dart-sass-base | |
tags: | | |
{0}/{1}:{3}dart-sass-base | |
{0}/{1}:{3}dart-sass-base-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-base | |
ghcr.io/{0}/{1}:{3}dart-sass-base-{2} | |
- prefix: dart-sass-git- | |
dockerfile: Dockerfile-dart-sass-git | |
tags: | | |
{0}/{1}:{3}dart-sass-git | |
{0}/{1}:{3}dart-sass-git-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-git | |
ghcr.io/{0}/{1}:{3}dart-sass-git-{2} | |
- prefix: dart-sass-go- | |
dockerfile: Dockerfile-dart-sass-go | |
tags: | | |
{0}/{1}:{3}dart-sass-go | |
{0}/{1}:{3}dart-sass-go-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-go | |
ghcr.io/{0}/{1}:{3}dart-sass-go-{2} | |
- prefix: dart-sass-go-git- | |
dockerfile: Dockerfile-dart-sass-go-git | |
tags: | | |
{0}/{1}:{3}dart-sass-go-git | |
{0}/{1}:{3}dart-sass-go-git-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-go-git | |
ghcr.io/{0}/{1}:{3}dart-sass-go-git-{2} | |
- prefix: dart-sass-node- | |
dockerfile: Dockerfile-dart-sass-node | |
tags: | | |
{0}/{1}:{3}dart-sass-node | |
{0}/{1}:{3}dart-sass-node-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-node | |
ghcr.io/{0}/{1}:{3}dart-sass-node-{2} | |
- prefix: dart-sass-node-git- | |
dockerfile: Dockerfile-dart-sass-node-git | |
tags: | | |
{0}/{1}:{3}dart-sass-node-git | |
{0}/{1}:{3}dart-sass-node-git-{2} | |
ghcr.io/{0}/{1}:{3}dart-sass-node-git | |
ghcr.io/{0}/{1}:{3}dart-sass-node-git-{2} | |
- prefix: git- | |
dockerfile: Dockerfile-git | |
tags: | | |
{0}/{1}:{3}git | |
{0}/{1}:{3}git-{2} | |
ghcr.io/{0}/{1}:{3}git | |
ghcr.io/{0}/{1}:{3}git-{2} | |
- prefix: go- | |
dockerfile: Dockerfile-go | |
tags: | | |
{0}/{1}:{3}go | |
{0}/{1}:{3}go-{2} | |
ghcr.io/{0}/{1}:{3}go | |
ghcr.io/{0}/{1}:{3}go-{2} | |
- prefix: go-git- | |
dockerfile: Dockerfile-go-git | |
tags: | | |
{0}/{1}:{3}go-git | |
{0}/{1}:{3}go-git-{2} | |
ghcr.io/{0}/{1}:{3}go-git | |
ghcr.io/{0}/{1}:{3}go-git-{2} | |
- prefix: node- | |
dockerfile: Dockerfile-node | |
tags: | | |
{0}/{1}:{3}node | |
{0}/{1}:{3}node-{2} | |
ghcr.io/{0}/{1}:{3}node | |
ghcr.io/{0}/{1}:{3}node-{2} | |
- prefix: node-git- | |
dockerfile: Dockerfile-node-git | |
tags: | | |
{0}/{1}:{3}node-git | |
{0}/{1}:{3}node-git-{2} | |
ghcr.io/{0}/{1}:{3}node-git | |
ghcr.io/{0}/{1}:{3}node-git-{2} | |
- prefix: node-lts- | |
dockerfile: Dockerfile-node-lts | |
tags: | | |
{0}/{1}:{3}node-lts | |
{0}/{1}:{3}node-lts-{2} | |
ghcr.io/{0}/{1}:{3}node-lts | |
ghcr.io/{0}/{1}:{3}node-lts-{2} | |
- prefix: exts- | |
dockerfile: Dockerfile-exts | |
tags: | | |
{0}/{1}:{3}exts | |
{0}/{1}:{3}exts-{2} | |
ghcr.io/{0}/{1}:{3}exts | |
ghcr.io/{0}/{1}:{3}exts-{2} | |
runs-on: ubuntu-latest | |
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.issue.number == 3 }} | |
steps: | |
- name: Fetch latest Hugo release | |
id: release | |
uses: razonyang/github-action-github-latest-release@v1 | |
with: | |
owner: gohugoio | |
name: hugo | |
prefix: v | |
- name: Check if the image tag exists | |
if: steps.release.outputs.version | |
id: check-image-tag | |
uses: razonyang/github-action-docker-image-tag-exists@v1 | |
with: | |
owner: ${{ env.IMAGE_OWNER }} | |
name: ${{ env.IMAGE_NAME }} | |
tag: ${{ matrix.version }}${{ matrix.prefix }}${{ steps.release.outputs.version }} | |
# The `build` is `true` on when the image tag doesn't exist or the commit message contains the word `[build]`. | |
- id: needs-build | |
if: steps.release.outputs.version | |
name: Check if there is a need to build images. | |
run: | | |
if [[ ${{ steps.check-image-tag.outputs.exists }} == 0 || "${{ github.event.head_commit.message }}" == *"[build]"* ]]; \ | |
then echo "build=1"; \ | |
else echo "build=0"; \ | |
fi \ | |
>> $GITHUB_OUTPUT; | |
# Checkout the main repository. | |
- name: Checkout repository | |
if: steps.needs-build.outputs.build == true | |
uses: actions/checkout@v4 | |
# Checkout the Hugo repository for building. | |
- name: Checkout Hugo repository | |
if: steps.needs-build.outputs.build == true | |
uses: actions/checkout@v4 | |
with: | |
repository: gohugoio/hugo | |
ref: v${{ steps.release.outputs.version }} | |
path: ./docker/hugo/src | |
- name: Build meta | |
id: build_meta | |
if: steps.needs-build.outputs.build == true | |
run: | | |
echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT | |
cd ./docker/hugo/src && echo "hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
- name: LDFLAGS | |
id: ldflags | |
if: steps.needs-build.outputs.build == true | |
run: | | |
HASH='github.com/gohugoio/hugo/common/hugo.commitHash=${{ steps.build_meta.outputs.hash }}' | |
BUILD_DATE='github.com/gohugoio/hugo/common/hugo.buildDate=${{ steps.build_meta.outputs.date }}' | |
VENDOR='github.com/gohugoio/hugo/common/hugo.vendorInfo=hugomods' | |
echo "-X '$HASH' -X '$BUILD_DATE' -X '$VENDOR'" | |
echo "flags=-X '$HASH' -X '$BUILD_DATE' -X '$VENDOR'">> $GITHUB_OUTPUT | |
- name: Set up QEMU | |
if: steps.needs-build.outputs.build == true | |
uses: docker/setup-qemu-action@v3 | |
with: | |
platforms: ${{ env.PLATFORMS }} | |
- name: Set up Docker Buildx | |
if: steps.needs-build.outputs.build == true | |
uses: docker/setup-buildx-action@v3 | |
with: | |
platforms: ${{ env.PLATFORMS }} | |
- name: Build and export to Docker | |
if: steps.needs-build.outputs.build == true | |
uses: docker/build-push-action@v5 | |
with: | |
load: true | |
context: docker/hugo | |
file: docker/hugo/${{ matrix.dockerfile }} | |
tags: hugomods/hugo:test | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
build-args: | | |
LDFLAGS=${{ steps.ldflags.outputs.flags }} | |
HUGO_VERSION=v${{ steps.release.outputs.version }} | |
HUGO_EXTENDED=${{ matrix.extended }} | |
- id: hugo-version | |
name: Save Hugo version for subsequent tests. | |
if: steps.needs-build.outputs.build == true | |
run: echo "version=$(docker run --rm hugomods/hugo:test hugo version)" >> $GITHUB_OUTPUT | |
- name: Check Hugo version | |
if: steps.needs-build.outputs.build == true | |
run: | | |
if [[ "${{ steps.hugo-version.outputs.version }}" != *"v${{ steps.release.outputs.version }}"* ]]; | |
then | |
echo "Expected Hugo version "v${{ steps.release.outputs.version }}", but got "${{ steps.hugo-version.outputs.version }}"." && exit 1; | |
fi | |
- name: Check Hugo edition | |
if: steps.needs-build.outputs.build == true | |
run: | | |
if [[ "${{ matrix.version }}" == "std-" && "${{ steps.hugo-version.outputs.version }}" == *"extended"* ]]; | |
then | |
echo "Expected standard edition of Hugo, got "${{ steps.hugo-version.outputs.version }}"." && exit 1; | |
elif [[ "${{ matrix.version }}" == "" && "${{ steps.hugo-version.outputs.version }}" != *"extended"* ]] | |
then | |
echo "Expected extended edition of Hugo, got "${{ steps.hugo-version.outputs.version }}"." && exit 1; | |
fi | |
- name: Check Vendor Info | |
if: steps.needs-build.outputs.build == true | |
run: | | |
if [[ "${{ steps.hugo-version.outputs.version }}" != *"VendorInfo=hugomods"* ]]; | |
then | |
echo "Expected vendor "hugomods", got "${{ steps.hugo-version.outputs.version }}"." && exit 1; | |
fi | |
- name: Test site build | |
if: steps.needs-build.outputs.build == true | |
run: | | |
docker run --rm -v $PWD/site:/src hugomods/hugo:test hugo | |
env: | |
IMAGE_PREFIX: ${{ matrix.prefix }} | |
- name: Test Extra Markdown Handlers | |
if: steps.needs-build.outputs.build == true && | |
contains(fromJson('["ci-", "exts-"]'), matrix.prefix) | |
run: | | |
docker run --rm -v $PWD/site:/src hugomods/hugo:test hugo --config config.yaml,config-markdown-handlers.yaml | |
env: | |
IMAGE_PREFIX: ${{ matrix.prefix }} | |
- name: Check Git installation | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["", "ci-", "dart-sass-", "dart-sass-git-", "dart-sass-go-git-", "dart-sass-node-git-", "git-", "node-git-", "go-git-", "exts-"]'), matrix.prefix) | |
run: docker run --rm hugomods/hugo:test git version | |
- name: Test site build with --enableGitInfo | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["", "ci-", "dart-sass-", "dart-sass-git-", "dart-sass-go-git-", "dart-sass-node-git-", "git-", "node-git-", "go-git-", "exts-"]'), matrix.prefix) | |
run: >- | |
docker run --rm | |
-v $PWD/site:/src | |
hugomods/hugo:test | |
/bin/sh -c "git init && | |
git add -A && | |
git config --global user.email "support@hugomods.com" && | |
git config --global user.name "HugoMods" && | |
git commit -m 'Test commit' && | |
hugo --enableGitInfo" | |
- name: Check Hugo server alias | |
if: steps.needs-build.outputs.build == true | |
run: >- | |
HUGO_SERVER_OUTPUT=$(docker run --rm -v $PWD/site:/src hugomods/hugo:test sh -c "server > server.out & sleep 5 && cat server.out") && | |
echo $HUGO_SERVER_OUTPUT && | |
if [[ $HUGO_SERVER_OUTPUT != *"bind address 0.0.0.0"* ]]; then echo "Expected bind "0.0.0.0" by default." && exit 1; fi | |
env: | |
IMAGE_PREFIX: ${{ matrix.prefix }} | |
- name: Check Go installation | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["", "ci-", "dart-sass-", "dart-sass-go-", "dart-sass-go-git-", "go-", "go-git-", "exts-"]'), matrix.prefix) | |
run: docker run --rm hugomods/hugo:test go version | |
- name: Check Node.js, NPM and Yarn installation | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["", "ci-", "dart-sass-", "dart-sass-node-", "dart-sass-node-git-", "node-", "node-git-", "node-lts-", "exts-"]'), matrix.prefix) | |
run: docker run --rm hugomods/hugo:test node -v && npm version && yarn -v | |
- name: Check PostCSS, PurgeCSS, Autoprefixer and RTLCSS | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["ci-", "exts-"]'), matrix.prefix) | |
run: >- | |
docker run --rm | |
-v $PWD/tests/postcss:/src | |
hugomods/hugo:test | |
postcss ./main.css | |
- name: Check CI tools | |
if: | | |
steps.needs-build.outputs.build == true && | |
contains(fromJson('["ci-"]'), matrix.prefix) | |
run: >- | |
docker run --rm | |
hugomods/hugo:test | |
sh -c "curl --version && | |
jq --version && | |
htmlproofer -v" | |
- name: Login to Docker Hub | |
if: ${{ steps.needs-build.outputs.build == true && env.BRANCH_NAME == 'main' }} | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ env.IMAGE_OWNER }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Login to GitHub Container Registry | |
if: ${{ steps.needs-build.outputs.build == true && env.BRANCH_NAME == 'main' }} | |
uses: docker/login-action@v3 | |
with: | |
registry: ghcr.io | |
username: ${{ env.IMAGE_OWNER }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Build and push | |
if: ${{ steps.needs-build.outputs.build == true && env.BRANCH_NAME == 'main' }} | |
uses: docker/build-push-action@v5 | |
with: | |
push: true | |
context: docker/hugo | |
platforms: ${{ env.PLATFORMS }} | |
file: docker/hugo/${{ matrix.dockerfile }} | |
# Reserve reg* variants for backwards compatibility. | |
tags: > | |
${{ | |
(matrix.version == 'std-' && matrix.prefix != '') && | |
format( | |
'{0}{1}', | |
format(matrix.tags, env.IMAGE_OWNER, env.IMAGE_NAME, steps.release.outputs.version, matrix.version), | |
format(matrix.tags, env.IMAGE_OWNER, env.IMAGE_NAME, steps.release.outputs.version, 'reg-') | |
) || | |
format(matrix.tags, env.IMAGE_OWNER, env.IMAGE_NAME, steps.release.outputs.version, matrix.version) | |
}} | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
build-args: | | |
LDFLAGS=${{ steps.ldflags.outputs.flags }} | |
HUGO_VERSION=v${{ steps.release.outputs.version }} | |
HUGO_EXTENDED=${{ matrix.extended }} |