Skip to content

Commit a443083

Browse files
authored
feat: reusable workflows for module integration testing (#75)
1 parent f84b57e commit a443083

11 files changed

Lines changed: 1049 additions & 189 deletions
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Module Integration Build Workflow
2+
#
3+
# Summary:
4+
# Builds all modules referenced in known_good.json with Bazel and runs the
5+
# integration test script to validate module interoperability.
6+
#
7+
# What it does:
8+
# - Checks out the reference integration repository
9+
# - Updates score_modules.MODULE.bazel from the provided known_good.json
10+
# - Builds all referenced modules (via scripts/integration_test.sh and Bazel)
11+
# - Runs integration tests
12+
# - Uploads logs from _logs/ as artifact: bazel-build-logs-${{ inputs.config }}
13+
#
14+
# Inputs:
15+
# - known_good (string, required): JSON content used to pin module SHAs.
16+
# - config (string, optional, default: bl-x86_64-linux): Bazel config passed as
17+
# CONFIG to scripts/integration_test.sh.
18+
# - repo_runner_labels (string, optional): Runner label(s). Accepts either a
19+
# single label string (e.g., ubuntu-latest) or a JSON string representing a
20+
# label or an array of labels (e.g., "\"ubuntu-latest\"" or
21+
# "[\"self-hosted\",\"linux\",\"x64\"]").
22+
# - target_branch (string, optional, default: main): Ref/branch to checkout.
23+
#
24+
# Repository Variables:
25+
# - reference_integration_repo (optional): Repository to checkout (owner/repo).
26+
# Default: eclipse-score/reference_integration
27+
#
28+
# Secrets:
29+
# - REPO_READ_TOKEN (secret, optional): Token for private module access; falls
30+
# back to github.token when not provided.
31+
#
32+
# Runner selection:
33+
# - Priority: `inputs.repo_runner_labels` > 'ubuntu-latest'.
34+
# - `repo_runner_labels` can be provided as a single label string or as JSON
35+
# (string or array). When JSON is used, it is parsed via fromJSON().
36+
#
37+
# Usage:
38+
# This workflow is reusable and triggered via workflow_call from other workflows.
39+
# Example:
40+
# jobs:
41+
# integration:
42+
# uses: eclipse-score/reference_integration/.github/workflows/module-integration-build.yml@main
43+
# with:
44+
# known_good: |
45+
# { "modules": [] }
46+
# config: bl-x86_64-linux
47+
# repo_runner_labels: 'ubuntu-latest'
48+
# secrets:
49+
# REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN }}
50+
#
51+
name: Module Integration Build
52+
53+
on:
54+
workflow_call:
55+
secrets:
56+
REPO_READ_TOKEN:
57+
description: 'GitHub token with read access to the score modules. Defaults to github.token'
58+
required: false
59+
inputs:
60+
known_good:
61+
description: 'Content of the known_good.json file to use for the integration test.'
62+
required: true
63+
type: string
64+
config:
65+
description: 'Optional configuration for the integration test.'
66+
required: false
67+
type: string
68+
default: 'bl-x86_64-linux'
69+
repo_runner_labels:
70+
description: 'Runner label(s) for the job; single label or JSON string/array.'
71+
required: false
72+
type: string
73+
target_branch:
74+
description: 'Reference Integration repository ref to checkout.'
75+
required: false
76+
type: string
77+
default: 'main'
78+
79+
env:
80+
REFERENCE_INTEGRATION_REPO: ${{ vars.reference_integration_repo != '' && vars.reference_integration_repo || 'eclipse-score/reference_integration' }}
81+
82+
jobs:
83+
integration-test:
84+
name: Integration Test
85+
runs-on: ${{ inputs.repo_runner_labels != '' && (startsWith(inputs.repo_runner_labels, '[') && fromJSON(inputs.repo_runner_labels) || inputs.repo_runner_labels) || 'ubuntu-latest' }}
86+
steps:
87+
- name: Show disk space before build
88+
run: |
89+
echo 'Disk space before build:'
90+
df -h
91+
- name: Removing unneeded software
92+
run: |
93+
echo "Removing unneeded software... "
94+
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
95+
#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
96+
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
97+
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
98+
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
99+
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
100+
- name: Show disk space after cleanup
101+
run: |
102+
echo 'Disk space after cleanup:'
103+
df -h
104+
- name: Checkout repository
105+
uses: actions/checkout@v4.2.2
106+
with:
107+
repository: ${{ env.REFERENCE_INTEGRATION_REPO }}
108+
ref: ${{ inputs.target_branch || 'main' }}
109+
token: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
110+
- name: Setup Bazel
111+
uses: bazel-contrib/setup-bazel@0.15.0
112+
with:
113+
# Avoid downloading Bazel every time.
114+
bazelisk-cache: true
115+
# Store build cache per workflow.
116+
disk-cache: ${{ github.workflow }}
117+
# Share repository cache between workflows.
118+
repository-cache: true
119+
- name: Update known good commits
120+
run: |
121+
echo "::group::write known_good.json from input"
122+
# write the known_good.json from input
123+
cat > known_good.updated.json <<'EOF'
124+
${{ inputs.known_good }}
125+
EOF
126+
cat known_good.updated.json
127+
echo "::endgroup::"
128+
129+
echo "::group::update score_modules.MODULE.bazel"
130+
python3 tools/update_module_from_known_good.py --known known_good.updated.json
131+
cat score_modules.MODULE.bazel
132+
echo "::endgroup::"
133+
env:
134+
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
135+
- name: Bazel build targets
136+
run: |
137+
CONFIG="${{ inputs.config }}" scripts/integration_test.sh --known-good known_good.updated.json
138+
env:
139+
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
140+
- name: Show disk space after build
141+
if: always()
142+
run: |
143+
echo 'Disk space after build:'
144+
df -h
145+
- name: Upload logs artifact
146+
if: always()
147+
uses: actions/upload-artifact@v4
148+
with:
149+
name: bazel-build-logs-${{ inputs.config }}
150+
path: _logs/
151+
if-no-files-found: warn
152+
retention-days: 14
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# Module Smoke Test Workflow
2+
#
3+
# Summary:
4+
# Orchestrates a fast validation of a single module by producing an
5+
# updated known_good.json (optionally overriding one module to the current PR)
6+
# and then invoking the integration build workflow to compile and test.
7+
#
8+
# What it does:
9+
# - Checks out the reference integration repository
10+
# - Generates known_good.updated.json:
11+
# * If testing an external module PR: overrides `module_name` to the PR SHA
12+
# * If testing this repo: updates modules to latest branches
13+
# - Uploads known_good.updated.json as an artifact
14+
# - Calls the Module Integration Build workflow with a matrix of configs
15+
# - Publishes a summary to the GitHub Step Summary
16+
#
17+
# Inputs:
18+
# - repo_runner_labels (string, required, default: ubuntu-latest): Runner label.
19+
# - module_name (string, required): Module to override (e.g., score_baselibs).
20+
# - target_branch (string, required, default: main):
21+
# The ref to checkout via actions/checkout — can be a branch name, tag, or
22+
# commit SHA. This ensures the workflow uses the exact version of the
23+
# integration files you intend.
24+
#
25+
# Repository Variables:
26+
# - reference_integration_repo (optional): Repository providing integration
27+
# workflows and tools (format: owner/repo). Supports private forks.
28+
# Default: eclipse-score/reference_integration
29+
#
30+
# Secrets:
31+
# - REPO_READ_TOKEN (optional): Token for reading private repos; falls back to
32+
# github.token when not provided.
33+
#
34+
# Usage:
35+
# This workflow is reusable and triggered via workflow_call from other workflows.
36+
# Example:
37+
# jobs:
38+
# smoke:
39+
# uses: eclipse-score/reference_integration/.github/workflows/module-smoke-test.yml@main
40+
# with:
41+
# repo_runner_labels: ubuntu-latest
42+
# module_name: score_baselibs
43+
# target_branch: main
44+
# secrets:
45+
# REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN }}
46+
#
47+
# Note: Set the 'reference_integration_repo' repository variable to use a
48+
# private fork (e.g., my-org/reference_integration).
49+
#
50+
# Notes:
51+
# - Extend the matrix in `integration-test` to cover additional configs.
52+
53+
name: Module Smoke Test
54+
55+
on:
56+
workflow_call:
57+
inputs:
58+
repo_runner_labels:
59+
description: 'The runner tag to use for the job'
60+
required: true
61+
type: string
62+
default: 'ubuntu-latest'
63+
module_name:
64+
description: 'Name of the module to override (e.g., score_baselibs).'
65+
required: true
66+
type: string
67+
target_branch:
68+
description: 'Ref to checkout (branch, tag, or commit SHA).'
69+
required: true
70+
type: string
71+
default: 'main'
72+
secrets:
73+
REPO_READ_TOKEN:
74+
description: 'Token for reading repositories'
75+
required: false
76+
77+
env:
78+
REFERENCE_INTEGRATION_REPO: ${{ vars.reference_integration_repo != '' && vars.reference_integration_repo || 'eclipse-score/reference_integration' }}
79+
80+
jobs:
81+
preparation:
82+
name: Preparation
83+
runs-on: ubuntu-latest
84+
outputs:
85+
known_good_updated: ${{ steps.set_known_good.outputs.known_good_updated }}
86+
steps:
87+
- name: Checkout repository
88+
uses: actions/checkout@v4.2.2
89+
with:
90+
repository: ${{ env.REFERENCE_INTEGRATION_REPO }}
91+
ref: ${{ inputs.target_branch }}
92+
token: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
93+
- name: Create updated known_good.json with PR commit
94+
id: set_known_good
95+
run: |
96+
if [ "${{ github.repository }}" != "${{ env.REFERENCE_INTEGRATION_REPO }}" ]; then
97+
echo "Overriding ${{ inputs.module_name }} with current PR"
98+
python3 tools/override_known_good_repo.py \
99+
--known known_good.json \
100+
--output known_good.updated.json \
101+
--module-override ${{ inputs.module_name }}@${{ github.event.repository.clone_url }}@${{ github.sha }}
102+
else
103+
echo "Testing reference integration repository itself - updating to latest commits"
104+
echo "::group::get latest commits from module branches"
105+
python3 tools/update_module_latest.py --output known_good.updated.json
106+
cat known_good.updated.json
107+
echo "::endgroup::"
108+
fi
109+
110+
# Output the content as a JSON string
111+
echo "known_good_updated<<EOF" >> $GITHUB_OUTPUT
112+
cat known_good.updated.json >> $GITHUB_OUTPUT
113+
echo "EOF" >> $GITHUB_OUTPUT
114+
env:
115+
GITHUB_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
116+
- name: Show updated known_good.json
117+
run: |
118+
echo "Updated known_good.json:"
119+
cat known_good.updated.json
120+
- name: Upload updated known_good.json artifact
121+
uses: actions/upload-artifact@v4
122+
with:
123+
name: known_good.updated.json
124+
path: known_good.updated.json
125+
126+
docs:
127+
name: Generate Documentation
128+
runs-on: ubuntu-latest
129+
needs: preparation
130+
steps:
131+
- name: not implemented
132+
run: echo "Documentation generation not yet implemented here."
133+
134+
integration-test:
135+
name: Integration Testing (${{ matrix.config }})
136+
needs: preparation
137+
strategy:
138+
fail-fast: false
139+
matrix:
140+
config:
141+
- bl-x86_64-linux
142+
# Add more configs here as needed
143+
# - bl-aarch64-linux
144+
# - bl-x86_64-qnx
145+
uses: ./.github/workflows/reusable_integration-build.yml
146+
secrets:
147+
REPO_READ_TOKEN: ${{ secrets.REPO_READ_TOKEN != '' && secrets.REPO_READ_TOKEN || github.token }}
148+
with:
149+
known_good: ${{ needs.preparation.outputs.known_good_updated }}
150+
config: ${{ matrix.config }}
151+
repo_runner_labels: ${{ inputs.repo_runner_labels }}
152+
target_branch: ${{ inputs.target_branch }}
153+
154+
summary:
155+
name: Publish Summary
156+
runs-on: ubuntu-latest
157+
needs: [integration-test, docs]
158+
if: always()
159+
steps:
160+
# get all artefacts from integration-test job with name bazel-build-logs-*
161+
- name: Download Integration Test Artifacts
162+
uses: actions/download-artifact@v4
163+
with:
164+
pattern: bazel-build-logs-*
165+
path: _logs/integration_test_logs
166+
merge-multiple: true
167+
- name: Publish Integration Test Summary
168+
run: |
169+
{
170+
echo '## Overall Status'
171+
echo
172+
if [ "${{ needs.integration-test.result }}" == "success" ]; then
173+
echo '- Integration Test: ✅ **SUCCESS**'
174+
else
175+
echo '- Integration Test: ❌ **FAILURE**'
176+
fi
177+
178+
if [ "${{ needs.docs.result }}" == "success" ]; then
179+
echo '- Documentation Generation: ✅ **SUCCESS**'
180+
else
181+
echo '- Documentation Generation: ❌ **FAILURE**'
182+
fi
183+
184+
echo
185+
echo '---'
186+
echo
187+
echo '## Integration Test Summary'
188+
echo
189+
190+
# Process each build_summary.md file from different configs
191+
for summary_file in _logs/integration_test_logs/*/build_summary.md; do
192+
if [ -f "$summary_file" ]; then
193+
config_name=$(basename $(dirname "$summary_file"))
194+
echo "### Configuration: $config_name"
195+
echo
196+
cat "$summary_file"
197+
echo
198+
fi
199+
done
200+
201+
# If no summary files found, check direct path
202+
if [ -f _logs/integration_test_logs/build_summary.md ]; then
203+
cat _logs/integration_test_logs/build_summary.md
204+
echo
205+
fi
206+
} >> "$GITHUB_STEP_SUMMARY"

0 commit comments

Comments
 (0)