Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
93efa13
[ci] Auto-generate manifest-diff report from multi-arch CI on PR/push…
amd-hsivasun May 12, 2026
d9d724c
[docs] Document manifest-diff report tool and multi-arch CI integration
amd-hsivasun May 12, 2026
63eb988
[CI] Add --branch parameter into manifest-diff workflow
amd-hsivasun May 12, 2026
c327453
[Docs] Link manifest-diff doc to new issue created
amd-hsivasun May 12, 2026
ede586c
Merge branch 'main' into amd/hsivasun/bump-pr-blamelist
amd-hsivasun May 12, 2026
1d9f400
[CI] Move manifest_diff to multi_arch_ci.yml; convert manifest-diff.yml
amd-hsivasun May 14, 2026
04cb776
Merge branch 'main' into amd/hsivasun/bump-pr-blamelist
amd-hsivasun May 14, 2026
ec0fd68
[CI] Add safe.directory step to manifest-diff for container-based git…
amd-hsivasun May 15, 2026
aa6113d
Merge branch 'main' into amd/hsivasun/bump-pr-blamelist
amd-hsivasun May 15, 2026
ebd3930
Update manifest_diff.md
amd-hsivasun May 19, 2026
98c08b3
[CI] Tighten manifest-diff input descriptions and align help/docstring
amd-hsivasun May 20, 2026
ee148fc
[CI] manifest-diff: install ca-certificates in ubuntu:24.04 container
amd-hsivasun May 20, 2026
125f8ba
[CI] manifest-diff: also install git for submodule walks
amd-hsivasun May 20, 2026
cc3c0e2
[CI] manifest-diff: bootstrap container before checkout; install AWS …
amd-hsivasun May 20, 2026
d4e8015
[CI] manifest-diff: persist safe.directory and consolidate system req…
amd-hsivasun May 20, 2026
b64b68e
[CI] manifest-diff: derive refs from caller github.event; drop with: …
amd-hsivasun May 20, 2026
b2a778f
[docs] manifest-diff: reflect that ref derivation lives in the reusab…
amd-hsivasun May 20, 2026
2695bbc
Updated manifest.md
amd-hsivasun May 20, 2026
17c516f
Merge branch 'main' into amd/hsivasun/bump-pr-blamelist
amd-hsivasun May 20, 2026
b8dac59
[CI] manifest-diff: small cleanup pass
amd-hsivasun May 20, 2026
77e99a1
[CI] manifest-diff: drop actions:read perm
amd-hsivasun May 20, 2026
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
96 changes: 78 additions & 18 deletions .github/workflows/manifest-diff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,74 +4,134 @@ on:
workflow_dispatch:
inputs:
start_ref:
description: 'Start commit SHA or workflow run ID (required when using workflow mode or commit SHA mode without find-last-successful)'
description: 'Start commit SHA or workflow run ID. Used when neither pr_base_ref nor find_last_run is set (start resolution precedence: pr_base_ref > find_last_run > start_ref).'
required: false
type: string
end_ref:
description: 'End commit SHA or workflow run ID'
description: 'End commit SHA (or, with workflow_mode=true, a workflow run ID).'
required: true
type: string
workflow_mode:
description: 'Treat inputs as workflow run IDs instead of commit SHAs'
description: 'Interpret start_ref and end_ref as workflow run IDs instead of commit SHAs (pr_base_ref and find_last_run are unaffected).'
required: false
type: boolean
default: false
find_last_successful:
description: 'Workflow file to find last successful run (e.g., ci_nightly.yml)'
find_last_run:
description: 'Workflow filename (e.g. multi_arch_ci.yml). When set, start_ref is resolved as the head SHA of that workflow''s most recent run on `branch` that concluded with success or failure (cancelled / skipped / in-progress runs are ignored).'
required: false
type: string
pr_base_ref:
description: 'PR base branch name (e.g. main). When set, start_ref is resolved as the merge-base between end_ref and the named branch via the GitHub Compare API — rebase-safe, works on rewritten PR histories.'
required: false
type: string
branch:
description: 'Branch to scope find_last_run lookups against (default: main). Only consulted when find_last_run is set; ignored otherwise.'
required: false
type: string
default: 'main'
repository:
description: 'Repository to check out (default: the repository hosting this workflow run).'
required: false
type: string
default: ''
ref:
description: 'Git ref to check out (default: the ref hosting this workflow run).'
required: false
type: string
default: ''
workflow_call:
inputs:
start_ref:
required: false
type: string
end_ref:
required: true
required: false
type: string
default: ''
workflow_mode:
required: false
type: boolean
default: false
find_last_successful:
find_last_run:
required: false
type: string
pr_base_ref:
required: false
type: string
branch:
required: false
type: string
default: 'main'
repository:
required: false
type: string
default: ''
ref:
required: false
type: string
default: ''

permissions:
contents: read

