Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions .github/workflows/reusable_integration-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Module Integration Build Workflow
#
# Summary:
# Builds all modules referenced in known_good.json with Bazel and runs the
# integration test script to validate module interoperability.
#
# What it does:
# - Checks out the reference integration repository
# - Updates score_modules.MODULE.bazel from the provided known_good.json
# - Builds all referenced modules (via scripts/integration_test.sh and Bazel)
# - Runs integration tests
# - Uploads logs from _logs/ as artifact: bazel-build-logs-${{ inputs.config }}
#
# Inputs:
# - known_good (string, required): JSON content used to pin module SHAs.
# - config (string, optional, default: bl-x86_64-linux): Bazel config passed as
# CONFIG to scripts/integration_test.sh.
# - repo_runner_labels (string, optional): Runner label(s). Accepts either a
# single label string (e.g., ubuntu-latest) or a JSON string representing a
# label or an array of labels (e.g., "\"ubuntu-latest\"" or
# "[\"self-hosted\",\"linux\",\"x64\"]").
# - target_branch (string, optional, default: main): Ref/branch to checkout.
#
# Repository Variables:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any idea from which repo this is used? The caller, this one, or reference_integration?

# - reference_integration_repo (optional): Repository to checkout (owner/repo).
# Default: eclipse-score/reference_integration
#
# Secrets:
# - REPO_READ_TOKEN (secret, optional): Token for private module access; falls
# back to github.token when not provided.
#
# Runner selection:
# - Priority: `inputs.repo_runner_labels` > 'ubuntu-latest'.
# - `repo_runner_labels` can be provided as a single label string or as JSON
# (string or array). When JSON is used, it is parsed via fromJSON().
#
# Usage:
# This workflow is reusable and triggered via workflow_call from other workflows.
# Example:
# jobs:
# integration:
# uses: eclipse-score/reference_integration/.github/workflows/module-integration-build.yml@main
# with:
# known_good: |
# { "modules": [] }
# config: bl-x86_64-linux
# repo_runner_labels: 'ubuntu-latest'
# secrets:
# REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN }}
#
name: Module Integration Build

on:
workflow_call:
secrets:
REPO_READ_TOKEN:
description: 'GitHub token with read access to the score modules. Defaults to github.token'
required: false
inputs:
known_good:
description: 'Content of the known_good.json file to use for the integration test.'
required: true
type: string
config:
description: 'Optional configuration for the integration test.'
required: false
type: string
default: 'bl-x86_64-linux'
repo_runner_labels:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the runner provided by the caller, or would it be better here in env?

description: 'Runner label(s) for the job; single label or JSON string/array.'
required: false
type: string
target_branch:
description: 'Reference Integration repository ref to checkout.'
required: false
type: string
default: 'main'

env:
REFERENCE_INTEGRATION_REPO: ${{ vars.reference_integration_repo != '' && vars.reference_integration_repo || 'eclipse-score/reference_integration' }}

jobs:
integration-test:
name: Integration Test
runs-on: ${{ inputs.repo_runner_labels != '' && (startsWith(inputs.repo_runner_labels, '[') && fromJSON(inputs.repo_runner_labels) || inputs.repo_runner_labels) || 'ubuntu-latest' }}
steps:
- name: Show disk space before build
run: |
echo 'Disk space before build:'
df -h
- name: Removing unneeded software
run: |
echo "Removing unneeded software... "
if [ -d /usr/share/dotnet ]; then echo "Removing dotnet..."; start=$(date +%s); sudo rm -rf /usr/share/dotnet; end=$(date +%s); echo "Duration: $((end-start))s"; fi
#if [ -d /usr/local/lib/android ]; then echo "Removing android..."; start=$(date +%s); sudo rm -rf /usr/local/lib/android; end=$(date +%s); echo "Duration: $((end-start))s"; fi
if [ -d /opt/ghc ]; then echo "Removing haskell (ghc)..."; start=$(date +%s); sudo rm -rf /opt/ghc; end=$(date +%s); echo "Duration: $((end-start))s"; fi
if [ -d /usr/local/.ghcup ]; then echo "Removing haskell (ghcup)..."; start=$(date +%s); sudo rm -rf /usr/local/.ghcup; end=$(date +%s); echo "Duration: $((end-start))s"; fi
if [ -d /usr/share/swift ]; then echo "Removing swift..."; start=$(date +%s); sudo rm -rf /usr/share/swift; end=$(date +%s); echo "Duration: $((end-start))s"; fi
if [ -d /usr/local/share/chromium ]; then echo "Removing chromium..."; start=$(date +%s); sudo rm -rf /usr/local/share/chromium; end=$(date +%s); echo "Duration: $((end-start))s"; fi
- name: Show disk space after cleanup
run: |
echo 'Disk space after cleanup:'
df -h
- name: Checkout repository
uses: actions/[email protected]
with:
repository: ${{ env.REFERENCE_INTEGRATION_REPO }}
ref: ${{ inputs.target_branch || 'main' }}
token: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
- name: Setup Bazel
uses: bazel-contrib/[email protected]
with:
# Avoid downloading Bazel every time.
bazelisk-cache: true
# Store build cache per workflow.
disk-cache: ${{ github.workflow }}
# Share repository cache between workflows.
repository-cache: true
- name: Update known good commits
run: |
echo "::group::write known_good.json from input"
# write the known_good.json from input
cat > known_good.updated.json <<'EOF'
${{ inputs.known_good }}
EOF
cat known_good.updated.json
echo "::endgroup::"

