Skip to content

build

build #23102

Workflow file for this run

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 }}