jobs:
generate-report:
name: Generate Manifest Diff Report
runs-on: ubuntu-24.04
runs-on: ${{ github.repository_owner == 'ROCm' && 'azure-linux-scale-rocm' || 'ubuntu-24.04' }}
continue-on-error: true
permissions:
id-token: write
contents: read
container:
image: ubuntu:24.04
options: -v /runner/config:/home/awsconfig/
env:
AWS_SHARED_CREDENTIALS_FILE: /home/awsconfig/credentials.ini
steps:
- name: Install bootstrap packages
run: |
apt-get update
apt-get install -y git ca-certificates curl unzip

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Comment thread
amd-hsivasun marked this conversation as resolved.
with:
repository: ${{ inputs.repository || github.repository }}
ref: ${{ inputs.ref || '' }}
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.12'

- name: Install AWS CLI
run: |
./dockerfiles/install_awscli.sh

- name: Adjust git config
run: |
git config --global --add safe.directory $PWD

- name: Generate manifest diff report
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
python3 build_tools/generate_manifest_diff_report.py \
--end "${{ inputs.end_ref }}" \
--start "${{ inputs.start_ref || '' }}" \
--find-last-successful "${{ inputs.find_last_successful || '' }}" \
--end "${{ inputs.end_ref || (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}" \
--start "${{ inputs.start_ref || (github.event_name == 'push' && github.event.before) || '' }}" \
--find-last-run "${{ inputs.find_last_run }}" \
--pr-base-ref "${{ inputs.pr_base_ref || (github.event_name == 'pull_request' && github.event.pull_request.base.ref) || '' }}" \
--branch "${{ inputs.branch }}" \
${{ inputs.workflow_mode && '--workflow-mode' || '' }} \
--output-dir reports

- name: Configure AWS Credentials
if: ${{ github.repository == 'ROCm/TheRock' }}
uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
with:
aws-region: us-east-2
role-to-assume: arn:aws:iam::692859939525:role/therock-ci
- name: Configure AWS credentials for artifact uploads
if: ${{ always() }}
uses: ./.github/actions/configure_aws_artifacts_credentials

- name: Upload Report to S3
if: ${{ github.repository == 'ROCm/TheRock' }}
if: ${{ always() }}
run: |
python3 build_tools/github_actions/upload_test_report_script.py \
--run-id ${{ github.run_id }} \
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/multi_arch_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ jobs:
contents: read
id-token: write

manifest_diff:
name: Manifest Diff
uses: ./.github/workflows/manifest-diff.yml
permissions:
contents: read
id-token: write

ci_summary:
name: CI Summary
if: always()
Expand Down
130 changes: 95 additions & 35 deletions build_tools/generate_manifest_diff_report.py
Comment thread
amd-hsivasun marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@
for each component between builds.

Arguments:
--start Start commit SHA or workflow run ID (required unless using --find-last-successful)
--end End commit SHA or workflow run ID (required)
--find-last-successful Workflow file to find last successful run (e.g., 'ci_nightly.yml')
--workflow-mode Treat --start and --end as workflow run IDs instead of commit SHAs
--start Start commit SHA or workflow run ID (required unless using
--find-last-run or --pr-base-ref).
--end End commit SHA or workflow run ID (required).
--find-last-run Workflow filename (e.g., 'multi_arch_ci.yml'). When set,
--start is resolved as the head SHA of that workflow's
most recent run on --branch that concluded with
'success' or 'failure' (cancelled / skipped /
in-progress runs are ignored).
--pr-base-ref PR base branch name. When set, --start is resolved as
the merge-base between --end and the named branch via
the GitHub Compare API. Rebase-safe.
--workflow-mode Treat --start and --end as workflow run IDs instead of
commit SHAs.
--branch Branch to scope --find-last-run lookups against
(default: 'main'). Only consulted when --find-last-run
is set.
--output-dir Directory to write the HTML report into. If unset,
falls back to the TheRock root directory.

If no usable start ref can be derived, the script logs the reason and
exits 0 without writing a report.

Example usage:
python build_tools/generate_manifest_diff_report.py --start abc123 --end def456
python build_tools/generate_manifest_diff_report.py --end def456 --find-last-successful ci_nightly.yml
python build_tools/generate_manifest_diff_report.py --end def456 --find-last-run multi_arch_ci.yml
python build_tools/generate_manifest_diff_report.py --end def456 --pr-base-ref main
python build_tools/generate_manifest_diff_report.py --start 12345 --end 67890 --workflow-mode
"""

Expand All @@ -34,7 +52,7 @@
from generate_therock_manifest import build_manifest_schema
from github_actions.github_actions_api import (
gha_append_step_summary,
gha_query_last_successful_workflow_run,
gha_query_last_workflow_run,
gha_query_workflow_run_by_id,
gha_send_request,
)
Expand Down Expand Up @@ -181,8 +199,21 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
)
parser.add_argument("--end", required=True, help="End workflow ID or commit SHA")
parser.add_argument(
"--find-last-successful",
help="Workflow name to find last successful run (e.g., 'ci_nightly.yml')",
"--find-last-run",
help=(
"Workflow filename (e.g. 'multi_arch_ci.yml'). When set, --start "
"is resolved as the head SHA of that workflow's most recent run "
"on --branch that concluded with 'success' or 'failure' "
"(cancelled / skipped / in-progress runs are ignored)."
),
)
parser.add_argument(
"--pr-base-ref",
help=(
"PR base branch name. When set, --start is resolved as the "
"merge-base between --end and this branch via the GitHub Compare "
"API. Rebase-safe."
),
)
parser.add_argument(
"--workflow-mode",
Expand All @@ -192,7 +223,10 @@ def parse_args(argv: list[str] | None) -> argparse.Namespace:
parser.add_argument(
"--branch",
default="main",
help="Branch to search for last successful workflow run (default: main)",
help=(
"Branch to scope --find-last-run lookups against (default: main). "
"Only consulted when --find-last-run is set; ignored otherwise."
),
)
parser.add_argument(
"--output-dir",
Expand All @@ -214,42 +248,68 @@ def _optional_str(val: str | None) -> str | None:
return s if s else None


def resolve_commits(args: argparse.Namespace) -> tuple[str, str]:
"""Resolve start and end commit SHAs from arguments."""
def resolve_commits(
args: argparse.Namespace,
) -> tuple[str | None, str | None]:
"""Resolve start and end commit SHAs from arguments.

