A GitHub/Gitea action for creating and managing releases across multiple platforms. This action is based on ncipollo/release-action but extends it to support GitHub, Gitea, and self-hosted Gitea instances.
- Multi-Platform Support: Works with GitHub, Gitea (including self-hosted instances)
- Auto-Detection: Automatically detects the platform from repository URL
- Full Feature Parity: Matches all features from ncipollo/release-action
- Create and update releases
- Upload artifacts with glob pattern support
- Draft and prerelease support
- Release body from file or input
- Generate release notes (GitHub only)
- Tag creation if missing
- Artifact replacement/removal
- Extensible Architecture: Easy to add support for additional platforms (GitLab, Bitbucket, etc.)
- Comprehensive Error Handling: Clear error messages and proper validation
The action automatically detects the platform from the repository URL, but you can also explicitly specify it:
- Explicit Platform: Set the
platforminput togithuborgitea - Auto-Detection: If not specified, the action will:
- Check if the repository URL contains
github.com→ GitHub - Check if the repository URL contains
gitea.ioor a custom domain → Gitea - Default to GitHub for GitHub Actions runners
- Check if the repository URL contains
name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: ${{ github.ref_name }}
token: ${{ secrets.GITHUB_TOKEN }}name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: LiquidLogicLabs/git-action-release@v2
with:
platform: 'gitea'
tag: ${{ github.ref_name }}
token: ${{ secrets.GITEA_TOKEN }}- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: 'v1.0.0'
artifacts: 'dist/*.zip,binaries/**/*'
replaces-artifacts: true
token: ${{ secrets.GITHUB_TOKEN }}- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: 'v1.0.0'
body-file: 'CHANGELOG.md'
token: ${{ secrets.GITHUB_TOKEN }}- uses: LiquidLogicLabs/git-action-release@v2
with:
platform: 'github' # or 'gitea'
tag: 'v1.0.0'
token: ${{ secrets.GITHUB_TOKEN }}| Input | Description | Required | Default |
|---|---|---|---|
platform |
Platform type (github or gitea). If not provided, will auto-detect from repository URL |
No | Auto-detect |
token |
Platform token for authentication | No | ${{ github.token }} |
| Input | Description | Required | Default |
|---|---|---|---|
tag |
Tag for the release. If omitted, the git ref will be used (if it is a tag) | No | - |
name |
Name for the release. If omitted, the tag will be used | No | - |
body |
Body for the release. Note: This input will have white space trimmed. Use body-file if you need a non-trivial markdown body |
No | - |
body-file |
Body file for the release. This should be the path to the file | No | - |
draft |
Marks this release as a draft release | No | false |
prerelease |
Marks this release as prerelease | No | false |
commit |
Commit reference. This will be used to create the tag if it does not exist | No | - |
| Input | Description | Required | Default |
|---|---|---|---|
artifacts |
Paths representing artifacts to upload. This may be a single path or a comma delimited list of paths (or globs) | No | - |
artifact-content-type |
The content type of the artifact | No | application/octet-stream |
replaces-artifacts |
Indicates if existing release artifacts should be replaced | No | true |
remove-artifacts |
Indicates if existing release artifacts should be removed before uploading | No | false |
artifact-errors-fail-build |
Indicates if artifact read or upload errors should fail the build | No | false |
| Input | Description | Required | Default |
|---|---|---|---|
allow-updates |
Indicates if we should update a release if it already exists | No | false |
skip-if-release-exists |
When enabled, the action will be skipped if a non-draft release already exists for the provided tag | No | false |
update-only-unreleased |
When allow-updates is enabled, this will fail the action if the release it is updating is not a draft or a prerelease |
No | false |
| Input | Description | Required | Default |
|---|---|---|---|
generate-release-notes |
Indicates if release notes should be automatically generated (GitHub only) | No | false |
generate-release-notes-previous-tag |
Previous tag to use when generating release notes. This will limit the release notes to changes between the two tags | No | - |
| Input | Description | Required | Default |
|---|---|---|---|
repository |
Repository in owner/repo format (e.g., LiquidLogicLabs/git-action-release). If provided, takes precedence over owner and repo inputs | No | - |
owner |
Optionally specify the owner of the repo where the release should be generated. Defaults to current repo owner | No | - |
repo |
Optionally specify the repo where the release should be generated. Defaults to current repo | No | - |
omit-body |
Indicates if the release body should be omitted | No | false |
omit-body-during-update |
Indicates if the release body should be omitted during updates | No | false |
omit-draft-during-update |
Indicates if the draft flag should be omitted during updates | No | false |
omit-name |
Indicates if the release name should be omitted | No | false |
omit-name-during-update |
Indicates if the release name should be omitted during updates | No | false |
omit-prerelease-during-update |
Indicates if the prerelease flag should be omitted during updates | No | false |
skip-certificate-check |
Skip TLS certificate verification for API calls (self-hosted instances) | No | false |
verbose |
Enable verbose debug logging | No | false |
| Output | Description |
|---|---|
id |
The identifier of the created release |
html-url |
The HTML URL of the release |
upload-url |
The URL for uploading assets to the release |
tarball-url |
The URL for downloading the release as a tarball (.tar.gz) |
zipball-url |
The URL for downloading the release as a zipball (.zip) |
assets |
JSON string containing a map of asset names to download URLs for uploaded assets |
Creating or updating releases requires contents: write. The job must have a token with sufficient scope (default GITHUB_TOKEN or GITEA_TOKEN is usually sufficient when the job has the right permissions).
name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Build artifacts
run: |
npm run build
npm run package
- name: Set release token
env:
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: echo "RELEASE_TOKEN set"
- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
body-file: CHANGELOG.md
artifacts: 'dist/*.zip,dist/*.tar.gz'
generate-release-notes: true
token: ${{ env.RELEASE_TOKEN }}name: Release
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Build artifacts
run: |
npm run build
npm run package
- name: Set release token (Gitea)
env:
RELEASE_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: echo "RELEASE_TOKEN set"
- uses: LiquidLogicLabs/git-action-release@v2
with:
platform: 'gitea'
tag: ${{ github.ref_name }}
name: Release ${{ github.ref_name }}
body-file: CHANGELOG.md
artifacts: 'dist/*.zip,dist/*.tar.gz'
token: ${{ env.RELEASE_TOKEN }}- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: 'v1.0.0'
draft: true
allow-updates: true
artifacts: 'build/*.zip'
token: ${{ secrets.GITHUB_TOKEN }}- uses: LiquidLogicLabs/git-action-release@v2
with:
tag: 'v1.0.0-beta.1'
prerelease: true
body: 'Beta release for testing'
token: ${{ secrets.GITHUB_TOKEN }}- Supports all features including automatic release notes generation
- Uses GitHub REST API v3
- Requires
contents: writepermission
- Supports most features except automatic release notes generation (Gitea API doesn't support this)
- Uses Gitea API v1
- Automatically detects Gitea URL from
GITHUB_SERVER_URLenvironment variable (available in Gitea Actions) - Requires repository access token with release permissions
When Gitea returns an empty response body on release creation, the action retries fetching the release by tag. You can tune the retry behavior with environment variables:
GITEA_RELEASE_LOOKUP_MAX_RETRIES(default:10)GITEA_RELEASE_LOOKUP_BASE_DELAY_MS(default:500)GITEA_RELEASE_LOOKUP_MAX_DELAY_MS(default:8000)
Example workflow configuration:
- uses: LiquidLogicLabs/git-action-release@v2
env:
GITEA_RELEASE_LOOKUP_MAX_RETRIES: '12'
GITEA_RELEASE_LOOKUP_BASE_DELAY_MS: '750'
GITEA_RELEASE_LOOKUP_MAX_DELAY_MS: '10000'
with:
platform: 'gitea'
tag: ${{ github.ref_name }}
token: ${{ secrets.GITEA_TOKEN }}If you're migrating from ncipollo/release-action, the action is largely compatible. The main differences are:
- Platform Detection: The action now auto-detects the platform, but you can override it
- Gitea Support: Added support for Gitea and self-hosted Gitea instances
- Additional Input:
platforminput for multi-platform support
To migrate:
- Replace
ncipollo/release-action@v1withLiquidLogicLabs/git-action-release@v2 - If using Gitea, add
platform: 'gitea'input (Gitea URL is auto-detected from environment) - All other inputs remain the same
- The action automatically masks tokens in logs using
core.setSecret() - Tokens are never logged or exposed
- Use GitHub Secrets or Gitea Secrets for storing tokens
- Use the least privilege principle when creating tokens
If platform detection fails, explicitly set the platform input:
platform: 'github' # or 'gitea'For self-hosted Gitea instances:
- Ensure
GITHUB_SERVER_URLenvironment variable is set correctly (this is automatically set by Gitea Actions) - Verify the token has release permissions
- Check network connectivity from the runner to your Gitea instance
- Ensure artifact paths are correct and files exist
- Check file permissions
- For large files, consider using a different upload mechanism
- Set
artifact-errors-fail-build: trueto fail fast on errors
This project includes comprehensive tests at multiple levels:
- Unit Tests: Test individual components in isolation
- Integration Tests (Mocked): Test components with mocked HTTP responses
- E2E Tests: Full end-to-end tests with real API calls
# Run unit tests
npm run test:unit
# Run integration tests (mocked)
npm run test:integration
# Run E2E tests (requires tokens)
export GITHUB_TOKEN="your-token"
export GITEA_TOKEN="your-token"
npm run test:e2e
# Run all tests (unit + integration, excludes E2E)
npm run test:allFor detailed testing information, see docs/TESTING.md.
Contributions are welcome! Please feel free to submit a Pull Request.
Before submitting:
- Run tests:
npm run test:all - Run linter:
npm run lint - Ensure all tests pass locally
This project is licensed under the MIT License - see the LICENSE file for details.
This action is based on ncipollo/release-action and extends it with multi-platform support. Special thanks to the original authors and contributors.