No description
  • Go 99.9%
  • Dockerfile 0.1%
Find a file
Vitaliy Vasylenko 0c68c56a0b
Some checks failed
release-please / release-please (push) Failing after 2m16s
fix: add write permissions and detect protected-branch push rejection
2026-06-15 08:14:25 -04:00
.forgejo fix: add write permissions and detect protected-branch push rejection 2026-06-15 08:14:25 -04:00
internal fix: add write permissions and detect protected-branch push rejection 2026-06-15 08:14:25 -04:00
.dockerignore feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
.gitignore fix: surface a clear error when the server rejects the release branch push 2026-06-11 10:49:09 -04:00
.golangci.yml feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
action.yml feat: add debug logging mode 2026-06-11 11:31:45 -04:00
Dockerfile feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
go.mod feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
go.sum feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
main.go feat: forgejo release-please action with conventional commits, monorepo and multi-language support 2026-06-09 12:02:35 -04:00
README.md fix: add write permissions and detect protected-branch push rejection 2026-06-15 08:14:25 -04:00

release-please for Forgejo

A Forgejo Actions replacement for googleapis/release-please-action. It automates releases from Conventional Commits: it maintains a release pull request that aggregates unreleased changes, and once that pull request is merged it creates the git tag and the Forgejo release.

The action keeps the same configuration files, inputs, and outputs as the original GitHub Action, so existing repositories can switch with minimal changes.

How it works

On every push to the target branch the action runs two flows in sequence.

flowchart TD
    A[Push to target branch] --> B{Release PR<br/>just merged?}
    B -->|Yes| C[Create tag and release<br/>from manifest version]
    B -->|No| D[Skip release flow]
    C --> E[Compute next version<br/>from conventional commits]
    D --> E
    E --> F{Any releasable<br/>commits?}
    F -->|Yes| G[Update changelog,<br/>version files, manifest]
    G --> H[Open or update<br/>release pull request]
    F -->|No| I[Do nothing]
  1. Release flow: if the most recently merged pull request came from the release branch, the action reads each package version from the manifest and creates the corresponding tag and release. This flow is idempotent: a release that already exists is skipped.
  2. Pull-request flow: the action parses the commits since the last release, computes the next version per package, regenerates the changelog and version files, and opens or updates the release pull request.

Version bumping

Versions follow Semantic Versioning. The bump is derived from the commit types since the last release.

Commit Bump Example version change
fix: patch 1.2.3 to 1.2.4
feat: minor 1.2.3 to 1.3.0
feat!: or BREAKING CHANGE: footer major 1.2.3 to 2.0.0
chore:, docs:, others none no release

While a package is in the 0.x.y range, breaking changes bump the minor component and features bump the patch component, matching release-please.

A specific version can be forced with the release-as input or a Release-As: x.y.z commit footer.

Usage

Create a workflow such as .forgejo/workflows/release-please.yml:

on:
  push:
    branches:
      - main

permissions:
  contents: write
  pull-requests: write

jobs:
  release-please:
    runs-on: docker
    steps:
      - uses: https://git.vitalvas.com/actions/release-please@v1
        with:
          release-type: go

The action uses the runner-provided token by default. For a single-package repository without a config file, set release-type and the action manages the root package using .release-please-manifest.json.

The job needs contents: write (push the release branch, create tags and releases) and pull-requests: write (open the release pull request). Note that this token is still subject to branch protection: if a protection rule blocks the Actions user from pushing the release-please--branches--* branches, allow that pattern (or whitelist the user) in the repository's branch protection settings, or pass a token with push rights via the token input.

Configuration files

For monorepos or fine-grained control, add a release-please-config.json and a .release-please-manifest.json to the target branch. The formats match release-please.

release-please-config.json:

{
  "release-type": "go",
  "include-component-in-tag": true,
  "packages": {
    "pkg/api": { "component": "api", "release-type": "go" },
    "pkg/web": { "component": "web", "release-type": "node" }
  }
}

.release-please-manifest.json records the last released version of each package:

{
  "pkg/api": "1.4.0",
  "pkg/web": "0.9.2"
}

File discovery

When the config-file / manifest-file inputs are not set, the action searches the target branch and uses the first file that exists. It looks in the repository root first, then .forgejo/, then .github/; within each directory the dot-less name is tried before the dot-prefixed name, so both variants are accepted regardless of which form a repository uses.