echo "::group::update score_modules.MODULE.bazel"
python3 tools/update_module_from_known_good.py --known known_good.updated.json
cat score_modules.MODULE.bazel
echo "::endgroup::"
env:
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
- name: Bazel build targets
run: |
CONFIG="${{ inputs.config }}" scripts/integration_test.sh --known-good known_good.updated.json
env:
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
- name: Show disk space after build
if: always()
run: |
echo 'Disk space after build:'
df -h
- name: Upload logs artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: bazel-build-logs-${{ inputs.config }}
path: _logs/
if-no-files-found: warn
retention-days: 14
206 changes: 206 additions & 0 deletions .github/workflows/reusable_smoke-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Module Smoke Test Workflow
#
# Summary:
# Orchestrates a fast validation of a single module by producing an
# updated known_good.json (optionally overriding one module to the current PR)
# and then invoking the integration build workflow to compile and test.
#
# What it does:
# - Checks out the reference integration repository
# - Generates known_good.updated.json:
# * If testing an external module PR: overrides `module_name` to the PR SHA
# * If testing this repo: updates modules to latest branches
# - Uploads known_good.updated.json as an artifact
# - Calls the Module Integration Build workflow with a matrix of configs
# - Publishes a summary to the GitHub Step Summary
#
# Inputs:
# - repo_runner_labels (string, required, default: ubuntu-latest): Runner label.
# - module_name (string, required): Module to override (e.g., score_baselibs).
# - target_branch (string, required, default: main):
# The ref to checkout via actions/checkout — can be a branch name, tag, or
# commit SHA. This ensures the workflow uses the exact version of the
# integration files you intend.
#
# Repository Variables:
# - reference_integration_repo (optional): Repository providing integration
# workflows and tools (format: owner/repo). Supports private forks.
# Default: eclipse-score/reference_integration
#
# Secrets:
# - REPO_READ_TOKEN (optional): Token for reading private repos; falls back to
# github.token when not provided.
#
# Usage:
# This workflow is reusable and triggered via workflow_call from other workflows.
# Example:
# jobs:
# smoke:
# uses: eclipse-score/reference_integration/.github/workflows/module-smoke-test.yml@main
# with:
# repo_runner_labels: ubuntu-latest
# module_name: score_baselibs
# target_branch: main
# secrets:
# REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN }}
#
# Note: Set the 'reference_integration_repo' repository variable to use a
# private fork (e.g., my-org/reference_integration).
#
# Notes:
# - Extend the matrix in `integration-test` to cover additional configs.

name: Module Smoke Test

on:
workflow_call:
inputs:
repo_runner_labels:
description: 'The runner tag to use for the job'
required: true
type: string
default: 'ubuntu-latest'
module_name:
description: 'Name of the module to override (e.g., score_baselibs).'
required: true
type: string
target_branch:
description: 'Ref to checkout (branch, tag, or commit SHA).'
required: true
type: string
default: 'main'
secrets:
REPO_READ_TOKEN:
description: 'Token for reading repositories'
required: false

