* fix: use getReleaseByTag API instead of iterating all releases
This avoids GitHub's API pagination limit of 10000 results which causes
failures for repositories with many releases.
The `findTagFromReleases` function now uses the direct `getReleaseByTag`
API for O(1) lookup instead of iterating through all releases with
`allReleases`. This is both more efficient and fixes the 10k limit issue.
Fixes#724
* fix: rebuild bundle after release lookup rebase
Signed-off-by: Rui Chen <rui@chenrui.dev>
---------
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: Rui Chen <rui@chenrui.dev>
Previously, the releases were created and then artifacts (if any)
were added to them. This broke when GitHub released "immutable"
releases, which disallow changes after the release is published.
Make it so that releases are always marked as "draft" when being
worked on by the action, and unmarked as draft (if desired) once
the action is completed.
Fixes#653
- Add retry logic for 422 'already_exists' errors in race conditions
- Allow action to find and update existing releases instead of failing
- Add test to verify race condition handling works correctly
- Fixes regression that broke matrix workflows in v2.2.2+
closes#616
* fix(release): break when draft release is found
when a release with the desired tag_name is found, break out of the loop
that looks for it. this prevents the case where accidentally overwrite a
detected release on successive iterations of the for loop
fixes: #602
* include built output
* add tests for finding tag from releases
add tests for updated functionality to break when we find a release.
the logic has been extracted into its own function, to make testing
simpler by avoiding over mocking/stubbing of network calls that would
create or update a release.
the tests that were added use jest's describe/it blocks, but use node's
assert function to align with other tests. there isn't any prior art for
mocking function calls in the codebase, so for now we use simple promises
in "mock" objects that adhere to the Releaser interface
* refactor findTagFromReleases
purely a sytlistic choice to not have to pre-declare the _release variable,
and not have to check using `typeof _release === "string"` when detecting
a found release
* reset dist/index.js to master
* update impl after merge with master
* update dist
* fix: use readableWebStream() to stream asset contents
This allows the uploads to finish without mismatched Content-Length,
likely because the original method implied a wrong body encoding or
something similar. Unfortunately a GitHub server API mock was not
readily available so I had to test manually with a barebones repository.
Fixes: #555Fixes: #556
Signed-off-by: WANG Xuerui <git@xen0n.name>
* feat: log when each asset is successfully uploaded
Signed-off-by: WANG Xuerui <git@xen0n.name>
* build: refresh dist
Signed-off-by: WANG Xuerui <git@xen0n.name>
* style: format with prettier
Signed-off-by: WANG Xuerui <git@xen0n.name>
---------
Signed-off-by: WANG Xuerui <git@xen0n.name>
Previously all assets were being read synchronously into memory, making
the action unsuitable for releasing very large assets. Because the
client library allows stream body inputs (it just forwards it to the
underlying `fetch` implementation), just do it.
The idea is also suggested by @enumag in
https://github.com/softprops/action-gh-release/issues/353#issuecomment-1793865790.
Fixes: #353
Signed-off-by: WANG Xuerui <git@xen0n.name>
* Update json5 deps
* Remove quote around env var `GITHUB_TOKEN`
* Factorize search by draft & tag
* Correct `_release` undefined when creating a new release
* Cleanup package-lock
Third-person singular simple present form of "let" is obviously intended, judging from grammatical context.
Contraction of "let us" is erroneously used instead.
When the input `input_files` is not defined, the
`config.input_files` will default to an empty array, which always
evaluate to true - that was triggering a warning like "hey man,
the value you inputted on `input_files` didn't yield any files",
which is logically wrong if `input_files` isn't explicitly defined.
description:Report a bug or regression in action-gh-release
title:"[Bug]: "
labels:
- bug
body:
- type:markdown
attributes:
value:|
Before filing:
- confirm the problem still reproduces on the latest release or `master`
- search existing issues for the same behavior
- if the original repository is private, include a minimal public repro, a sanitized workflow snippet, or exact redacted steps a maintainer can follow
- type:checkboxes
id:checks
attributes:
label:Pre-flight checks
options:
- label:I searched existing issues and did not find a duplicate
required:true
- label:I reproduced this with the latest released version or current `master`
required:true
- label:I included a reproducible example or a sanitized/redacted reproduction path if the original repository is private
required:true
- type:input
id:action_version
attributes:
label:action-gh-release version
description:Tag, SHA, or ref used in your workflow
placeholder:v2.5.2
validations:
required:true
- type:dropdown
id:runner
attributes:
label:Runner operating system
options:
- ubuntu-latest
- windows-latest
- macos-latest
- other
validations:
required:true
- type:input
id:target_repository
attributes:
label:Release target repository
description:Fill this in if you set the `repository:` input
placeholder:owner/repo
- type:input
id:repro_reference
attributes:
label:Reproduction repo, gist, or artifact
description:Link a minimal repro repository, gist, run URL, or other shareable artifact if you have one
placeholder:https://github.com/owner/repro-repo
- type:textarea
id:workflow
attributes:
label:Workflow snippet
description:Include the relevant `uses:` step and inputs. If the original repo is private, paste a sanitized version here.
render:yaml
- type:textarea
id:expected
attributes:
label:Expected behavior
validations:
required:true
- type:textarea
id:actual
attributes:
label:Actual behavior
validations:
required:true
- type:textarea
id:reproduce
attributes:
label:Steps to reproduce
description:Include tags, matrix/concurrency details, and any repo rules involved. If the original repo is private, describe the smallest setup a maintainer can recreate locally or in a throwaway repo.
placeholder:|
1. Trigger workflow with ...
2. Action creates ...
3. Action fails with ...
validations:
required:true
- type:textarea
id:logs
attributes:
label:Relevant logs
description:Paste the relevant error output or run URL
render:shell
validations:
required:true
- type:textarea
id:additional
attributes:
label:Additional context
description:Any extra environment, token, ruleset, or asset details
This repository is maintained as a small, user-facing GitHub Action with a relatively wide compatibility surface.
Optimize for stability, reproducibility, and clear user value over broad rewrites.
## Core Rules
- Prefer narrow behavior fixes over structural churn.
- Reproduce current behavior on `master` before changing code.
- Treat GitHub platform behavior as distinct from action behavior.
If GitHub controls the outcome, prefer docs or clearer errors over brittle workarounds.
- Do not revive stale PRs mechanically.
Reuse the idea if it still has value, but reimplement on top of current `master`.
- Avoid standalone refactors with no clear user-facing benefit.
## Current Architecture
-`src/main.ts` is the orchestration layer: parse config, validate inputs, create/update release, upload assets, finalize, set outputs.
-`src/github.ts` owns release semantics: lookup, create/update/finalize, asset upload, race handling, and GitHub API interaction.
-`src/util.ts` owns parsing and path normalization.
- Keep behavior-specific logic in `src/github.ts` or `src/util.ts`; avoid growing `src/main.ts` with ad-hoc feature branches.
## Bug-Fix Workflow
- Reproduce the issue against current `master` first.
- When available, use the companion consumer harness repo `action-gh-release-test`.
- Capture exact workflow run URLs and release URLs before claiming a fix.
- If the issue is really a docs/usage or platform-limit case, document it and close it as such instead of forcing a code change.
- If a historical issue no longer reproduces on current `master`, prefer a short closeout note that asks the reporter to open a fresh issue if they still see it.
## Feature Triage
- Ship features only when there is clear user value or repeated demand.
- Small convenience features are fine, but they should stay small.
- Weak-demand features should not expand parsing complexity, cross-platform ambiguity, or maintenance surface.
- For old feature PRs:
- check whether current `master` already covers the behavior
- prefer a tiny docs clarification if the behavior exists but is poorly explained
- close stale feature PRs when the idea is obsolete, low-value, or badly shaped for the current codebase
## Contract Sync
When behavior changes, keep the external contract in sync:
- update `README.md`
- update `action.yml`
- update tests under `__tests__/`
- regenerate `dist/index.js` with `npm run build`
Docs-only changes do not need `dist/index.js` regeneration.
## Verification
For code changes, run:
-`npm run fmtcheck`
-`npm run typecheck`
-`npm run build`
-`npm test`
For behavior changes, also run the relevant external regression workflow(s) in `action-gh-release-test` against the exact ref under test.
## Release and Triage Conventions
- Keep PR labels accurate. Release notes depend on them.
- bug fixes: `bug`
- docs-only changes: `documentation`
- additive features: `feature` or `enhancement`
- dependency updates: `dependencies`
- Follow [RELEASE.md](RELEASE.md) for version bumps, changelog updates, tagging, and release publication.
- Prefer manual issue/PR closeouts with a short rationale over implicit assumptions.
- Do not auto-close old PRs or issues through unrelated docs PRs.
## Implementation Preferences
- Preserve the current upload/finalize flow unless there is strong evidence it needs to change.
- Prefer upload-time semantics over filesystem mutation.
- Be careful with parsing changes around `files`, path handling, and Windows compatibility.
- Be careful with race-condition fixes; verify both local tests and consumer-repo concurrency harnesses.
- Do not assume a refactor is safe just because tests are green. This action’s behavior is heavily shaped by GitHub API edge cases.
`3.0.0` is a major release that moves the action runtime from Node 20 to Node 24.
Use `v3` on GitHub-hosted runners and self-hosted fleets that already support the
Node 24 Actions runtime. If you still need the last Node 20-compatible line, stay on
`v2.6.2`.
## What's Changed
### Other Changes 🔄
* Move the action runtime and bundle target to Node 24
* Update `@types/node` to the Node 24 line and allow future Dependabot updates
* Keep the floating major tag on `v3`; `v2` remains pinned to the latest `2.x` release
## 2.6.2
## What's Changed
### Other Changes 🔄
* chore(deps): bump picomatch from 4.0.3 to 4.0.4 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/775
* chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/777
* chore(deps): bump vite from 8.0.0 to 8.0.5 by @dependabot[bot] in https://github.com/softprops/action-gh-release/pull/781
## 2.6.1
`2.6.1` is a patch release focused on restoring linked discussion thread creation when
`discussion_category_name` is set. It fixes `#764`, where the draft-first publish flow
stopped carrying the discussion category through the final publish step.
If you still hit an issue after upgrading, please open a report with the bug template and include a minimal repro or sanitized workflow snippet where possible.
## What's Changed
### Bug fixes 🐛
* fix: preserve discussion category on publish by @chenrui333 in https://github.com/softprops/action-gh-release/pull/765
## 2.6.0
`2.6.0` is a minor release centered on `previous_tag` support for `generate_release_notes`,
which lets workflows pin GitHub's comparison base explicitly instead of relying on the default range.
It also includes the recent concurrent asset upload recovery fix, a `working_directory` docs sync,
a checked-bundle freshness guard for maintainers, and clearer immutable-prerelease guidance where
GitHub platform behavior imposes constraints on how prerelease asset uploads can be published.
If you still hit an issue after upgrading, please open a report with the bug template and include a minimal repro or sanitized workflow snippet where possible.
## What's Changed
### Exciting New Features 🎉
* feat: support previous_tag for generate_release_notes by @pocesar in https://github.com/softprops/action-gh-release/pull/372
### Bug fixes 🐛
* fix: recover concurrent asset metadata 404s by @chenrui333 in https://github.com/softprops/action-gh-release/pull/760
### Other Changes 🔄
* docs: clarify reused draft release behavior by @chenrui333 in https://github.com/softprops/action-gh-release/pull/759
* docs: clarify working_directory input by @chenrui333 in https://github.com/softprops/action-gh-release/pull/761
* ci: verify dist bundle freshness by @chenrui333 in https://github.com/softprops/action-gh-release/pull/762
* fix: clarify immutable prerelease uploads by @chenrui333 in https://github.com/softprops/action-gh-release/pull/763
## 2.5.3
`2.5.3` is a patch release focused on the remaining path-handling and release-selection bugs uncovered after `2.5.2`.
It fixes `#639`, `#571`, `#280`, `#614`, `#311`, `#403`, and `#368`.
It also adds documentation clarifications for `#541`, `#645`, `#542`, `#393`, and `#411`,
where the current behavior is either usage-sensitive or constrained by GitHub platform limits rather than an action-side runtime bug.
If you still hit an issue after upgrading, please open a report with the bug template and include a minimal repro or sanitized workflow snippet where possible.
## What's Changed
### Bug fixes 🐛
* fix: prefer token input over GITHUB_TOKEN by @chenrui333 in https://github.com/softprops/action-gh-release/pull/751
* fix: clean up duplicate drafts after canonicalization by @chenrui333 in https://github.com/softprops/action-gh-release/pull/753
* fix: support Windows-style file globs by @chenrui333 in https://github.com/softprops/action-gh-release/pull/754
* fix: normalize refs-tag inputs by @chenrui333 in https://github.com/softprops/action-gh-release/pull/755
* fix: expand tilde file paths by @chenrui333 in https://github.com/softprops/action-gh-release/pull/756
### Other Changes 🔄
* docs: clarify token precedence by @chenrui333 in https://github.com/softprops/action-gh-release/pull/752
* docs: clarify GitHub release limits by @chenrui333 in https://github.com/softprops/action-gh-release/pull/758
* documentation clarifications for empty-token handling, `preserve_order`, and special-character asset filename behavior
## 2.5.2
`2.5.2` is a patch release focused on the remaining release-creation and prerelease regressions in the `2.5.x` bug-fix cycle.
It fixes `#705`, fixes `#708`, fixes `#740`, fixes `#741`, and fixes `#722`.
same-filename concurrent uploads, and blocked-tag cleanup behavior.
If you still hit an issue after upgrading, please open a report with the bug template and include a minimal repro or sanitized workflow snippet where possible.
## What's Changed
### Bug fixes 🐛
* fix: canonicalize releases after concurrent create by @chenrui333 in https://github.com/softprops/action-gh-release/pull/746
* fix: preserve prereleased events for prereleases by @chenrui333 in https://github.com/softprops/action-gh-release/pull/748
* fix: restore dotfile asset labels by @chenrui333 in https://github.com/softprops/action-gh-release/pull/749
* fix: handle upload already_exists races across workflows by @api2062 in https://github.com/softprops/action-gh-release/pull/745
* fix: clean up orphan drafts when tag creation is blocked by @chenrui333 in https://github.com/softprops/action-gh-release/pull/750
## 2.5.1
`2.5.1` is a patch release focused on regressions introduced in `2.5.0` and on release lookup reliability.
It fixes `#713`, addresses `#703`, and fixes `#724`. Regression testing shows that
current `master` no longer reproduces the finalize-race behavior reported in `#704` and `#709`.
## What's Changed
### Bug fixes 🐛
* fix: fetch correct asset URL after finalization; test; some refactoring by @pzhlkj6612 in https://github.com/softprops/action-gh-release/pull/738
* fix: release marked as 'latest' despite make_latest: false by @Boshen in https://github.com/softprops/action-gh-release/pull/715
* fix: use getReleaseByTag API instead of iterating all releases by @kim-em in https://github.com/softprops/action-gh-release/pull/725
### Other Changes 🔄
* dependency updates, including the ESM/runtime compatibility refresh in https://github.com/softprops/action-gh-release/pull/731
## 2.5.0
## What's Changed
### Exciting New Features 🎉
* feat: mark release as draft until all artifacts are uploaded by @dumbmoron in https://github.com/softprops/action-gh-release/pull/692
### Other Changes 🔄
* dependency updates
## 2.4.2
## What's Changed
### Exciting New Features 🎉
* feat: Ensure generated release notes cannot be over 125000 characters by @BeryJu in https://github.com/softprops/action-gh-release/pull/684
### Other Changes 🔄
* dependency updates
## 2.4.1
## What's Changed
### Other Changes 🔄
* fix(util): support brace expansion globs containing commas in parseInputFiles by @Copilot in https://github.com/softprops/action-gh-release/pull/672
* fix: gracefully fallback to body when body_path cannot be read by @Copilot in https://github.com/softprops/action-gh-release/pull/671
## 2.4.0
## What's Changed
### Exciting New Features 🎉
* feat(action): respect working_directory for files globs by @stephenway in https://github.com/softprops/action-gh-release/pull/667
## 2.3.4
## What's Changed
### Bug fixes 🐛
* fix(action): handle 422 already_exists race condition by @stephenway in https://github.com/softprops/action-gh-release/pull/665
### Other Changes 🔄
- dependency updates
## 2.3.3
## What's Changed
### Exciting New Features 🎉
* feat: add input option `overwrite_files` by @asfernandes in https://github.com/softprops/action-gh-release/pull/343
### Other Changes 🔄
- dependency updates
## 2.3.2
* fix: revert fs `readableWebStream` change
## 2.3.1
### Bug fixes 🐛
* fix: fix file closing issue by @WailGree in https://github.com/softprops/action-gh-release/pull/629
## 2.3.0
* Migrate from jest to vitest
* Replace `mime` with `mime-types`
* Bump to use node 24
* Dependency updates
## 2.2.2
## What's Changed
### Bug fixes 🐛
* fix: updating release draft status from true to false by @galargh in https://github.com/softprops/action-gh-release/pull/316
### Other Changes 🔄
* chore: simplify ref_type test by @steinybot in https://github.com/softprops/action-gh-release/pull/598
* fix(docs): clarify the default for tag_name by @muzimuzhi in https://github.com/softprops/action-gh-release/pull/599
* test(release): add unit tests when searching for a release by @rwaskiewicz in https://github.com/softprops/action-gh-release/pull/603
* dependency updates
## 2.2.1
## What's Changed
### Bug fixes 🐛
* fix: big file uploads by @xen0n in https://github.com/softprops/action-gh-release/pull/562
### Other Changes 🔄
* chore(deps): bump @types/node from 22.10.1 to 22.10.2 by @dependabot in https://github.com/softprops/action-gh-release/pull/559
* chore(deps): bump @types/node from 22.10.2 to 22.10.5 by @dependabot in https://github.com/softprops/action-gh-release/pull/569
* chore: update error and warning messages for not matching files in files field by @ytimocin in https://github.com/softprops/action-gh-release/pull/568
## 2.2.0
## What's Changed
### Exciting New Features 🎉
* feat: read the release assets asynchronously by @xen0n in https://github.com/softprops/action-gh-release/pull/552
### Bug fixes 🐛
* fix(docs): clarify the default for tag_name by @alexeagle in https://github.com/softprops/action-gh-release/pull/544
### Other Changes 🔄
* chore(deps): bump typescript from 5.6.3 to 5.7.2 by @dependabot in https://github.com/softprops/action-gh-release/pull/548
* chore(deps): bump @types/node from 22.9.0 to 22.9.4 by @dependabot in https://github.com/softprops/action-gh-release/pull/547
* chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 by @dependabot in https://github.com/softprops/action-gh-release/pull/545
* chore(deps): bump @vercel/ncc from 0.38.2 to 0.38.3 by @dependabot in https://github.com/softprops/action-gh-release/pull/543
* chore(deps): bump prettier from 3.3.3 to 3.4.1 by @dependabot in https://github.com/softprops/action-gh-release/pull/550
* chore(deps): bump @types/node from 22.9.4 to 22.10.1 by @dependabot in https://github.com/softprops/action-gh-release/pull/551
* chore(deps): bump prettier from 3.4.1 to 3.4.2 by @dependabot in https://github.com/softprops/action-gh-release/pull/554
## 2.1.0
## What's Changed
### Exciting New Features 🎉
* feat: add support for release assets with multiple spaces within the name by @dukhine in https://github.com/softprops/action-gh-release/pull/518
* feat: preserve upload order by @richarddd in https://github.com/softprops/action-gh-release/pull/500
### Other Changes 🔄
* chore(deps): bump @types/node from 22.8.2 to 22.8.7 by @dependabot in https://github.com/softprops/action-gh-release/pull/539
## 2.0.9
- maintenance release with updated dependencies
## 2.0.8
### Other Changes 🔄
* chore(deps): bump prettier from 2.8.0 to 3.3.3 by @dependabot in https://github.com/softprops/action-gh-release/pull/480
* chore(deps): bump @types/node from 20.14.9 to 20.14.11 by @dependabot in https://github.com/softprops/action-gh-release/pull/483
* chore(deps): bump @octokit/plugin-throttling from 9.3.0 to 9.3.1 by @dependabot in https://github.com/softprops/action-gh-release/pull/484
* chore(deps): bump glob from 10.4.2 to 11.0.0 by @dependabot in https://github.com/softprops/action-gh-release/pull/477
* refactor: write jest config in ts by @chenrui333 in https://github.com/softprops/action-gh-release/pull/485
* chore(deps): bump @actions/github from 5.1.1 to 6.0.0 by @dependabot in https://github.com/softprops/action-gh-release/pull/470
## 2.0.7
### Bug fixes 🐛
* Fix missing update release body by @FirelightFlagboy in https://github.com/softprops/action-gh-release/pull/365
### Other Changes 🔄
* Bump @octokit/plugin-retry from 4.0.3 to 7.1.1 by @dependabot in https://github.com/softprops/action-gh-release/pull/443
* Bump typescript from 4.9.5 to 5.5.2 by @dependabot in https://github.com/softprops/action-gh-release/pull/467
* Bump @types/node from 20.14.6 to 20.14.8 by @dependabot in https://github.com/softprops/action-gh-release/pull/469
* Bump @types/node from 20.14.8 to 20.14.9 by @dependabot in https://github.com/softprops/action-gh-release/pull/473
* Bump typescript from 5.5.2 to 5.5.3 by @dependabot in https://github.com/softprops/action-gh-release/pull/472
* Bump ts-jest from 29.1.5 to 29.2.2 by @dependabot in https://github.com/softprops/action-gh-release/pull/479
* docs: document that existing releases are updated by @jvanbruegge in https://github.com/softprops/action-gh-release/pull/474
## 2.0.6
- maintenance release with updated dependencies
## 2.0.5
- Factor in file names with spaces when upserting files [#446](https://github.com/softprops/action-gh-release/pull/446) via [@MystiPanda](https://github.com/MystiPanda)
- Improvements to error handling [#449](https://github.com/softprops/action-gh-release/pull/449) via [@till](https://github.com/till)
## 2.0.4
- Minor follow up to [#417](https://github.com/softprops/action-gh-release/pull/417). [#425](https://github.com/softprops/action-gh-release/pull/425)
## 2.0.3
- Declare `make_latest` as an input field in `action.yml` [#419](https://github.com/softprops/action-gh-release/pull/419)
## 2.0.2
- Revisit approach to [#384](https://github.com/softprops/action-gh-release/pull/384) making unresolved pattern failures opt-in [#417](https://github.com/softprops/action-gh-release/pull/417)
## 2.0.1
- Add support for make_latest property [#304](https://github.com/softprops/action-gh-release/pull/304) via [@samueljseay](https://github.com/samueljseay)
- Fail run if files setting contains invalid patterns [#384](https://github.com/softprops/action-gh-release/pull/384) via [@rpdelaney](https://github.com/rpdelaney)
- Add support for proxy env variables (don't use node-fetch) [#386](https://github.com/softprops/action-gh-release/pull/386/) via [@timor-raiman](https://github.com/timor-raiman)
- Suppress confusing warning when input_files is empty [#389](https://github.com/softprops/action-gh-release/pull/389) via [@Drowze](https://github.com/Drowze)
## 2.0.0
-`2.0.0`!? this release corrects a disjunction between git tag versions used in the marketplace and the versions listed in this file. Previous versions should have really been 1.\*. Going forward this should be better aligned.
- Upgrade action.yml declaration to node20 to address deprecations
## 0.1.15
- Upgrade to action.yml declaration to node16 to address deprecations
- Upgrade dependencies
- Add `asset` output as a JSON array containing information about the uploaded assets
## 0.1.14
- provides a new workflow input option `generate_release_notes` which when set to true will automatically generate release notes for you based on GitHub activity [#179](https://github.com/softprops/action-gh-release/pull/179). Please see the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information
## 0.1.13
- fix issue with multiple runs concatenating release bodies [#145](https://github.com/softprops/action-gh-release/pull/145)
## 0.1.12
- fix bug leading to empty strings substituted for inputs users don't provide breaking api calls [#144](https://github.com/softprops/action-gh-release/pull/144)
## 0.1.11
- better error message on release create failed [#143](https://github.com/softprops/action-gh-release/pull/143)
## 0.1.10
- fixed error message formatting for file uploads
@@ -12,7 +365,7 @@
## 0.1.8
- address recent warnings in assert upload api as well as introduce asset upload overrides, allowing for multiple runs for the same release with the same named asserts [#134](https://github.com/softprops/action-gh-release/pull/134)
- fix backwards compatibility with `GITHUB_TOKEN` resolution. `GITHUB_TOKEN` is no resolved first from an env varibale and then from and input [#133](https://github.com/softprops/action-gh-release/pull/133)
- fix backwards compatibility with `GITHUB_TOKEN` resolution. `GITHUB_TOKEN` is now resolved first from an env variable and then from an input [#133](https://github.com/softprops/action-gh-release/pull/133)
- trim white space in provided `tag_name` [#130](https://github.com/softprops/action-gh-release/pull/130)
## 0.1.7
@@ -25,14 +378,14 @@
This is a release catch up have a hiatus. Future releases will happen more frequently
- Add 'fail_on_unmatched_files' input, useful for catching cases were your `files` input does not actually match what you expect [#55](https://github.com/softprops/action-gh-release/pull/55)
- Add 'fail_on_unmatched_files' input, useful for catching cases where your `files` input does not actually match what you expect [#55](https://github.com/softprops/action-gh-release/pull/55)
- Add `repository` input, useful for creating a release in an external repository [#61](https://github.com/softprops/action-gh-release/pull/61)
- Add release `id` to outputs, useful for refering to release in workflow steps following the step that uses this action [#60](https://github.com/softprops/action-gh-release/pull/60)
- Add release `id` to outputs, useful for referring to release in workflow steps following the step that uses this action [#60](https://github.com/softprops/action-gh-release/pull/60)
- Add `upload_url` as action output, useful for managing uploads separately [#75](https://github.com/softprops/action-gh-release/pull/75)
- Support custom `target_commitish` value, useful to customize the default [#76](https://github.com/softprops/action-gh-release/pull/76)
- fix `body_path` input first then fall back on `body` input. this was the originally documented precedence but was implemened the the opposite order! [#85](https://github.com/softprops/action-gh-release/pull/85)
- fix `body_path` input first then fall back on `body` input. This was the originally documented precedence but was implemented in the opposite order! [#85](https://github.com/softprops/action-gh-release/pull/85)
- Retain original release info if the keys are not set, useful for filling in blanks for a release you've already started separately [#109](https://github.com/softprops/action-gh-release/pull/109)
- Limit number of times github api request to create a release is retried, useful for avoiding eating up your rate limit and action minutes do to either an invalid token or other circumstance causing the api call to fail [#111](https://github.com/softprops/action-gh-release/pull/111)
- Limit number of times github api request to create a release is retried, useful for avoiding eating up your rate limit and action minutes due to either an invalid token or other circumstance causing the api call to fail [#111](https://github.com/softprops/action-gh-release/pull/111)
## 0.1.5
@@ -42,7 +395,7 @@ This is a release catch up have a hiatus. Future releases will happen more frequ
- Added support for updating releases body [#36](https://github.com/softprops/action-gh-release/pull/36)
- Steps can now access the url of releases with the `url` output of this Action [#28](https://github.com/softprops/action-gh-release/pull/28)
- Added basic GitHub API retry support to manage API turbulance [#26](https://github.com/softprops/action-gh-release/pull/26)
- Added basic GitHub API retry support to manage API turbulence [#26](https://github.com/softprops/action-gh-release/pull/26)
## 0.1.3
@@ -57,7 +410,7 @@ This is now fixed.
- Add support for newline-delimited asset list [#18](https://github.com/softprops/action-gh-release/pull/18)
GitHub actions inputs don't inherently support lists of things and one might like to append a list of files to include in a release. Previously this was possible using a comma-delimited list of asset path patterns to upload. You can now provide these as a newline delimieted list for better readability
GitHub actions inputs don't inherently support lists of things and one might like to append a list of files to include in a release. Previously this was possible using a comma-delimited list of asset path patterns to upload. You can now provide these as a newline delimited list for better readability
@@ -29,6 +39,9 @@ Typically usage of this action involves adding a step to a build that
is gated pushes to git tags. You may find `step.if` field helpful in accomplishing this
as it maximizes the reuse value of your workflow for non-tag pushes.
`v3` requires a GitHub Actions runtime that supports Node 24. If you still need the
last Node 20-compatible line, stay on `v2.6.2`.
Below is a simple example of `step.if` tag gating
```yaml
@@ -41,10 +54,10 @@ jobs:
runs-on:ubuntu-latest
steps:
- name:Checkout
uses:actions/checkout@v2
uses:actions/checkout@v6
- name:Release
uses:softprops/action-gh-release@v1
if:startsWith(github.ref, 'refs/tags/')
uses:softprops/action-gh-release@v3
if:github.ref_type == 'tag'
```
You can also use push config tag filter
@@ -62,9 +75,9 @@ jobs:
runs-on:ubuntu-latest
steps:
- name:Checkout
uses:actions/checkout@v2
uses:actions/checkout@v6
- name:Release
uses:softprops/action-gh-release@v1
uses:softprops/action-gh-release@v3
```
### ⬆️ Uploading release assets
@@ -75,6 +88,7 @@ GitHub release and all are optional.
A common case for GitHub releases is to upload your binary after its been validated and packaged.
Use the `with.files` input to declare a newline-delimited list of glob expressions matching the files
you wish to upload to GitHub releases. If you'd like you can just list the files by name directly.
If a tag already has a GitHub release, the existing release will be updated with the release assets.
Below is an example of uploading a single asset named `Release.txt`
@@ -88,14 +102,14 @@ jobs:
runs-on:ubuntu-latest
steps:
- name:Checkout
uses:actions/checkout@v2
uses:actions/checkout@v6
- name:Build
run:echo ${{ github.sha }} > Release.txt
- name:Test
run:cat Release.txt
- name:Release
uses:softprops/action-gh-release@v1
if:startsWith(github.ref, 'refs/tags/')
uses:softprops/action-gh-release@v3
if:github.ref_type == 'tag'
with:
files:Release.txt
```
@@ -112,21 +126,37 @@ jobs:
runs-on:ubuntu-latest
steps:
- name:Checkout
uses:actions/checkout@v2
uses:actions/checkout@v6
- name:Build
run:echo ${{ github.sha }} > Release.txt
- name:Test
run:cat Release.txt
- name:Release
uses:softprops/action-gh-release@v1
if:startsWith(github.ref, 'refs/tags/')
uses:softprops/action-gh-release@v3
if:github.ref_type == 'tag'
with:
files:|
Release.txt
LICENSE
```
> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That let's you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
> **⚠️ Note:** Notice the `|` in the yaml syntax above ☝️. That lets you effectively declare a multi-line yaml string. You can learn more about multi-line yaml syntax [here](https://yaml-multiline.info)
> **⚠️ Note for Windows:** Both `\` and `/` path separators are accepted in `files` globs. If you need to match a literal glob metacharacter such as `[` or `]`, keep escaping the metacharacter itself in the pattern.
If your release assets are generated under a subdirectory, set `working_directory`
and keep the `files` patterns relative to that directory.
```yaml
- name:Release
uses:softprops/action-gh-release@v3
if:github.ref_type == 'tag'
with:
working_directory:dist
files:|
Release.txt
checksums/*.txt
```
### 📝 External release notes
@@ -144,19 +174,34 @@ jobs:
runs-on:ubuntu-latest
steps:
- name:Checkout
uses:actions/checkout@v2
uses:actions/checkout@v6
- name:Generate Changelog
run:echo "# Good things have arrived" > ${{ github.workspace }}-CHANGELOG.txt
- name:Release
uses:softprops/action-gh-release@v1
if:startsWith(github.ref, 'refs/tags/')
uses:softprops/action-gh-release@v3
if:github.ref_type == 'tag'
with:
body_path:${{ github.workspace }}-CHANGELOG.txt
repository:my_gh_org/my_gh_repo
# note you'll typically need to create a personal access token
# with permissions to create releases in the other repo
# with permissions to create releases in the other repo.
# A non-empty explicit token overrides GITHUB_TOKEN.
# Omit the input to use github.token; passing "" treats the token as unset.
token:${{ secrets.CUSTOM_GITHUB_TOKEN }}
env:
GITHUB_REPOSITORY:my_gh_org/my_gh_repo
```
When you use GitHub's built-in `generate_release_notes` support, you can optionally
pin the comparison base explicitly with `previous_tag`. This is useful when the default
comparison range does not match the release series you want to publish.
| `body` | String | Text communicating notable changes in this release |
| `body_path` | String | Path to load text communicating notable changes in this release |
| `draft` | Boolean | Indicator of whether or not this release is a draft |
| `prerelease` | Boolean | Indicator of whether or not is a prerelease |
| `files` | String | Newline-delimited globs of paths to assets to upload for release |
| `name` | String | Name of the release. defaults to tag name |
| `tag_name` | String | Name of a tag. defaults to `github.ref` |
| `fail_on_unmatched_files` | Boolean | Indicator of whether to fail if any of the `files` globs match nothing |
| `repository` | String | Name of a target repository in `<owner>/<repo>` format. Defaults to GITHUB_REPOSITORY env variable |
| `target_commitish` | String | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. |
| `token` | String | Secret GitHub Personal Access Token. Defaults to `${{ github.token }}` |
| `discussion_category_name` | String | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository) |
| `body` | String | Text communicating notable changes in this release |
| `body_path` | String | Path to load text communicating notable changes in this release |
| `draft` | Boolean | Keep the release as a draft. Defaults to false. When reusing an existing draft release, set this to true to keep it draft; omit it to publish after upload. |
| `prerelease` | Boolean | Indicator of whether or not is a prerelease |
| `preserve_order` | Boolean | Upload assets sequentially in the provided order. This controls the action's upload behavior, but it does not control the final asset ordering that GitHub may display on the release page or return from the Releases API. |
| `files` | String | Newline-delimited globs of paths to assets to upload for release. Escape glob metacharacters when you need to match a literal filename that contains them, such as `[` or `]`. `~/...` expands to the runner home directory. On Windows, both `\` and `/` separators are accepted. GitHub may normalize raw asset filenames that contain special characters; the action restores the asset label when possible, but the final download name remains GitHub-controlled. |
| `working_directory` | String | Base directory to resolve `files` globs against. Use this when release assets live under a subdirectory. If omitted, the action resolves `files` from `${{ github.workspace }}`. |
| `overwrite_files` | Boolean | Indicator of whether files should be overwritten when they already exist. Defaults to true |
| `name` | String | Name of the release. defaults to tag name |
| `tag_name` | String | Name of a tag. defaults to `github.ref_name`. `refs/tags/<name>` values are normalized to `<name>`. |
| `fail_on_unmatched_files` | Boolean | Indicator of whether to fail if any of the `files` globs match nothing |
| `repository` | String | Name of a target repository in `<owner>/<repo>` format. Defaults to GITHUB_REPOSITORY env variable |
| `target_commitish` | String | Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Defaults to repository default branch. When creating a new tag for an older commit, `github.token` may not have permission to create the ref; use a PAT or another token with sufficient contents permissions if you hit `403 Resource not accessible by integration`. |
| `token` | String | Authorized GitHub token or PAT. Defaults to `${{ github.token }}` when omitted. A non-empty explicit token overrides `GITHUB_TOKEN`. Passing `""` treats the token as explicitly unset, so omit the input entirely or use an expression such as `${{ inputs.token || github.token }}` when wrapping this action in a composite action. |
| `discussion_category_name` | String | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository) |
| `generate_release_notes` | Boolean | Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information |
| `previous_tag` | String | Optional. When `generate_release_notes` is enabled, use this tag as GitHub's `previous_tag_name` comparison base. If omitted, GitHub chooses the comparison base automatically. |
| `append_body` | Boolean | Append to existing body instead of overwriting it |
| `make_latest` | String | Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api defaults if not provided |
💡 When providing a `body` and `body_path` at the same time, `body_path` will be
attempted first, then falling back on `body` if the path can not be read from.
💡 When the release info keys (such as `name`, `body`,`draft`,`prerelease`, etc.)
are not explicitly set and there is already an existing release for the tag, the
release will retain its original info.
💡 When the release info keys (such as `name`, `body`, `prerelease`, etc.) are not
explicitly set and there is already an existing release for the tag, the release
will retain its original info.
💡 Draft status is handled separately during finalization. If the action reuses an
existing draft release, set `draft: true` to keep it draft; if `draft` is omitted,
the action will publish that draft after uploading assets.
💡 GitHub immutable releases lock assets after publication. Standard releases in this
action already upload assets before publishing, but prereleases stay published by
default so `release.prereleased` workflows keep firing. On an immutable-release
repository, use `draft: true` for prereleases that upload assets, then publish that
draft later and subscribe downstream workflows to `release.published`.
💡 `files` is glob-based, so literal filenames that contain glob metacharacters such as
`[` or `]` must be escaped in the pattern.
💡 GitHub may normalize or rewrite uploaded asset filenames that contain special or
non-ASCII characters. This action uploads the requested file, but it cannot force the
final asset name that GitHub stores or returns from the Releases API. In particular,
4-byte Unicode characters such as emoji cannot currently be restored via asset labels.
#### outputs
The following outputs can be accessed via `${{ steps.<step-id>.outputs }}` from this action
| `url` | String | Github.com URL for the release |
| `id` | String | Release ID |
| `upload_url` | String | URL for uploading assets to the release |
| `assets` | String | JSON array containing information about each updated (newly uploaded or overwritten) asset, in the format given [here](https://docs.github.com/en/rest/releases/assets#get-a-release-asset) (minus the `uploader` field) |
As an example, you can use `${{ fromJSON(steps.<step-id>.outputs.assets)[0].browser_download_url }}` to get the download URL of the first asset.
#### environment variables
@@ -208,4 +281,26 @@ The following `step.env` keys are allowed as a fallback but deprecated in favor
> **⚠️ Note:** This action was previously implemented as a Docker container, limiting its use to GitHub Actions Linux virtual environments only. With recent releases, we now support cross platform usage. You'll need to remove the `docker://` prefix in these versions
### Permissions
This Action requires the following permissions on the GitHub integration token:
```yaml
permissions:
contents:write
```
When used with `discussion_category_name`, additional permission is needed:
```yaml
permissions:
contents:write
discussions:write
```
[GitHub token permissions](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) can be set for an individual job, workflow, or for Actions as a whole.
Note that if you intend to run workflows on the release event (`on: { release: { types: [published] } }`), you need to use
a personal access token for this action, as the [default `secrets.GITHUB_TOKEN` does not trigger another workflow](https://github.com/actions/create-release/issues/71).
8. Move the floating major tag to the new release tag.
- For the current major line, run `npm run updatetag` to move `v3`.
- Keep `v2` pinned to the latest `2.x` release for consumers that still need the Node 20 runtime.
- Verify the floating tag points at the same commit as the new full tag.
9. Create the GitHub release from the new tag.
- Prefer the release body from [CHANGELOG.md](CHANGELOG.md), then let GitHub append generated notes only if they add value.
- Verify the release shows the expected tag, title, notes, and attached artifacts.
## Notes
- Behavior changes should already have matching updates in [README.md](README.md), [action.yml](action.yml), tests, and `dist/index.js` before release prep begins.
- Docs-only releases still need an intentional changelog entry and version bump decision.
- If a release is mainly bug fixes, keep the title and summary patch-oriented; do not bury the actual fixes under dependency noise.
description:"Gives the release a custom name. Defaults to tag name"
required:false
tag_name:
description:"Gives a tag name. Defaults to github.GITHUB_REF"
description:"Gives a tag name. Defaults to github.ref_name. refs/tags/<name> values are normalized to <name>."
required:false
draft:
description:"Creates a draft release. Defaults to false"
description:"Keeps the release as a draft. Defaults to false. When reusing an existing draft release, set this to true to keep it draft; omit it to publish after upload. On immutable-release repositories, use this for prereleases that upload assets and publish the draft later."
required:false
prerelease:
description:"Identify the release as a prerelease. Defaults to false"
required:false
files:
description:"Newline-delimited list of path globs for asset files to upload"
preserve_order:
description:"Upload artifacts sequentially in the provided order. This does not control the final display order GitHub uses for release assets."
required:false
files:
description:"Newline-delimited list of path globs for asset files to upload. Escape glob metacharacters when matching literal filenames that contain them. `~/...` expands to the runner home directory. On Windows, both \\ and / path separators are accepted. GitHub may normalize raw asset filenames that contain special characters; the action restores the asset label when possible, but the final download name remains GitHub-controlled."
required:false
working_directory:
description:"Base directory to resolve 'files' globs against. Defaults to the workspace root used by the action step."
required:false
overwrite_files:
description:"Overwrite existing files with the same name. Defaults to true"
required:false
default:'true'
fail_on_unmatched_files:
description:"Fails if any of the `files` globs match nothing. Defaults to false"
required:false
@@ -31,17 +41,30 @@ inputs:
description:"Repository to make releases against, in <owner>/<repo> format"
required:false
token:
description:"Authorized secret GitHub Personal Access Token. Defaults to github.token"
description:"Authorized GitHub token or PAT. Defaults to github.token when omitted. A non-empty explicit token overrides GITHUB_TOKEN. Passing an empty string treats the token as unset."
required:false
default:${{ github.token }}
target_commitish:
description:"Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA."
description:"Commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. When creating a new tag for an older commit, `github.token` may not have permission to create the ref; use a PAT or another token with sufficient contents permissions if you hit 403 `Resource not accessible by integration`."
required:false
discussion_category_name:
description:"If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. If there is already a discussion linked to the release, this parameter is ignored."
required:false
generate_release_notes:
description:"Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes."
required:false
previous_tag:
description:"Optional. When generate_release_notes is enabled, use this tag as GitHub's previous_tag_name comparison base. If omitted, GitHub chooses the comparison base automatically."
required:false
default:""
append_body:
description:"Append to existing body instead of overwriting it. Default is false."
required:false
make_latest:
description:"Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Can be `true`, `false`, or `legacy`. Uses GitHub api default if not provided"
required:false
env:
"GITHUB_TOKEN": "As provided by Github Actions"
GITHUB_TOKEN:"As provided by Github Actions"
outputs:
url:
description:"URL to the Release HTML Page"
@@ -49,8 +72,10 @@ outputs:
description:"Release ID"
upload_url:
description:"URL for uploading assets to the release"
assets:
description:"JSON array containing information about each uploaded asset, in the format given [here](https://docs.github.com/en/rest/reference/repos#upload-a-release-asset--code-samples) (minus the `uploader` field)"
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
@@ -43,7 +45,7 @@
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
"types":["node","vitest/globals"],
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.