File Search order (first found wins)
config release-please-config.json, .release-please-config.json, then the same pair under .forgejo/ and .github/
manifest release-please-manifest.json, .release-please-manifest.json, then the same pair under .forgejo/ and .github/

The config and manifest are discovered independently, so they may live in different directories or use different dot conventions. The manifest is written back to the path it was discovered at, so updates stay in place; when no manifest exists yet it is created as .release-please-manifest.json. Setting an input pins the path explicitly and disables discovery for that file.

Release types

The release type controls which version-bearing files are updated alongside the changelog and tag.

Release type Version file(s) updated Notes
simple version.txt Language-agnostic, version-only file.
go none Go modules version through git tags only.
node package.json Updates the version field in place.
rust Cargo.toml Updates version in the [package] section only.
helm Chart.yaml Updates version and, when present, appVersion.
terraform-module versions.tf, README.md Replaces vX.Y.Z tokens in versions.tf and version = "~> X.Y" constraints in README.md, when present.
expo app.json, package.json Updates expo.version, expo.ios.buildNumber (when present) and the package.json version.

An unknown release type falls back to simple behavior, still producing a changelog and tag.

Tag naming

Tag names are built from the package configuration.

include-component-in-tag include-v-in-tag tag-separator Component Tag
false true - (none) v1.2.3
false false - (none) 1.2.3
true true - api api-v1.2.3
true false @ web web@1.2.3

Inputs

Input Default Description
token runner token Forgejo access token for API calls.
release-type (none) Strategy used when no config file is present.
target-branch current branch Branch release pull requests target.
config-file auto-discovered Config file path. When unset, discovered from the candidate locations (see File discovery).
manifest-file auto-discovered Manifest file path. When unset, discovered from the candidate locations (see File discovery).
repo-url current repository Repository as owner/repo.
github-api-url runner server URL Override the API base URL.
changelog-host server URL Host for changelog links.
versioning-strategy default default, always-bump-patch, always-bump-minor or always-bump-major.
release-as (none) Force the next version.
skip-github-release false Skip creating releases on merge.
skip-github-pull-request false Skip creating or updating the release pull request.
skip-labeling false Skip applying autorelease labels.
debug false Enable verbose debug logging (see Debugging).

Debugging

Set the debug input to true to log the resolved settings, the discovered config/manifest paths, the per-package version plan, and the file operations the action pushes:

      - uses: https://git.vitalvas.com/actions/release-please@v1
        with:
          debug: "true"

Debug logging is also enabled automatically when the runner sets ACTIONS_STEP_DEBUG or RUNNER_DEBUG (Forgejo's standard Actions debug variables, configurable as a repository or organization variable). Lines are emitted with the ::debug:: prefix so the runner renders them as debug output. Tokens are never logged.

Outputs

Output Description
release_created Whether a release was created in this run.
releases_created Alias of release_created.
prs_created Whether a release pull request was created or updated.
paths_released JSON array of released package paths.
tag_name Tag of the root release.
version Full version of the root release.
major, minor, patch Components of the root release version.
sha Commit SHA the root release points at.
html_url Browser URL of the root release.
upload_url Asset upload URL of the root release.
body Release notes of the root release.
pr JSON summary of the release pull request.

For monorepos, each released path also exposes prefixed outputs such as pkg/api--tag_name and pkg/api--version.

Compatibility notes

The Forgejo API is modeled on the GitHub API but is not identical. This action talks to the Forgejo/Gitea api/v1 endpoints directly and does not use GraphQL. The runner exposes GITHUB_* variables as aliases of FORGEJO_*, so both forms are accepted for the repository, server URL, and token.

Dogfooding

This repository manages its own releases with the action it provides. The setup lives in three files:

File Purpose
.forgejo/release-please-config.json Declares the root package with release-type: go.
.forgejo/release-please-manifest.json Tracks the last released version.
.forgejo/workflows/release-please.yml Runs the action on every push to main.

The config and manifest live under .forgejo/ rather than the repository root; the action auto-discovers them there, so the workflow does not pass explicit paths. The workflow checks out the repository and runs the action from the working tree (uses: ./), so each run exercises the exact code under development. The runner-provided forgejo.token is used for the API calls; it has the repository owner's permissions, which is sufficient to push the release branch, open the release pull request, and create releases.