env:
REFERENCE_INTEGRATION_REPO: ${{ vars.reference_integration_repo != '' && vars.reference_integration_repo || 'eclipse-score/reference_integration' }}

jobs:
preparation:
name: Preparation
runs-on: ubuntu-latest
outputs:
known_good_updated: ${{ steps.set_known_good.outputs.known_good_updated }}
steps:
- name: Checkout repository
uses: actions/[email protected]
with:
repository: ${{ env.REFERENCE_INTEGRATION_REPO }}
ref: ${{ inputs.target_branch }}
token: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
- name: Create updated known_good.json with PR commit
id: set_known_good
run: |
if [ "${{ github.repository }}" != "${{ env.REFERENCE_INTEGRATION_REPO }}" ]; then
echo "Overriding ${{ inputs.module_name }} with current PR"
python3 tools/override_known_good_repo.py \
--known known_good.json \
--output known_good.updated.json \
--module-override ${{ inputs.module_name }}@${{ github.event.repository.clone_url }}@${{ github.sha }}
else
echo "Testing reference integration repository itself - updating to latest commits"
echo "::group::get latest commits from module branches"
python3 tools/update_module_latest.py --output known_good.updated.json
cat known_good.updated.json
echo "::endgroup::"
fi

# Output the content as a JSON string
echo "known_good_updated<<EOF" >> $GITHUB_OUTPUT
cat known_good.updated.json >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
Comment on lines +110 to +113
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using multiline output for potentially large JSON content could hit GitHub Actions output size limits for large known_good.json files. Consider using artifacts exclusively for passing this data between jobs instead of job outputs, as artifacts are already being uploaded at line 120-123.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can live with both solutions. @AlexanderLanin what is your opinion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Artifacts between actions is most likely best as that could also enable you (depending on how it's set up) to download them and see what is going wrong.
At least I think that is an option then.

env:
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
- name: Show updated known_good.json
run: |
echo "Updated known_good.json:"
cat known_good.updated.json
- name: Upload updated known_good.json artifact
uses: actions/upload-artifact@v4
with:
name: known_good.updated.json
path: known_good.updated.json

docs:
name: Generate Documentation
runs-on: ubuntu-latest
needs: preparation
steps:
- name: not implemented
run: echo "Documentation generation not yet implemented here."

integration-test:
name: Integration Testing (${{ matrix.config }})
needs: preparation
strategy:
fail-fast: false
matrix:
config:
- bl-x86_64-linux
# Add more configs here as needed
# - bl-aarch64-linux
# - bl-x86_64-qnx
uses: ./.github/workflows/reusable_integration-build.yml
secrets:
REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
with:
known_good: ${{ needs.preparation.outputs.known_good_updated }}
config: ${{ matrix.config }}
repo_runner_labels: ${{ inputs.repo_runner_labels }}
target_branch: ${{ inputs.target_branch }}

summary:
name: Publish Summary
runs-on: ubuntu-latest
needs: [integration-test, docs]
if: always()
steps:
# get all artefacts from integration-test job with name bazel-build-logs-*
- name: Download Integration Test Artifacts
uses: actions/download-artifact@v4
with:
pattern: bazel-build-logs-*
path: _logs/integration_test_logs
merge-multiple: true
- name: Publish Integration Test Summary
run: |
{
echo '## Overall Status'
echo
if [ "${{ needs.integration-test.result }}" == "success" ]; then
echo '- Integration Test: ✅ **SUCCESS**'
else
echo '- Integration Test: ❌ **FAILURE**'
fi

if [ "${{ needs.docs.result }}" == "success" ]; then
echo '- Documentation Generation: ✅ **SUCCESS**'
else
echo '- Documentation Generation: ❌ **FAILURE**'
fi

echo
echo '---'
echo
echo '## Integration Test Summary'
echo

# Process each build_summary.md file from different configs
for summary_file in _logs/integration_test_logs/*/build_summary.md; do
if [ -f "$summary_file" ]; then
config_name=$(basename $(dirname "$summary_file"))
echo "### Configuration: $config_name"
echo
cat "$summary_file"
echo
fi
done

# If no summary files found, check direct path
if [ -f _logs/integration_test_logs/build_summary.md ]; then
cat _logs/integration_test_logs/build_summary.md
echo
fi
} >> "$GITHUB_STEP_SUMMARY"
Loading
Loading