-
Notifications
You must be signed in to change notification settings - Fork 245
Add configure-aws-credentials composite workflow with release support #4386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
cd67f6b
Add dynamic configure-aws-credentials with release bucket support
ScottTodd f895a76
Add syspath to fix import
ScottTodd eba89b4
Split iam_namespace into iam_account and fstring in property
ScottTodd a2f9004
Use delete=False for tempfile in tests (Windows compat)
ScottTodd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
.github/actions/configure_aws_artifacts_credentials/action.yml
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Copyright Advanced Micro Devices, Inc. | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| name: "Configure AWS credentials for artifact uploads" | ||
|
|
||
| description: >- | ||
| Determine the IAM role for the artifacts S3 bucket and assume it via OIDC. | ||
| * Forks and external repos skip OIDC and use runner base credentials. | ||
| * Release builds (dev/nightly/prerelease) use 'therock-{release_type}' roles. | ||
| * Other CI runs use the 'therock-ci' role. | ||
| See the "Authentication" section in docs/development/s3_buckets.md. | ||
|
|
||
| inputs: | ||
| release_type: | ||
| description: 'Release type: "" for CI, or "dev", "nightly", "prerelease".' | ||
| default: "" | ||
|
|
||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - name: Determine IAM role | ||
| if: ${{ always() }} | ||
| id: iam | ||
| shell: bash | ||
| run: | | ||
| python build_tools/github_actions/write_artifacts_bucket_info.py \ | ||
| --release-type "${{ inputs.release_type }}" | ||
|
|
||
| - name: Configure AWS Credentials | ||
| if: ${{ always() && steps.iam.outputs.iam_role != '' }} | ||
| uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 | ||
| with: | ||
| aws-region: ${{ steps.iam.outputs.aws_region }} | ||
| role-to-assume: ${{ steps.iam.outputs.iam_role }} | ||
| special-characters-workaround: ${{ runner.os == 'Windows' }} |
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
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
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| # Copyright Advanced Micro Devices, Inc. | ||
| # SPDX-License-Identifier: MIT | ||
|
|
||
| """Inventory of S3 buckets used by CI/CD systems and related functions. | ||
|
|
||
| See docs/development/s3_buckets.md. | ||
| """ | ||
|
|
||
| from dataclasses import dataclass, field | ||
| import json | ||
| import os | ||
| import sys | ||
|
|
||
|
|
||
| def _log(*args, **kwargs): | ||
| """Log to stdout with flush for CI visibility.""" | ||
| print(*args, **kwargs) | ||
| sys.stdout.flush() | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class S3BucketConfig: | ||
| """Metadata for a single bucket in S3""" | ||
|
|
||
| name: str | ||
| """S3 bucket name (e.g. 'therock-ci-artifacts')""" | ||
|
|
||
| region: str = field(default="us-east-2") | ||
| """Region in S3 (e.g. 'us-east-2')""" | ||
|
|
||
| iam_account: str | None = field(default="692859939525") | ||
| """IAM account for write_access_iam_role""" | ||
|
|
||
| iam_role: str | None = field(default=None) | ||
| """IAM role name that grants write access to this bucket (e.g. 'therock-ci'), if any""" | ||
|
|
||
| @property | ||
| def write_access_iam_role(self) -> str | None: | ||
| """IAM role granting write access to the bucket""" | ||
| if not self.iam_role: | ||
| return None | ||
| if not self.iam_account: | ||
| raise ValueError( | ||
| f"Bucket {self.name!r} has iam_role={self.iam_role!r} but no iam_account" | ||
| ) | ||
| return f"arn:aws:iam::{self.iam_account}:role/{self.iam_role}" | ||
|
|
||
|
|
||
| s3_bucket_configs = [ | ||
| # CI (self-hosted runners include credentials for therock-ci-artifacts-external) | ||
| S3BucketConfig("therock-ci-artifacts", iam_role="therock-ci"), | ||
| S3BucketConfig("therock-ci-artifacts-external", iam_role=None), | ||
| # Release type "dev" | ||
| S3BucketConfig("therock-dev-artifacts", iam_role="therock-dev"), | ||
| S3BucketConfig("therock-dev-packages", iam_role="therock-dev"), | ||
| S3BucketConfig("therock-dev-python", iam_role="therock-dev"), | ||
| S3BucketConfig("therock-dev-tarball", iam_role="therock-dev"), | ||
| # Release type "nightly" | ||
| S3BucketConfig("therock-nightly-artifacts", iam_role="therock-nightly"), | ||
| S3BucketConfig("therock-nightly-packages", iam_role="therock-nightly"), | ||
| S3BucketConfig("therock-nightly-python", iam_role="therock-nightly"), | ||
| S3BucketConfig("therock-nightly-tarball", iam_role="therock-nightly"), | ||
| # Release type "prerelease" | ||
| S3BucketConfig("therock-prerelease-artifacts", iam_role="therock-prerelease"), | ||
| S3BucketConfig("therock-prerelease-packages", iam_role="therock-prerelease"), | ||
| S3BucketConfig("therock-prerelease-python", iam_role="therock-prerelease"), | ||
| S3BucketConfig("therock-prerelease-tarball", iam_role="therock-prerelease"), | ||
| # Release type "release" (no automated credentials for uploading) | ||
| S3BucketConfig("therock-release-artifacts", iam_role=None), | ||
| S3BucketConfig("therock-release-packages", iam_role=None), | ||
| S3BucketConfig("therock-release-python", iam_role=None), | ||
| S3BucketConfig("therock-release-tarball", iam_role=None), | ||
| ] | ||
|
|
||
|
|
||
| _BUCKET_CONFIGS_BY_NAME = {c.name: c for c in s3_bucket_configs} | ||
|
|
||
| _ALLOWED_RELEASE_TYPES = {"dev", "nightly", "prerelease"} | ||
|
|
||
| # Repositories allowed to use release_type. Only these repositories are trusted | ||
| # to assume release IAM roles that grant write access to release buckets. | ||
| _ALLOWED_RELEASE_REPOS = {"ROCm/TheRock", "ROCm/rockrel"} | ||
|
|
||
|
|
||
| def get_artifacts_bucket_config( | ||
| release_type: str, | ||
| repository: str, | ||
| is_pr_from_fork: bool, | ||
| ) -> S3BucketConfig: | ||
| """Look up the artifacts bucket config for a repository. | ||
|
|
||
| Args: | ||
| release_type: "" for CI builds, or "dev", "nightly", "prerelease". | ||
| repository: GitHub repository (e.g. "ROCm/TheRock"). | ||
| is_pr_from_fork: Whether this is a PR from a fork. | ||
| """ | ||
| if release_type: | ||
| if release_type not in _ALLOWED_RELEASE_TYPES: | ||
| raise ValueError( | ||
| f"release_type={release_type!r} is invalid, " | ||
| f"expected empty string or one of {_ALLOWED_RELEASE_TYPES}" | ||
| ) | ||
| if repository not in _ALLOWED_RELEASE_REPOS: | ||
| raise ValueError( | ||
| f"release_type={release_type!r} is set but " | ||
| f"repository {repository!r} is not one of " | ||
| f"{_ALLOWED_RELEASE_REPOS}" | ||
| ) | ||
| bucket_name = f"therock-{release_type}-artifacts" | ||
| else: | ||
| if is_pr_from_fork or repository != "ROCm/TheRock": | ||
| bucket_name = "therock-ci-artifacts-external" | ||
| else: | ||
| bucket_name = "therock-ci-artifacts" | ||
| return _BUCKET_CONFIGS_BY_NAME[bucket_name] | ||
|
|
||
|
|
||
| def _is_current_run_pr_from_fork() -> bool: | ||
| """Check if the current workflow run is a pull request from a fork. | ||
|
|
||
| Reads the GitHub event payload to check the .fork property on the | ||
| head repo, matching the behavior of the GitHub Actions expression | ||
| ``github.event.pull_request.head.repo.fork``. | ||
|
|
||
| Returns False for non-pull_request events or if the event payload | ||
| is not available (e.g. local development). | ||
| """ | ||
| event_name = os.environ.get("GITHUB_EVENT_NAME", "") | ||
| if event_name != "pull_request": | ||
| return False | ||
|
|
||
| event_path = os.environ.get("GITHUB_EVENT_PATH") | ||
| if not event_path: | ||
| return False | ||
|
|
||
| with open(event_path) as f: | ||
| event = json.load(f) | ||
|
|
||
| return bool( | ||
| event.get("pull_request", {}).get("head", {}).get("repo", {}).get("fork", False) | ||
| ) | ||
|
|
||
|
|
||
| def get_artifacts_bucket_config_for_workflow_run( | ||
| github_repository: str, | ||
| release_type: str | None = None, | ||
| workflow_run_id: str | None = None, | ||
| workflow_run: dict | None = None, | ||
| ) -> S3BucketConfig: | ||
| """Look up the artifacts bucket config for a workflow run. | ||
|
|
||
| Combines environment-based inputs (RELEASE_TYPE, event payload) with | ||
| optional workflow run metadata from the GitHub API to determine the | ||
| correct artifacts bucket. | ||
|
|
||
| Args: | ||
| github_repository: GitHub repository (e.g. "ROCm/TheRock"). | ||
| release_type: Release type override. If None, reads RELEASE_TYPE | ||
| from the environment (default: empty string = CI build). | ||
| workflow_run_id: If set and ``workflow_run`` is None, fetches the | ||
| workflow run from the GitHub API for fork detection. | ||
| workflow_run: Optional workflow run dict from GitHub API. If | ||
| provided, used directly for fork detection (no API call). | ||
| """ | ||
| _log("Retrieving bucket info for workflow run...") | ||
| _log(f" github_repository: {github_repository}") | ||
|
|
||
| if release_type is None: | ||
| release_type = os.environ.get("RELEASE_TYPE", "") | ||
| if release_type: | ||
| _log(f" release_type: {release_type}") | ||
|
|
||
| # Fetch workflow_run from API if not provided but workflow_run_id is set. | ||
| # Deferred import: github_actions is an optional dependency not available in | ||
| # all environments (e.g. local dev without the GHA support package installed). | ||
| if workflow_run is None and workflow_run_id is not None: | ||
| from github_actions.github_actions_api import gha_query_workflow_run_by_id | ||
|
|
||
| workflow_run = gha_query_workflow_run_by_id(github_repository, workflow_run_id) | ||
|
|
||
| # Extract metadata from workflow_run if available | ||
| if workflow_run is not None: | ||
| _log(f" workflow_run_id: {workflow_run['id']}") | ||
| head_github_repository = workflow_run["head_repository"]["full_name"] | ||
| is_pr_from_fork = head_github_repository != github_repository | ||
| _log(f" head_github_repository: {head_github_repository}") | ||
| _log(f" is_pr_from_fork: {is_pr_from_fork}") | ||
| else: | ||
| is_pr_from_fork = _is_current_run_pr_from_fork() | ||
| _log(f" is_pr_from_fork: {is_pr_from_fork}") | ||
|
|
||
| config = get_artifacts_bucket_config( | ||
| release_type=release_type, | ||
| repository=github_repository, | ||
| is_pr_from_fork=is_pr_from_fork, | ||
| ) | ||
| _log(f" bucket: {config.name}") | ||
| return config |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also update
TheRock/.github/workflows/release_portable_linux_packages.yml
Lines 274 to 279 in aee2385
but that workflow uses more than just the
therock-{release_type}-artifactsbucket, it also usesTheRock/.github/workflows/release_portable_linux_packages.yml
Line 185 in aee2385
For multi-arch release workflows, I plan on having the existing build workflows upload artifacts,logs,etc. to
therock-{release_type}-artifactsand then have new workflow code copy from those buckets to e.g.therock-{release_type}-tarballBy the way, I decided to NOT update
TheRock/.github/workflows/manifest-diff.yml
Lines 66 to 71 in aee2385
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updating
release_portable_linux_packages.ymlshould be fine as the role allows to access the other buckets as well. Can be in a follow up however.