Skip to main content

GitHub Actions Artifact Client for Python

Project description

gha-artifact-client

Python wrapper/CLI around @actions/artifact for creating workflow artifacts from inside a GitHub Actions job.

Allows you to upload workflow artifacts dynamically from Python code without needing to invoke the actions/upload-artifact action in your workflow yaml.

Notes

  • Uploading artifacts only works during the lifetime of a GitHub Actions job.
  • Unlike other GitHub API interactions requires a ACTIONS_RUNTIME_TOKEN and and not a GITHUB_TOKEN.
  • Since the upload API is not publicly documented, this package vendors a custom-built node wrapper around the official @actions/artifact package, which is invoked with node. node needs to be provided by the user.
  • Only depends on the Python standard library.
  • Only direct single-file uploads are supported. If you need zip files, you need to create them yourself before uploading.

Usage

Python API

import io

from gha_artifact_client import ArtifactClientApi

# Credentials from environment variables (default)
api = ArtifactClientApi()

# Or supply credentials explicitly — useful when you don't want them
# sitting in os.environ where other subprocesses could inherit them
api = ArtifactClientApi(
    runtime_token="...",
    results_url="...",
)

# Upload a file from disk
result = api.upload_artifact("dist/package.tar.gz")

# Upload with a custom artifact name and expiry time
result = api.upload_artifact(
    "dist/package.tar.gz",
    name="build-output.tar.gz",
    expires_in=7 * 24 * 3600,  # 7 days from now, in seconds
)

# Or set an exact expiry datetime (must be timezone-aware)
import datetime as dt
result = api.upload_artifact(
    "dist/package.tar.gz",
    expires_at=dt.datetime(2026, 12, 31, 23, 59, 59, tzinfo=dt.timezone.utc),
)

print(result.id)
print(result.digest)

# Upload from in-memory bytes
result = api.upload_artifact_bytes(
    b"hello from memory\n",
    name="build-output.txt",
)

print(result.id)

# Upload using a file-like object
with open("dist/package.tar.gz", "rb") as f:
    result = api.upload_artifact_fileobj(f, name="package.tar.gz")

print(result.id)

CLI

gha-artifact-client upload dist/package.tar.gz --name package.tar.gz --expires-in 604800

--expires-in takes seconds (int or float). Use --expires-at for an exact point in time as a timezone-aware ISO 8601 datetime. The two flags are mutually exclusive.

Credentials default to ACTIONS_RUNTIME_TOKEN and ACTIONS_RESULTS_URL from the environment, but can be supplied explicitly:

gha-artifact-client --runtime-token "$MY_TOKEN" --results-url "$MY_RESULTS_URL" \
  upload dist/package.tar.gz

Credentials & Security Considerations

Uploading artifacts requires a URL and a credential that is only available inside a live GitHub Actions job:

  • ACTIONS_RUNTIME_TOKEN — a token created for the current job.
  • ACTIONS_RESULTS_URL — the endpoint for the artifact storage backend.

These are not the same as GITHUB_TOKEN and are not exposed as regular environment variables. They are only exposed to action steps and not run steps. To make them available in run steps you can extract them via actions/github-script:

permissions: {}

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Get artifact upload credentials
        id: vars
        uses: actions/github-script@v8
        with:
          script: |
            core.setOutput('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN'])
            core.setOutput('ACTIONS_RESULTS_URL', process.env['ACTIONS_RESULTS_URL'])

      - name: Upload artifact
        env:
          ACTIONS_RUNTIME_TOKEN: ${{ steps.vars.outputs.ACTIONS_RUNTIME_TOKEN }}
          ACTIONS_RESULTS_URL: ${{ steps.vars.outputs.ACTIONS_RESULTS_URL }}
        run: python your_script.py

Notes on the Token and Security

  • The token is valid for timeout-minutes of the current job, which defaults to 360 minutes (6 hours). After that, it expires and cannot be used to upload artifacts.

  • Even if the token hasn't expired, it appears to be invalidated after the job completes. Using it after the current job completes results in:

    Failed to CreateArtifact: Received non-retryable error: Failed request: (403) Forbidden: job is complete

  • From what I understand, the token can also be used to upload cache entries and job logs, but I haven't tested that. If you are passing them to third party code, consider the security implications of that. I'd recommend to remove the token from the environment when calling third-party code that doesn't need it, to avoid accidental leaks.

  • ACTIONS_RESULTS_URL for github.com on hosted runners, at the time of writing, is https://results-receiver.actions.githubusercontent.com/.

Development

  • Install Python dependencies with uv sync.
  • Install node wrapper dependencies with npm ci in node-wrapper/.
  • Lint the node wrapper with npm run lint in node-wrapper/.
  • Type-check the node wrapper with npm run tsc in node-wrapper/.
  • Rebuild the vendored node wrapper with npm run build in node-wrapper/.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gha_artifact_client-0.1.0.tar.gz (311.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gha_artifact_client-0.1.0-py3-none-any.whl (246.5 kB view details)

Uploaded Python 3

File details

Details for the file gha_artifact_client-0.1.0.tar.gz.

File metadata

  • Download URL: gha_artifact_client-0.1.0.tar.gz
  • Upload date:
  • Size: 311.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gha_artifact_client-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c0073122ac9720afe929c37de6ca85939e6ea44fa2b704e1abbba426032ffafa
MD5 5bf9f2e6b52327108ab222043577f6db
BLAKE2b-256 aff4967dc900fca4aced8743cc4a704a044448c52ed6cca36d02f78a9554f2f1

See more details on using hashes here.

File details

Details for the file gha_artifact_client-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gha_artifact_client-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 246.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.0 {"installer":{"name":"uv","version":"0.11.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gha_artifact_client-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 afb6cf2418beb7f75a91e0cd606f756372bc6429543efd70b2c45a3c089c8713
MD5 33aeb1af15672889ea0927511511431d
BLAKE2b-256 ff561ef9fd81aee2f822d7d850cb245327131b2ed253edeb91855c5d638606da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page