Returns ``(None, None)`` when --find-last-run finds no prior matching
run (graceful empty); caller should exit 0. Other API errors (e.g.
Compare API 404 on --pr-base-ref) propagate as GitHubAPIError; the
workflow's continue-on-error gate handles those.
"""
start = _optional_str(args.start)
find_last = _optional_str(args.find_last_successful)
find_last = _optional_str(args.find_last_run)
pr_base = _optional_str(args.pr_base_ref)
end = _optional_str(args.end)

if start is None and find_last is None:
raise ValueError(
"--start is required unless --find-last-successful is provided"
)
if end is None:
raise ValueError("--end is required")
if start is None and find_last is None and pr_base is None:
raise ValueError(
"--start is required unless --find-last-run or --pr-base-ref is provided"
)

therock_repo_full = f"{ROCM_ORG}/{THEROCK_REPO}"
therock = f"{ROCM_ORG}/{THEROCK_REPO}"

# Resolve start commit
if find_last is not None:
last_run = gha_query_last_successful_workflow_run(
therock_repo_full, find_last, branch=args.branch
# Resolve end first; --pr-base-ref needs end_sha to compute the merge-base.
if args.workflow_mode:
end_sha = gha_query_workflow_run_by_id(therock, end).get("head_sha")
else:
end_sha = end

# Resolve start, in priority order: --pr-base-ref, --find-last-run,
# --workflow-mode, then plain --start.
if pr_base is not None:
compare_url = (
f"https://api.github.com/repos/{therock}/compare/{pr_base}...{end_sha}"
)
compare = gha_send_request(compare_url)
start_sha = compare.get("merge_base_commit", {}).get("sha")
elif find_last is not None:
# Hardcoded to terminal-status: any run that ran to completion (success
# or failure) is acceptable — devs comparing to "the last run that
# actually ran" don't care whether it was green or red, only that it
# wasn't cancelled / skipped / in-progress.
accepted = {"success", "failure"}
last_run = gha_query_last_workflow_run(
therock,
find_last,
branch=args.branch,
accepted_statuses=accepted,
)
if not last_run:
raise ValueError(f"No previous successful run found for {find_last}")
if last_run is None:
print(
f" [empty] No prior run of {find_last} on {args.branch} with "
f"conclusion in {sorted(accepted)} (likely a first-ever run)."
)
return None, None
start_sha = last_run["head_sha"]
elif args.workflow_mode:
workflow_info = gha_query_workflow_run_by_id(therock_repo_full, start)
start_sha = workflow_info.get("head_sha")
start_sha = gha_query_workflow_run_by_id(therock, start).get("head_sha")
else:
start_sha = start

# Resolve end commit
if args.workflow_mode:
workflow_info = gha_query_workflow_run_by_id(therock_repo_full, end)
end_sha = workflow_info.get("head_sha")
else:
end_sha = end

return start_sha, end_sha


Expand Down Expand Up @@ -1423,11 +1483,11 @@ def main(argv: list[str] | None = None) -> int:
"""Main entry point."""
args = parse_args(argv)
start_commit, end_commit = resolve_commits(args)
if start_commit is None:
return 0

diff = compare_manifests(start_commit, end_commit)

output_dir = args.output_dir
generate_html_report(diff, output_dir)
generate_html_report(diff, args.output_dir)

print("\n=== Generating Step Summary ===")
generate_step_summary(diff)
Expand Down
1 change: 1 addition & 0 deletions build_tools/github_actions/configure_ci_path_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ def is_ci_run_required(paths: Optional[Iterable[str]]) -> bool:
"multi_arch_build_windows_artifacts.yml",
"multi_arch_build_wsl_rocdxg_artifacts.yml",
"setup_multi_arch.yml",
"manifest-diff.yml",
"test_artifacts_structure.yml",
"test_native_linux_packages_install.yml",
# both
Expand Down
Loading
Loading