Artifact storage
Firmware is built in other repositories and stored as GitHub workflow artifacts, GitHub release assets, or Cloudsmith packages. These classes handle authentication, lookup, and download.
They include a fallback to allow providing the artifacts directly, without
downloading from the storage buckets, allowing to use locally built artifacts.
For Cloudsmith, the fallback is when CLOUDSMITH_NAMESPACE is unset (no
token required for public repos), and GitHub, GITHUB_TOKEN (token
required).
GitHub
Download workflow artifacts and release assets from GitHub.
Basic usage:
import logging
logging.basicConfig(level=logging.INFO)
from hw_tests.github import GitHub
# Gets defaults from context
gh = GitHub(context)
# Get artifact 'example' from run '1234' (overrides the context)
# of the repository from the context
path = gh.download(
name='example',
run_id='1234',
)
- class hw_tests.github.GitHub(context)
GitHub API client for a test run.
The default repository and workflow run come from
workflow_run_urlincontextif present, else fromGITHUB_REPOSITORYandGITHUB_RUN_ID.GITHUB_TOKENis used for authentication; without it, workflow artifacts cannot be downloaded.- Parameters:
context – Test context, see
hw_tests.context.build_context().
- static get_id_token()
Return a GitHub Actions OIDC token.
The audience is
https://github.com/<owner>. The job needs theid-token: writepermission.
- list_artifacts(owner_repository=None, run_id=None, source=None)
List the artifacts of a workflow run or the assets of a release.
Results are cached per run or release. Expired artifacts are skipped.
- Parameters:
owner_repository – Repository. Defaults to
owner_repository.run_id – Workflow run ID. Defaults to the run from the context.
source – Release, as
{'repository': ..., 'tag': ...}. Takes precedence overowner_repositoryandrun_id.
- Returns:
Artifact or asset dicts from the GitHub API. Empty if the run cannot be resolved or there is no token.
- download(name: str, owner_repository: str | None = None, run_id: str | None = None, path: Path | str | None = None, source: dict | None = None) Path
Download an artifact and extract it if it is an archive.
Like
actions/download-artifact. Release assets are cached in$HW_TEST_CACHE_DIR(default$XDG_CACHE_HOME/hw-test).If a workflow artifact cannot be downloaded (no token or no run), a warning is logged and
_artifacts/<test name>/<n>is returned, wherencounts calls. Put the files there to run locally.- Parameters:
name – Artifact or asset name.
owner_repository – Repository. Defaults to
owner_repository.run_id – Workflow run ID. Defaults to the run from the context.
path – Output directory for workflow artifacts. A temporary directory by default.
source – Release, as
{'repository': ..., 'tag': ...}.
- Returns:
Directory containing the artifact.
Cloudsmith
Download build artifacts from Cloudsmith.
Basic usage:
import logging
logging.basicConfig(level=logging.INFO)
from hw_tests.cloudsmith import Cloudsmith
cs = Cloudsmith()
# Get the latest artifact from branch 'refs/heads/...'
path = cs.download(
repository='linux',
name='adi_bcm2709_defconfig-gcc-arm-devel',
version='refs/heads/rpi-6.12.y',
)
- class hw_tests.cloudsmith.Cloudsmith(context=None)
Cloudsmith API client.
Packages are looked up in
$CLOUDSMITH_NAMESPACE/<repository>. Authentication is done on creation, seeauthenticate().- Parameters:
context – Test context. Its
namesets the local fallback directory ofdownload().
- authenticate()
Get an API token and validate it.
Uses
CLOUDSMITH_API_KEYif set. Otherwise, in GitHub Actions, gets a token throughgithub_oidc(). Without a token, only public artifacts can be downloaded.
- github_oidc()
Exchange a GitHub OIDC token for a Cloudsmith API token.
Requires
CLOUDSMITH_SERVICE_SLUGandCLOUDSMITH_NAMESPACE. The token is exported asCLOUDSMITH_API_KEYto the environment andGITHUB_ENV, for the next steps.
- static get_api_token(org_name: str, cs_service_slug: str, id_token: str, api_host: str = 'api.cloudsmith.io') str
Return a Cloudsmith API token for an OIDC
id_token.- Raises:
ValueError – Cloudsmith returned an empty token.
- static validate(token: str, api_host: str = 'api.cloudsmith.io') None
Check
tokenagainst the API and log the authenticated user.- Raises:
requests.HTTPError – the token is rejected.
- download(repository: str, name: str, version: str | None = None, tags: tuple | list = (), path: Path | str | None = None) Path
Download an artifact and extract it if it is an archive.
The package is selected by
versionif given, else bytags:versionas a full 40-char SHA: exact match.versionas a git ref (refs/heads/*,refs/tags/*,refs/pull/*): latest package built from that ref.other
versionvalues, such as a short SHA: latest pushed package matching the version.tags: latest package that has all the tags, for example('on/push', 'refs/heads/main').
If
CLOUDSMITH_NAMESPACEis not set, a warning is logged and_artifacts/<test name>/<n>is returned, wherencounts calls. Put the files there to run locally. Without acontext, aValueErroris raised instead.- Parameters:
repository – Cloudsmith repository in
CLOUDSMITH_NAMESPACE.name – Package name.
version – SHA, git ref, or version.
tags – Tags to match when
versionis not given.path – Output directory. A temporary directory by default.
- Returns:
Directory containing the artifact.
- Raises:
LookupError – no package matches.