Build HOTFIX-ORG-434 #602
This file contains hidden or 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: CI-BUILD | |
description: "Continuous Integration workflow for building, the project." | |
run-name: Build ${{ github.ref_name }} | |
# | |
# Jobs included: | |
# - BUILD: Ensures the project compiles correctly | |
# - BOOTSTRAP: Tests installation across Python versions and locales | |
# | |
# Required Secrets: | |
# NONE | |
on: # yamllint disable-line rule:truthy | |
push: | |
branches: ["**"] # matches any branch | |
tags: ["v*"] | |
# Declare default permissions as none. | |
permissions: {} | |
env: | |
ENVIRONMENT: ${{ (github.ref == 'refs/heads/stable' || startsWith(github.ref, 'refs/tags/v')) && 'Deployment' || (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/feature') || startsWith(github.ref, 'refs/heads/patch-') || startsWith(github.ref, 'refs/tags/v')) && 'Testing' || 'Experimenting' }} | |
# Define Python versions at the top level -- Expected format: X.Y (e.g., 3.13) | |
PYTHON_DEFAULT: "${{ vars.PYTHON_DEFAULT }}" | |
PYTHON_OLD_MIN: "${{ vars.PYTHON_OLD_MIN }}" # For Oldest Python versions | |
PYTHON_EXPERIMENTAL: "${{ vars.PYTHON_EXPERIMENTAL }}" # For future Python versions | |
jobs: | |
BUILD: | |
permissions: | |
actions: read | |
contents: read | |
statuses: write | |
packages: none | |
pull-requests: read | |
security-events: none | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
runs-on: ubuntu-latest | |
environment: ${{ (github.ref == 'refs/heads/stable' || startsWith(github.ref, 'refs/tags/v')) && 'Deployment' || (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/feature') || startsWith(github.ref, 'refs/heads/patch-') || startsWith(github.ref, 'refs/tags/v')) && 'Testing' || 'Experimenting' }} | |
defaults: | |
run: | |
shell: bash | |
env: | |
LANG: "en_US.UTF-8" | |
BUILD_MATCH_PATTERN: "${{ vars.BUILD_MATCH_PATTERN }}" | |
outputs: | |
build_status: ${{ steps.build.outcome }} | |
artifact-id: ${{ steps.upload.outputs.artifact-id }} | |
artifact-url: ${{ steps.upload.outputs.artifact-url }} | |
artifact-digest: ${{ steps.upload.outputs.artifact-digest }} | |
artifact-files: ${{ steps.buildfiles.outputs.files }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
persist-credentials: false | |
- id: build-python | |
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
with: | |
python-version: "${{ vars.PYTHON_DEFAULT }}" | |
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 | |
with: | |
path: ~/.cache/pip | |
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} | |
restore-keys: | | |
${{ runner.os }}-pip- | |
- name: Pre-Clean | |
id: clean | |
run: make -j1 -f Makefile purge 2>/dev/null || true | |
- name: "License" | |
id: show-build-license | |
shell: bash | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
run: | | |
if [[ -r LICENSE.md ]] ; then | |
printf "\n\n" | |
cat <LICENSE.md ; | |
printf "\n\n" | |
else | |
printf "%s\n" "::warning title=UNLICENSED:: This is an UNLICENSED Build" | |
fi | |
- name: Test Build | |
id: build | |
run: make -j1 -f Makefile build | |
- name: Get BUILD Files | |
id: buildfiles | |
shell: bash | |
run: | | |
FILES=$(git ls-files -oi --exclude-standard -- ${{ env.BUILD_MATCH_PATTERN }} ) | |
if [ -z "$FILES" ]; then | |
printf "%s\n" "::warning file=.github/workflows/CI-BUILD.yml:: No Built files found." | |
printf "%s\n" "files=" >> "$GITHUB_OUTPUT" | |
else | |
printf "%s\n" "Built files found:" | |
printf "%s\n" "$FILES" | |
# Replace line breaks with commas for GitHub Action Output | |
FILES="${FILES//$'\n'/ }" | |
printf "%s\n" "files=$FILES" >> "$GITHUB_OUTPUT" | |
fi | |
if: ${{ success() }} | |
- name: "Hint for pip hashing" | |
id: build-pip-hash-hint | |
shell: bash | |
if: ${{ !cancelled() }} | |
run: | | |
for build_file in ${{ steps.buildfiles.outputs.files }} ; do | |
${{ steps.build-python.outputs.python-path }} -m pip hash --algorithm sha512 ${build_file} ; | |
done | |
- name: Upload build artifact | |
id: upload | |
if: ${{ !cancelled() && (steps.buildfiles.outputs.files != '') && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
with: | |
path: dist | |
name: multicast-build-${{ github.sha }} | |
compression-level: 3 | |
overwrite: true | |
BOOTSTRAP: | |
permissions: | |
actions: read | |
contents: read | |
statuses: write | |
packages: none | |
pull-requests: read | |
security-events: none | |
if: ${{ (github.repository == 'reactive-firewall-org/multicast') && !cancelled() }} | |
needs: BUILD | |
runs-on: ubuntu-latest | |
defaults: | |
run: | |
shell: bash | |
timeout-minutes: 5 | |
continue-on-error: ${{ matrix.experimental }} | |
strategy: | |
fail-fast: false | |
matrix: | |
python-version: ["${{ vars.PYTHON_OLD_MIN }}", "${{ vars.PYTHON_DEFAULT }}", "${{ vars.PYTHON_EXPERIMENTAL }}"] | |
lang-var: ["de.utf-8", "jp.utf-8"] | |
experimental: [true] | |
include: | |
- python-version: "${{ vars.PYTHON_DEFAULT }}" | |
lang-var: "de.utf-8" | |
experimental: false | |
- python-version: "${{ vars.PYTHON_DEFAULT }}" | |
lang-var: "jp.utf-8" | |
experimental: false | |
- python-version: "${{ vars.PYTHON_OLD_MIN }}" | |
lang-var: "en_US.utf-8" | |
experimental: false | |
- python-version: "${{ vars.PYTHON_OLD_EXTRA }}" | |
lang-var: "en_US.utf-8" | |
experimental: false | |
- python-version: "${{ vars.PYTHON_DEFAULT }}" | |
lang-var: "en_US.utf-8" | |
experimental: false | |
- python-version: "${{ vars.PYTHON_EXPERIMENTAL }}" | |
lang-var: "en_US.utf-8" | |
experimental: ${{ (needs.BUILD.environment == 'Experimenting') }} | |
outputs: | |
bootstrap_status: ${{ steps.bootstrap.outcome }} | |
env: | |
PYTHON_VERSION: ${{ matrix.python-version }} | |
LANG: ${{ matrix.lang-var }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
with: | |
persist-credentials: false | |
- name: Set up Python | |
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
with: | |
python-version: ${{ matrix.python-version }} | |
- name: Pre-build | |
id: bootstrap | |
run: | | |
printf "%s\n" "::group::make-init" | |
make -f Makefile init || exit 1 | |
printf "%s\n%s\n" "::endgroup::" "::group::make-clean" | |
make -j1 -f Makefile clean || true ; | |
printf "%s\n%s\n" "::endgroup::" "::group::make-build" | |
make -j1 -f Makefile build || exit 1 ; | |
printf "%s\n" "::endgroup::" | |
shell: bash | |
- name: Summerize Building | |
id: sumerize-py-build | |
run: | | |
printf "%s\n" "- [x] Building works on python version ${{ matrix.python-version }}" >> "$GITHUB_STEP_SUMMARY" | |
if: ${{ success() }} | |
shell: bash | |
- name: Run Tests | |
id: test-user-install | |
run: make -j1 -f Makefile user-install ; | |
shell: bash | |
- name: Summerize Install | |
id: sumerize-user-install | |
run: | | |
printf "%s\n" "- [x] User Installing works on python version ${{ matrix.python-version }}" >> "$GITHUB_STEP_SUMMARY" | |
if: ${{ success() }} | |
shell: bash | |
- name: Test Info | |
id: test-info | |
run: python -m multicast --version || true ; | |
- name: Post-Clean | |
id: post-bootstrap | |
run: | | |
make -j1 -f Makefile purge || true ; | |
make -j1 -f Makefile clean || true ; | |
if: ${{ always() }} | |
shell: bash | |
BUILD_ATTEST: | |
permissions: | |
actions: read | |
id-token: write | |
contents: read | |
attestations: write | |
needs: [BUILD] | |
runs-on: ubuntu-latest | |
environment: ${{ needs.BUILD.envs.ENVIRONMENT }} | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
outputs: | |
build-artifact-attestation-url: ${{ steps.multicast-build-attest.outputs.attestation-url }} | |
build-artifact-attestation-id: ${{ steps.multicast-build-attest.outputs.attestation-id }} | |
steps: | |
- name: Download All Artifacts | |
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
with: | |
path: ${{ github.workspace }}/dist | |
pattern: multicast-build-${{ github.sha }} | |
merge-multiple: true | |
- name: Calculate artifact digests | |
run: | | |
shasum -a 512 dist/* > build.checksums.txt | |
- name: "Attest Build Checksums" | |
id: multicast-build-chksum-attest | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') && (needs.BUILD.envs.ENVIRONMENT == 'Deployment' && startsWith(github.ref, 'refs/tags/v')) }} | |
uses: actions/attest-build-provenance@39cb715ce0ddd23df1f705e863f642bfb72dfb2b # v2.3.0 | |
with: | |
subject-checksums: build.checksums.txt | |
github-token: ${{ github.token }} | |
- name: "Attest Build Artifact" | |
id: multicast-build-attest | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: actions/attest-build-provenance@39cb715ce0ddd23df1f705e863f642bfb72dfb2b # v2.3.0 | |
with: | |
subject-name: multicast-build-${{ github.sha }} | |
subject-digest: sha256:${{ needs.BUILD.outputs.artifact-digest }} | |
github-token: ${{ github.token }} | |
show-summary: false | |
BUILD_STATUS: | |
permissions: | |
actions: read | |
contents: read | |
pull-requests: read | |
needs: [BUILD, BOOTSTRAP, BUILD_ATTEST] | |
runs-on: ubuntu-latest | |
environment: ${{ needs.BUILD.envs.ENVIRONMENT }} | |
if: ${{ !cancelled() }} | |
outputs: | |
didBUILD: ${{ steps.check_status.outputs.build_success }} | |
build_ref: ${{ steps.check_status.outputs.build_ref }} | |
build_ref_name: ${{ steps.check_status.outputs.build_ref_name }} | |
build-artifact-filename: ${{ steps.check_status.outputs.build_artifact_filename }} | |
build-artifact-id: ${{ needs.BUILD.outputs.artifact-id }} | |
build-artifact-url: ${{ needs.BUILD.outputs.artifact-url }} | |
build-artifact-digest: ${{ needs.BUILD.outputs.artifact-digest }} | |
build-artifact-attestation-url: ${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-url || '' }} | |
build-artifact-attestation-id: ${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-id || '' }} | |
environment: ${{ steps.check_status.outputs.build_environment }} | |
steps: | |
- id: check_status | |
run: | | |
if [[ "${{ needs.BUILD.result }}" == "success" && "${{ needs.BOOTSTRAP.result }}" == "success" ]]; then | |
printf "%s\n" "build_success=true" >> "$GITHUB_OUTPUT" | |
else | |
printf "%s\n" "build_success=false" >> "$GITHUB_OUTPUT" | |
fi | |
printf "%s\n" "build_url=${{ github.api_url }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_ref=${{ github.ref }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_sha=${{ github.sha }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_ref_name=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_artifact_filename=multicast-build-${{ github.sha }}.zip" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_artifact_url=${{ needs.BUILD.outputs.artifact-url }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_artifact_id=${{ needs.BUILD.outputs.artifact-id }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_artifact_digest=${{ needs.BUILD.outputs.artifact-digest }}" >> "$GITHUB_OUTPUT" | |
if [[ "${{ needs.BUILD_ATTEST.result }}" == "success" ]] ; then | |
printf "%s\n" "build-artifact-attestation-url=${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-url }}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build-artifact-attestation-id=${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-id }}" >> "$GITHUB_OUTPUT" | |
fi | |
printf "%s\n" "build_environment=${ENVIRONMENT}" >> "$GITHUB_OUTPUT" | |
printf "%s\n" "build_id=${{ github.run_id }}" >> "$GITHUB_OUTPUT" | |
cat <"$GITHUB_OUTPUT" >> "BUILD-info.txt" | |
- name: Download All Artifacts | |
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
with: | |
path: ${{ github.workspace }}/dist | |
pattern: multicast-build-${{ github.sha }} | |
merge-multiple: true | |
- name: Upload build summary | |
id: upload-build-info | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
with: | |
path: "BUILD-info.txt" | |
name: multicast-info-${{ github.sha }} | |
if-no-files-found: error | |
compression-level: 3 | |
retention-days: 2 | |
overwrite: true | |
- name: "Summarize Build" | |
id: summarize-build-success | |
env: | |
BUILD_ID: ${{ github.run_id }} | |
BUILD_SHA: ${{ github.sha }} | |
BUILD_ARTIFACT_FILES: ${{ needs.BUILD.outputs.artifact-files }} | |
BUILD_COMMENT_BODY: '${{ github.workspace }}/Build-Summary-Artifact.txt' | |
shell: bash | |
run: | | |
printf "%s\n\n" "# :building_construction: Build" > "${BUILD_COMMENT_BODY}" | |
printf "%s\n" ":ballot_box_with_check: BUILD \`${BUILD_ID}\` succeeded with commit [${BUILD_SHA}](https://github.com/reactive-firewall-org/multicast/commit/${BUILD_SHA})" >> "${BUILD_COMMENT_BODY}" | |
if [[ ( -d dist ) ]] ; then | |
for BLD_FILE in ${BUILD_ARTIFACT_FILES} ; do | |
printf "%s\n" " * :page_facing_up: Including building the file \`${BLD_FILE}\`" >> "${BUILD_COMMENT_BODY}" | |
done | |
printf "%s\n" " * :package: Including producing the build artifact [multicast-build-${BUILD_SHA}](https://github.com/reactive-firewall-org/multicast/actions/runs/${BUILD_ID}#artifacts)" >> "${BUILD_COMMENT_BODY}" | |
if [[ "${{ needs.BUILD_ATTEST.result }}" == "success" ]] ; then | |
printf "%s\n" " * :receipt: Build Attestation Created [\`${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-id }}\`](${{ needs.BUILD_ATTEST.outputs.build-artifact-attestation-url }})" >> "${BUILD_COMMENT_BODY}" | |
else | |
printf "%s\n" " * :no_entry_sign: Build Unattested" >> "${BUILD_COMMENT_BODY}" | |
fi | |
fi | |
cat <"${BUILD_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY" | |
if: ${{ success() && (github.repository == 'reactive-firewall-org/multicast') }} | |
- name: "Summarize Build (FAILED)" | |
id: summarize-build-failure | |
env: | |
BUILD_ID: ${{ github.run_id }} | |
BUILD_SHA: ${{ github.sha }} | |
BUILD_COMMENT_BODY: '${{ github.workspace }}/Build-Summary-Artifact.txt' | |
shell: bash | |
run: | | |
printf "%s\n" "# :construction: Build" > "${BUILD_COMMENT_BODY}" | |
printf "%s\n" ":x: ~BUILD \`${BUILD_ID}\` succeeded with commit [${BUILD_SHA}](https://github.com/reactive-firewall-org/multicast/commit/${BUILD_SHA})~" > "${BUILD_COMMENT_BODY}" | |
cat <"${BUILD_COMMENT_BODY}" >> "$GITHUB_STEP_SUMMARY" | |
if: ${{ failure() && (github.repository == 'reactive-firewall-org/multicast') }} | |
- name: Upload build summary | |
id: upload-build-summary | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
with: | |
path: ./Build-Summary-Artifact.txt | |
name: BUILD-COMMENT-BODY-${{ github.sha }} | |
if-no-files-found: error | |
compression-level: 3 | |
retention-days: 2 | |
overwrite: true | |
BUILD_SUMMARY: | |
permissions: | |
actions: read | |
contents: write | |
needs: [BUILD_STATUS] | |
runs-on: ubuntu-latest | |
environment: ${{ needs.BUILD_STATUS.outputs.environment }} | |
if: ${{ !cancelled() }} | |
steps: | |
- name: "Download Status Summary Artifact" | |
id: download-build-summary | |
if: ${{ !cancelled() && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
with: | |
name: BUILD-COMMENT-BODY-${{ github.sha }} | |
github-token: ${{ github.token }} | |
- name: "Build commit comment" | |
id: build-commit-comment | |
if: ${{ success() && (github.repository == 'reactive-firewall-org/multicast') }} | |
uses: peter-evans/commit-comment@5a6f8285b8f2e8376e41fe1b563db48e6cf78c09 # v3.0.0 | |
with: | |
sha: ${{ github.sha }} | |
token: ${{ github.token }} | |
body-path: '${{ steps.download-build-summary.outputs.download-path }}/Build-Summary-Artifact.txt' |