Skip to content

Commit ef9c3f3

Browse files
Update token handling in artifact-manifest action (#822)
* created manifest action, README, and testing workflow * fixed typos * removed required:false as it is the default * updated examples in README * updated upload-artifact action to 7.0.1 * pared down comments in python script * added input validation * added duplicate detection for manually added artifacts * added JSON validation logic * replaced backticks with single quotes. removed action:write permissions. * replaced backticks with simgle quotes. added masking to github token thats passed to the python script to prevent possibility of exposure in exception tracebacks * updated README with examples * testing masking * changed method of passing the GH token. updated in all places * pass the token ENV var to the script. update the README accordingly * updated README * updated README * github_token now only required when fetching GHA artifacts
1 parent a311c53 commit ef9c3f3

4 files changed

Lines changed: 59 additions & 15 deletions

File tree

.github/workflows/test-artifact-manifest.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ jobs:
5555
- name: Create and upload manifest
5656
id: manifest
5757
uses: ./artifact-manifest
58+
env:
59+
GITHUB_TOKEN: ${{ github.token }}
5860
with:
5961
mode: upload
6062
gha_artifacts: |
@@ -92,6 +94,8 @@ jobs:
9294
- name: Download manifest
9395
id: manifest
9496
uses: ./artifact-manifest
97+
env:
98+
GITHUB_TOKEN: ${{ github.token }}
9599
with:
96100
mode: download
97101
run_id: ${{ github.run_id }}

artifact-manifest/README.md

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Use this action to create an auditable record of exactly what a run produced, pa
88
## Key Features
99
- **Dual upload/download modes**: One action handles both publishing and consuming the manifest
1010
- **Flexible artifact selection**: Include all GHA artifacts with `*`, or specify by name
11-
- **External artifact support**: Merge non-GHA artifacts (container images, blobs, release assets) via `additional_artifacts`
11+
- **External artifact support**: Add non-GHA artifacts (container images, blobs, release assets) via `additional_artifacts`
1212
- **Paginated API handling**: Correctly handles runs with more than 100 artifacts
1313
- **No external dependencies**: Pure Python standard library — no pip installs required
1414

@@ -20,6 +20,8 @@ Add this step at the end of a build job, after all artifacts have been uploaded:
2020
```yaml
2121
- name: Upload artifact manifest
2222
uses: bitwarden/gh-actions/artifact-manifest@main
23+
env:
24+
GITHUB_TOKEN: ${{ github.token }}
2325
with:
2426
mode: upload
2527
gha_artifacts: |
@@ -40,7 +42,9 @@ Inputs:
4042
- `mode`: Set to `upload`
4143
- `gha_artifacts`: Newline-separated list of GHA artifact names that have been uploaded to the current run to include. Use `*` to include all artifacts from the run (the manifest itself is always excluded). Omit to include none.
4244
- `additional_artifacts`: JSON object of non-GHA artifact entries to merge into the manifest. Keys are logical artifact names; values are type-specific objects.
43-
- `github_token`: GitHub token used to query the run's artifact list. Defaults to `${{ github.token }}`.
45+
46+
Environment:
47+
- `GITHUB_TOKEN`: GitHub token used to query the run's artifact list. **Required when using `gha_artifacts`.** Pass via `env: GITHUB_TOKEN: ${{ github.token }}`. Not required if using only `additional_artifacts`.
4448

4549
### Download Mode
4650
Reference the manifest in a downstream workflow using the run ID from the upstream run:
@@ -49,6 +53,8 @@ Reference the manifest in a downstream workflow using the run ID from the upstre
4953
- name: Download artifact manifest
5054
id: manifest
5155
uses: bitwarden/gh-actions/artifact-manifest@main
56+
env:
57+
GITHUB_TOKEN: ${{ github.token }}
5258
with:
5359
mode: download
5460
run_id: ${{ github.event.workflow_run.id }}
@@ -68,7 +74,9 @@ Inputs:
6874
- `mode`: Set to `download`
6975
- `run_id`: The workflow run ID to download the manifest from. Required.
7076
- `repo`: The `owner/repo` to download from. Defaults to the current repository.
71-
- `github_token`: GitHub token with artifact read access. Defaults to `${{ github.token }}`.
77+
78+
Environment:
79+
- `GITHUB_TOKEN`: GitHub token with artifact read access. **Required.** Pass via `env: GITHUB_TOKEN: ${{ github.token }}`. For cross-repo downloads, use a GitHub App token with `actions: read` permission on the target repository.
7280

7381
Outputs:
7482
- `manifest`: The full manifest as a JSON string, accessible via `${{ steps.<step-id>.outputs.manifest }}`. Also available in upload mode.
@@ -81,6 +89,29 @@ Outputs:
8189
run: echo "$IMAGE_SHA"
8290
```
8391

92+
### Using Custom Tokens
93+
94+
For cross-repo artifact downloads, use a GitHub App token passed via the `env` parameter:
95+
96+
```yaml
97+
- name: Generate app token
98+
id: app-token
99+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
100+
with:
101+
app-id: ${{ vars.APP_ID }}
102+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
103+
repositories: target-repo # scope to specific repos
104+
105+
- name: Download manifest from another repo
106+
uses: bitwarden/gh-actions/artifact-manifest@main
107+
env:
108+
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
109+
with:
110+
mode: download
111+
run_id: ${{ github.event.workflow_run.id }}
112+
repo: other-org/other-repo
113+
```
114+
84115
### CI/CD Workflow Handoff Example
85116

86117
A common pattern is to have a CI workflow build and upload the manifest, then trigger a CD workflow that downloads and uses it:
@@ -108,6 +139,8 @@ jobs:
108139
109140
- name: Upload artifact manifest
110141
uses: bitwarden/gh-actions/artifact-manifest@main
142+
env:
143+
GITHUB_TOKEN: ${{ github.token }}
111144
with:
112145
mode: upload
113146
gha_artifacts: |
@@ -142,14 +175,22 @@ jobs:
142175
runs-on: ubuntu-latest
143176
permissions:
144177
contents: read
145-
actions: read
146178
steps:
147179
- name: Checkout
148180
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
149181
182+
- name: Generate app token
183+
id: app-token
184+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
185+
with:
186+
app-id: ${{ vars.APP_ID }}
187+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
188+
150189
- name: Download artifact manifest
151190
id: manifest
152191
uses: bitwarden/gh-actions/artifact-manifest@main
192+
env:
193+
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
153194
with:
154195
mode: download
155196
run_id: ${{ github.event.workflow_run.id }}
@@ -234,7 +275,7 @@ Provided via `additional_artifacts`. The `type` field is required; all other fie
234275
- Python 3.6 or later must be available on the runner (present by default on GitHub-hosted runners)
235276
- For `upload` mode, the GitHub token must have `actions: read` permission to query the run artifacts from the GitHub API
236277
- The `gh` CLI must be available on the runner for download mode (present by default on GitHub-hosted runners)
237-
- In `download` mode, for cross-repo downloads, the token must have `actions: read` on the target repository — the default `github.token` is scoped to the current repository only and will not work
278+
- In `download` mode, for cross-repo downloads, use a GitHub App token with `actions: read` on the target repository — the default `GITHUB_TOKEN` is scoped to the current repository only
238279

239280
## Troubleshooting
240281

@@ -258,3 +299,8 @@ Provided via `additional_artifacts`. The `type` field is required; all other fie
258299
- Confirm the upstream run completed successfully and the manifest was uploaded
259300
- Verify `repo` points to the correct repository if downloading cross-repo
260301
- The artifact is uploaded under the name `artifact-manifest` — it must not have been deleted or expired
302+
303+
### "GITHUB_TOKEN environment variable is required when using gha_artifacts"
304+
- This error occurs in upload mode when `gha_artifacts` is specified but `GITHUB_TOKEN` is not set
305+
- Confirm that the `GITHUB_TOKEN` environment variable is set in an `env:` block: `env: GITHUB_TOKEN: ${{ github.token }}`
306+
- If using only `additional_artifacts` (no `gha_artifacts`), the token is not required

artifact-manifest/action.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ inputs:
66
mode:
77
description: "'upload' to build and upload the manifest, 'download' to fetch and parse it."
88
required: true
9-
github_token:
10-
description: "GitHub token"
11-
default: ${{ github.token }}
129
gha_artifacts:
1310
description: |
1411
Newline-separated list of GHA artifact names to include in the manifest.
@@ -45,15 +42,10 @@ runs:
4542
exit 1
4643
fi
4744
48-
- name: Mask GitHub token
49-
shell: bash
50-
run: echo "::add-mask::${{ inputs.github_token }}"
51-
5245
- name: Build manifest
5346
if: inputs.mode == 'upload'
5447
shell: bash
5548
env:
56-
GH_TOKEN: ${{ inputs.github_token }}
5749
_RUN_ID: ${{ github.run_id }}
5850
_REPOSITORY: ${{ github.repository }}
5951
_SHA: ${{ github.sha }}
@@ -86,7 +78,6 @@ runs:
8678
if: inputs.mode == 'download'
8779
shell: bash
8880
env:
89-
GH_TOKEN: ${{ inputs.github_token }}
9081
_REPO: ${{ inputs.repo }}
9182
_RUN_ID: ${{ inputs.run_id }}
9283
run: |

artifact-manifest/create_manifest.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def get_run_artifacts(token, repository, run_id):
3737

3838

3939
def main():
40-
token = os.environ["GH_TOKEN"]
4140
run_id = os.environ["_RUN_ID"]
4241
repository = os.environ["_REPOSITORY"]
4342
sha = os.environ["_SHA"]
@@ -60,6 +59,10 @@ def main():
6059
}
6160

6261
if gha_artifacts_input:
62+
token = os.environ.get("GITHUB_TOKEN")
63+
if not token:
64+
print("::error::GITHUB_TOKEN environment variable is required when using gha_artifacts.", file=sys.stderr)
65+
sys.exit(1)
6366
all_artifacts = get_run_artifacts(token, repository, run_id)
6467

6568
if gha_artifacts_input == "*":

0 commit comments

Comments
 (0)