From d8df180f3845c5454b13bf578237d5df11678a69 Mon Sep 17 00:00:00 2001 From: Tim Dawborn Date: Wed, 26 Mar 2025 20:45:12 +1000 Subject: [PATCH] Initial WIP to test image building here. --- .../build-gha-docker-image/action.yaml | 58 +++ .github/workflows/test.yml | 331 ++++++++++-------- docker/github-actions/Dockerfile | 19 + docker/github-actions/main.sh | 1 + docker/github-actions/run-setup-fortran.sh | 17 + docker/github-actions/setup-fortran.sh | 1 + .../github-actions/update-job-environment.sh | 15 + 7 files changed, 292 insertions(+), 150 deletions(-) create mode 100644 .github/actions/build-gha-docker-image/action.yaml create mode 100644 docker/github-actions/Dockerfile create mode 120000 docker/github-actions/main.sh create mode 100755 docker/github-actions/run-setup-fortran.sh create mode 120000 docker/github-actions/setup-fortran.sh create mode 100755 docker/github-actions/update-job-environment.sh diff --git a/.github/actions/build-gha-docker-image/action.yaml b/.github/actions/build-gha-docker-image/action.yaml new file mode 100644 index 0000000..357d975 --- /dev/null +++ b/.github/actions/build-gha-docker-image/action.yaml @@ -0,0 +1,58 @@ +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions +# https://docs.github.com/en/actions/use-cases-and-examples/publishing-packages/publishing-docker-images#publishing-images-to-github-packages +name: 'Build docker image for use in GitHub Actions' +description: 'Builds a docker image for use in GitHub Actions for a given compiler and a given compiler version.' + +inputs: + compiler-name: + description: 'The Fortran compiler to install.' + required: true + compiler-version: + description: 'The compiler version to install.' + required: true + docker-registry-name: + description: 'The docker registry to publish to.' + default: 'ghcr.io' + docker-registry-username: + description: 'The username to login to the docker registry with.' + required: true + docker-registry-password: + description: 'The password to login to the docker registry with.' + required: true + image-name: + description: 'The name of the docker image.' + required: true + +runs: + using: 'composite' + steps: + - name: "Log in to the container registry" + uses: docker/login-action@v3 + with: + registry: ${{ inputs.docker-registry-name }} + username: ${{ inputs.docker-registry-username }} + password: ${{ inputs.docker-registry-password }} + + - name: "Extract metadata (tags, labels) for docker" + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.docker-registry-name }}/${{ inputs.image-name }} + tags: | + type=raw,value=linux-${{ inputs.compiler-name }}-${{ inputs.compiler-version }} + type=sha + type=ref,enable=true,priority=600,prefix=,suffix=,event=branch + type=ref,enable=true,priority=600,prefix=,suffix=,event=tag + type=ref,enable=true,priority=600,prefix=pr-,suffix=,event=pr + + - name: "Build and push docker image" + id: push + uses: docker/build-push-action@v6 + with: + context: docker/github-actions/ + build-args: | + COMPILER=${{ inputs.compiler-name }} + VERSION=${{ inputs.compiler-version }} + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4648aa1..e3a1bf1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,162 +54,193 @@ jobs: # debugging - name: Show matrix run: echo "${{ toJSON(fromJSON(steps.matrix.outputs.matrix)) }}" - - test: - name: Test - needs: options - runs-on: ${{ matrix.os }} - continue-on-error: ${{ needs.options.outputs.mode == 'report' }} - strategy: - fail-fast: false - matrix: ${{ fromJSON(needs.options.outputs.matrix) }} - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup Fortran - id: setup-fortran - continue-on-error: ${{ needs.options.outputs.mode == 'report' }} - uses: ./ - with: - compiler: ${{ matrix.toolchain.compiler }} - version: ${{ matrix.toolchain.version }} - - # - name: Debug with tmate - # uses: mxschmitt/action-tmate@v3 - - - name: Test Fortran compiler - if: steps.setup-fortran.outcome == 'success' - uses: ./.github/actions/test-fc - with: - compiler: ${{ matrix.toolchain.compiler }} - version: ${{ matrix.toolchain.version }} - - - name: Test C compiler - continue-on-error: true - if: needs.options.outputs.mode == 'report' && steps.setup-fortran.outcome == 'success' - uses: ./.github/actions/test-cc - with: - compiler: ${{ matrix.toolchain.compiler }} - version: ${{ matrix.toolchain.version }} - - - name: Test C++ compiler - continue-on-error: true - if: needs.options.outputs.mode == 'report' && steps.setup-fortran.outcome == 'success' - uses: ./.github/actions/test-cxx - with: - compiler: ${{ matrix.toolchain.compiler }} - version: ${{ matrix.toolchain.version }} - - name: Create compatibility report - if: needs.options.outputs.mode == 'report' - shell: bash - run: | - mkdir -p compat - support=$([ "${{ steps.setup-fortran.outcome }}" == "success" ] && echo "✓" || echo "") - prefix="${{ matrix.os }},${{ matrix.toolchain.compiler }},${{ matrix.toolchain.version }}" - report="compat/${prefix//,/_}.csv" - echo "$prefix,$support" >> "$report" - cat "$report" - - name: Upload compatibility report - if: needs.options.outputs.mode == 'report' - uses: actions/upload-artifact@v4 - with: - name: compat-${{ matrix.os }}-${{ matrix.toolchain.compiler }}-${{ matrix.toolchain.version }} - path: compat/*.csv - - compat: - name: Report compatibility - needs: - - options - - test - if: needs.options.outputs.mode == 'report' + build-and-push-docker-image: + name: 'Build and push docker image' runs-on: ubuntu-latest + timeout-minutes: 12 permissions: - contents: write - pull-requests: write + contents: read + packages: write + attestations: write + id-token: write + strategy: + fail-fast: false + matrix: + include: + - compiler-name: 'gcc' + compiler-version: '13' steps: - - - name: Checkout repository + - name: "Checkout repository" uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - - name: Install packages - run: pip install -r requirements.txt - - - name: Download reports - uses: actions/download-artifact@v4 - with: - pattern: compat-* - path: compat - merge-multiple: true - - - name: Concatenate reports - run: | - echo "runner,compiler,version,support" > .github/compat/long_compat.csv - cat compat/*.csv >> .github/compat/long_compat.csv - - - name: Make wide reports - working-directory: .github/compat - run: | - python wide_compat_reports.py "long_compat.csv" "compat.csv" - cat compat.md - - - name: Upload artifacts - uses: actions/upload-artifact@v4 + - name: 'Build and push docker image' + uses: ./.github/actions/build-gha-docker-image with: - name: compat - path: | - .github/compat/long_compat.csv - .github/compat/compat.csv - .github/compat/compat.md - - - name: Check for changes - working-directory: .github/compat - id: diff - run: | - if ! [ -f compat.csv ]; then - echo "diff=false" >> $GITHUB_OUTPUT - exit 0 - fi - - diff=$(git diff compat.csv) - if [[ $diff == "" ]]; then - echo "No changes found" - echo "diff=false" >> $GITHUB_OUTPUT - else - echo "Changes found:" - echo "$diff" - echo "diff=true" >> $GITHUB_OUTPUT - fi - - - name: Update README - if: ${{ steps.diff.outputs.diff == 'true' }} - run: python .github/compat/update_compat_table.py ".github/compat/compat.md" "README.md" - - - name: Print README diff - if: ${{ steps.diff.outputs.diff == 'true' }} - run: git diff README.md + compiler-name: ${{ matrix.compiler-name }} + compiler-version: ${{ matrix.compiler-version }} + docker-registry-name: 'ghcr.io' + docker-registry-username: ${{ github.actor }} + docker-registry-password: ${{ secrets.GITHUB_TOKEN }} + image-name: ${{ github.repository }} - - name: Create pull request - if: ${{ steps.diff.outputs.diff == 'true' }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - now=$(date +'%Y-%m-%dT%H-%M-%S') - updated_branch="compat_$now" - default_branch="${{ github.event.repository.default_branch }}" - - git switch -c "$updated_branch" - git add .github/compat/*compat.csv README.md - git commit -m "Update compatibility matrix" - git push -u origin "$updated_branch" - gh pr create -B "$default_branch" -H "$updated_branch" --title "Update compatibility matrix" --body-file .github/compat/compat.md + +# test: +# name: Test +# needs: options +# runs-on: ${{ matrix.os }} +# continue-on-error: ${{ needs.options.outputs.mode == 'report' }} +# strategy: +# fail-fast: false +# matrix: ${{ fromJSON(needs.options.outputs.matrix) }} +# steps: +# - name: Checkout repository +# uses: actions/checkout@v4 +# +# - name: Setup Fortran +# id: setup-fortran +# continue-on-error: ${{ needs.options.outputs.mode == 'report' }} +# uses: ./ +# with: +# compiler: ${{ matrix.toolchain.compiler }} +# version: ${{ matrix.toolchain.version }} +# +# # - name: Debug with tmate +# # uses: mxschmitt/action-tmate@v3 +# +# - name: Test Fortran compiler +# if: steps.setup-fortran.outcome == 'success' +# uses: ./.github/actions/test-fc +# with: +# compiler: ${{ matrix.toolchain.compiler }} +# version: ${{ matrix.toolchain.version }} +# +# - name: Test C compiler +# continue-on-error: true +# if: needs.options.outputs.mode == 'report' && steps.setup-fortran.outcome == 'success' +# uses: ./.github/actions/test-cc +# with: +# compiler: ${{ matrix.toolchain.compiler }} +# version: ${{ matrix.toolchain.version }} +# +# - name: Test C++ compiler +# continue-on-error: true +# if: needs.options.outputs.mode == 'report' && steps.setup-fortran.outcome == 'success' +# uses: ./.github/actions/test-cxx +# with: +# compiler: ${{ matrix.toolchain.compiler }} +# version: ${{ matrix.toolchain.version }} +# +# - name: Create compatibility report +# if: needs.options.outputs.mode == 'report' +# shell: bash +# run: | +# mkdir -p compat +# support=$([ "${{ steps.setup-fortran.outcome }}" == "success" ] && echo "✓" || echo "") +# prefix="${{ matrix.os }},${{ matrix.toolchain.compiler }},${{ matrix.toolchain.version }}" +# report="compat/${prefix//,/_}.csv" +# echo "$prefix,$support" >> "$report" +# cat "$report" +# +# - name: Upload compatibility report +# if: needs.options.outputs.mode == 'report' +# uses: actions/upload-artifact@v4 +# with: +# name: compat-${{ matrix.os }}-${{ matrix.toolchain.compiler }}-${{ matrix.toolchain.version }} +# path: compat/*.csv +# +# compat: +# name: Report compatibility +# needs: +# - options +# - test +# if: needs.options.outputs.mode == 'report' +# runs-on: ubuntu-latest +# permissions: +# contents: write +# pull-requests: write +# steps: +# +# - name: Checkout repository +# uses: actions/checkout@v4 +# +# - name: Setup Python +# uses: actions/setup-python@v4 +# with: +# python-version: 3.9 +# +# - name: Install packages +# run: pip install -r requirements.txt +# +# - name: Download reports +# uses: actions/download-artifact@v4 +# with: +# pattern: compat-* +# path: compat +# merge-multiple: true +# +# - name: Concatenate reports +# run: | +# echo "runner,compiler,version,support" > .github/compat/long_compat.csv +# cat compat/*.csv >> .github/compat/long_compat.csv +# +# - name: Make wide reports +# working-directory: .github/compat +# run: | +# python wide_compat_reports.py "long_compat.csv" "compat.csv" +# cat compat.md +# +# - name: Upload artifacts +# uses: actions/upload-artifact@v4 +# with: +# name: compat +# path: | +# .github/compat/long_compat.csv +# .github/compat/compat.csv +# .github/compat/compat.md +# +# - name: Check for changes +# working-directory: .github/compat +# id: diff +# run: | +# if ! [ -f compat.csv ]; then +# echo "diff=false" >> $GITHUB_OUTPUT +# exit 0 +# fi +# +# diff=$(git diff compat.csv) +# if [[ $diff == "" ]]; then +# echo "No changes found" +# echo "diff=false" >> $GITHUB_OUTPUT +# else +# echo "Changes found:" +# echo "$diff" +# echo "diff=true" >> $GITHUB_OUTPUT +# fi +# +# - name: Update README +# if: ${{ steps.diff.outputs.diff == 'true' }} +# run: python .github/compat/update_compat_table.py ".github/compat/compat.md" "README.md" +# +# - name: Print README diff +# if: ${{ steps.diff.outputs.diff == 'true' }} +# run: git diff README.md +# +# - name: Create pull request +# if: ${{ steps.diff.outputs.diff == 'true' }} +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +# run: | +# git config user.name "github-actions[bot]" +# git config user.email "41898282+github-actions[bot]@users.noreply.github.com" +# +# now=$(date +'%Y-%m-%dT%H-%M-%S') +# updated_branch="compat_$now" +# default_branch="${{ github.event.repository.default_branch }}" +# +# git switch -c "$updated_branch" +# git add .github/compat/*compat.csv README.md +# git commit -m "Update compatibility matrix" +# git push -u origin "$updated_branch" +# gh pr create -B "$default_branch" -H "$updated_branch" --title "Update compatibility matrix" --body-file .github/compat/compat.md diff --git a/docker/github-actions/Dockerfile b/docker/github-actions/Dockerfile new file mode 100644 index 0000000..4de2fa3 --- /dev/null +++ b/docker/github-actions/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:24.04 + +ARG COMPILER +ARG VERSION + +# Update dependencies. +RUN apt update && apt -y upgrade + +# Create a directory for the GITHUB_* files +RUN mkdir -p /etc/github-actions + +# Copy in the script for use when running this container, to populate the runtime environment. +COPY --chmod=755 ./update-job-environment.sh /etc/github-actions/update-job-environment.sh + +# Install the specified Fortran compiler. +COPY --follow-symlinks ./main.sh /tmp/main.sh +COPY --follow-symlinks ./setup-fortran.sh /tmp/setup-fortran.sh +COPY --chmod=755 ./run-setup-fortran.sh /tmp/run-setup-fortran.sh +RUN env GITHUB_ENV=/etc/github-actions/ENV GITHUB_PATH=/etc/github-actions/PATH /tmp/run-setup-fortran.sh diff --git a/docker/github-actions/main.sh b/docker/github-actions/main.sh new file mode 120000 index 0000000..f7a862b --- /dev/null +++ b/docker/github-actions/main.sh @@ -0,0 +1 @@ +../../main.sh \ No newline at end of file diff --git a/docker/github-actions/run-setup-fortran.sh b/docker/github-actions/run-setup-fortran.sh new file mode 100755 index 0000000..4e035ac --- /dev/null +++ b/docker/github-actions/run-setup-fortran.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +# Install necessary dependencies. +apt install -y make software-properties-common sudo + +# Run setup-fortran. +cd /tmp +source main.sh +cd - + +# Add the value of exported compiler environment variables to the set of environment variables to persist. +for v in FC CC CXX; do + if [ ! -z "${!v}" ]; then + echo "${v}=${!v}" >> ${GITHUB_ENV} + fi +done diff --git a/docker/github-actions/setup-fortran.sh b/docker/github-actions/setup-fortran.sh new file mode 120000 index 0000000..2765f1f --- /dev/null +++ b/docker/github-actions/setup-fortran.sh @@ -0,0 +1 @@ +../../setup-fortran.sh \ No newline at end of file diff --git a/docker/github-actions/update-job-environment.sh b/docker/github-actions/update-job-environment.sh new file mode 100755 index 0000000..63932b7 --- /dev/null +++ b/docker/github-actions/update-job-environment.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# This script is to be run within a GitHub Action job step, and is used to update the runtime +# environment variables based on environment variables setup during build time. +set -uex + +D=/etc/github-actions + +for v in ENV PATH; do + if [ -r ${D}/${v} ]; then + env_var=GITHUB_${v} + if env | grep -q "^${env_var}="; then + cat ${D}/${v} >> ${!env_var} + fi + fi +done