Skip to content

Publish releases on Gitea and Forgejo, and run on Gitea Actions and Forgejo Actions - #411

Merged
rdeago merged 9 commits into
Tenacom:mainfrom
rdeago:406-gitea-forgejo
Oct 26, 2026
Merged

rdeago merged 9 commits into
Tenacom:mainfrom
rdeago:406-gitea-forgejo

Conversation

@rdeago

@rdeago rdeago commented Oct 26, 2026

Copy link
Copy Markdown
Member

Checklist of related issues / discussions

Proposed changes

GitHost.Create made an UnknownHost for every Gitea and Forgejo repository, so bv release created no release page there. A Gitea or Forgejo runner sets GITHUB_ACTIONS=true, so bv also took it for GitHub Actions. This PR adds Gitea and Forgejo as Git hosts, and Gitea Actions and Forgejo Actions as CI platforms.

The hosts:

  • GiteaApiClient and ForgejoApiClient reach the REST API at https://<host>/api/v1, with Authorization: token <token>.
  • GiteaHost and ForgejoHost build the release and file URLs. GetFileUrl puts tag, branch, or commit before the ref, after the kind of GitRef.
  • GiteaReleasePublisher and ForgejoReleasePublisher check the token, create and publish the release, and undo it on a rollback.
  • buildvana.jsonc accepts gitea and forgejo in repository.host. hosts.gitea.tokenEnv defaults to GITEA_TOKEN, and hosts.forgejo.tokenEnv to FORGEJO_TOKEN.
  • GitHost.DetectKind takes gitea.com for Gitea and codeberg.org for Forgejo on every CI platform. On its own runners, a self-hosted instance is recognized through CIPlatform.ServerKind.

The release, on both hosts:

  • BeginAsync reads GET /repos/{owner}/{repo}. It refuses a repository whose has_releases is false, or whose permissions.push is false.
  • PublishAsync runs after the push of the tag. It creates a draft on the tag, with target_commitish set to the release commit.
  • PublishAsync then uploads each asset as multipart field attachment, with ?name=<file name>. Last, it sends PATCH with name, body, prerelease, and draft false.
  • The description is "We have a human-curated changelog.", with the link to CHANGELOG.md on the release branch.
  • UndoAsync deletes the release, then sends DELETE /repos/{owner}/{repo}/tags/{tag}. Each deletion tolerates a 404.
  • CheckAssets refuses two assets with the same file name.

The platforms:

  • ForgejoActionsPlatform is detected on FORGEJO_ACTIONS. It reads FORGEJO_SERVER_URL, and writes the step outputs to the file FORGEJO_OUTPUT names.
  • GiteaActionsPlatform is detected on GITEA_ACTIONS. It reads GITHUB_SERVER_URL, and writes the step outputs to the file GITHUB_OUTPUT names.
  • Both detectors run before the GitHub Actions one, and Forgejo goes first. Forgejo runners v7 to v12 set GITEA_ACTIONS too.
  • Both platforms write through GitHubActionsStepOutputWriter. Both runners parse its format.
  • The bot identities are gitea-actions <gitea-actions@noreply.<host>> and forgejo-actions <noreply@forgejo.org>. The Gitea Actions user has no email, so the address names the host of GITHUB_SERVER_URL. Forgejo states its own address.

release.md has a "Publishing on Gitea" and a "Publishing on Forgejo" section. Each states the token kinds, the scope and the access the token needs, the token of an Actions job, and the attachments. environment-variables.md describes the platform variables and the token variables. introduction.md has a row for each host and each platform. configuration-file.md lists the two values of repository.host, and hosts.gitea.tokenEnv and hosts.forgejo.tokenEnv.

Where the code differs from the issue

The facts below come from Gitea v28.2.0, Forgejo v17.0.0, and the runners of both.

  • Forgejo is its own host. The issue makes forgejo select GiteaHost, with no hosts.forgejo section. Forgejo has its own HostKind, host, client, publisher, configuration, and platform. The Gitea and Forgejo types share no code beyond HostApiClient, so that each follows its own server. The two APIs already differ: Forgejo has hide_archive_links and no tag_message, and its createTag has no default-branch fallback.
  • The push username. The push username is the constant token, where the issue reads the login of the token owner. Basic authentication ignores the username when the password is an access token or an Actions token, on both hosts. The Git HTTP routes authenticate through the same code.
  • No draft before the push. BeginAsync creates nothing, where the issue creates a draft there. When Gitea or Forgejo processes the push of a tag, it publishes a draft on the same tag name. A draft created before the push would be published without its attachments.
  • The permission check. BeginAsync reads permissions.push and has_releases of the repository instead. A token without the write:repository scope also fails at the push of the release commit, before anything is published.
  • The PATCH. The update sends no tag_name and no target_commitish, which the issue lists. The draft already carries both, and a PATCH with draft false keeps the tag of the release.
  • The tag record. UndoAsync also deletes the record of the tag. A rollback deletes the tag before UndoAsync, which turns the release into a draft. Deleting a release keeps the record of its tag, which then shows in the tag list.
  • A missing release. DeleteReleaseAsync returns false on a 404, and UndoAsync reports it at Info level. A throw there would skip the deletion of the tag record.
  • IsPrivateRepositoryAsync. It is true when private is true or owner.visibility is not public. The issue reads private alone, which misses a public repository of a limited or private owner.
  • Asset descriptions. An attachment has only a name, so the descriptions of the assets do not reach the release. release.md says so.
  • The changelog. Gitea and Forgejo have separate bullets, two for the hosts and two for the platforms.

Risks

  • A tag push goes through an asynchronous queue, the push_update queue. A slow queue can publish the draft before the assets are uploaded. The release ends complete either way.
  • ForgejoActionsPlatform reads FORGEJO_OUTPUT, which exists from Forgejo Runner 9.0.0. An older runner fails bv release with a message that names the variable. introduction.md states the minimum version.
  • Gitea does not state whether a token can write the releases of a repository. A token without that access fails after the push of the tag, and the rollback deletes the tag.
  • Both release flows are tested against a stubbed API. No release has run on a Gitea or Forgejo repository, so the tables of introduction.md say "Supported (untested)" for both hosts and both platforms.

Additional changes

  • GitHubApiClient.DeleteReleaseAsync. It threw on a 404, so a rollback that found the release gone stopped with an error. It returns false instead, and GitHubReleasePublisher.UndoAsync reports the missing release at Info level, as GitLabReleasePublisher does. On GitHub, the 404 happens only when someone deletes the release by hand. No changelog bullet, because GitHubApiClient did not exist in the last stable release.
  • Long lines. GitHostTests.cs and ReleaseHarness.cs had lines over 140 characters, which predate this PR. They are wrapped, in their own commit.
  • terminology.md. The "CI platform" row listed the platforms in its first cell. The list moves below the table, with Gitea Actions and Forgejo Actions.

Types of changes

This pull request introduces the following types of changes:

  • Bug fix
  • New feature
  • Test addition / update (no changes to non-test code)
  • Refactor (no changes in public API syntax or semantics)
  • Performance improvement (no changes in public API syntax or semantics)
  • Documentation update (not including changelog)
  • Dependency addition / update
  • Changes to toolchain configuration
  • Changes to CI (workflows, bot / app configurations)
  • Changes to repository files (.gitattributes, .gitignore)
  • Other

Breaking changes

This pull request introduces breaking changes:

  • Yes
  • No

Checklist

  • For all types of changes:
  • For code changes only:
    • The project builds on my machine, via the provided build script, with zero warnings
    • I have added tests that prove my feature works / my fix is effective
    • I have added / modified XML documentation according to changes in code
    • I have checked that all the links I added or modified in XML documentation point to their intended destination
  • For documentation changes only:
    • I have checked and proofread documentation locally
    • I have checked that all the links I added or modified point to their intended destination

🤖 Generated with Claude Code

rdeago and others added 9 commits October 25, 2026 21:27
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Just report it as information, like the other Git host clients do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Although similar to Gitea, Forgejo is its own platform and gets its own API client and support classes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gitea and Forgejo hosts are now properly configurable (although yet seen as unknown hosts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Now `bv release` can publish a release on a Gitea host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Those lines predate GiteaHost and did not follow the 140-character guideline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Now `bv release` can publish a release on a Forgejo host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Now `bv release` recognizes Gitea and Forgejo runners and deals with them properly.

Previously they were incorrectly recognized as GitHub runners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Now that we have it, support for Gitea and Forgejo deserves to be documented.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rdeago rdeago added the enhancement [issue/PR] requests / implements new or improved functionality. label Oct 26, 2026
@github-actions github-actions Bot added area:docs [issue/PR] affects documentation (excluding XML documentation that is part of source code). area:code [issue/PR] affects project code (excluding tests). labels Oct 26, 2026
@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.10390% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.28%. Comparing base (4ff155e) to head (978e8ac).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
.../Services/Hosts/Forgejo/ForgejoReleasePublisher.cs 95.12% 1 Missing and 3 partials ⚠️
...Tool/Services/Hosts/Gitea/GiteaReleasePublisher.cs 95.12% 1 Missing and 3 partials ⚠️
...ol/Services/Hosts/Forgejo/ForgejoRepositoryUrls.cs 88.23% 1 Missing and 1 partial ⚠️
...ol/Services/Hosts/GitHub/GitHubReleasePublisher.cs 50.00% 0 Missing and 2 partials ⚠️
...a.Tool/Services/Hosts/Gitea/GiteaRepositoryUrls.cs 88.23% 1 Missing and 1 partial ⚠️
...ildvana.Tool/Services/Hosts/Forgejo/ForgejoHost.cs 96.87% 0 Missing and 1 partial ⚠️
...c/Buildvana.Tool/Services/Hosts/Gitea/GiteaHost.cs 96.87% 0 Missing and 1 partial ⚠️
....Tool/Services/Platforms/ForgejoActionsPlatform.cs 94.44% 1 Missing ⚠️
...na.Tool/Services/Platforms/GiteaActionsPlatform.cs 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #411      +/-   ##
==========================================
+ Coverage   86.82%   87.28%   +0.45%     
==========================================
  Files         307      321      +14     
  Lines        9055     9514     +459     
  Branches     1749     1793      +44     
==========================================
+ Hits         7862     8304     +442     
- Misses        905      911       +6     
- Partials      288      299      +11     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rdeago rdeago left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by Claude. Self-review.

👍 Approved.


No blocking findings.

@rdeago
rdeago merged commit 3191443 into Tenacom:main Oct 26, 2026
7 checks passed
@rdeago
rdeago deleted the 406-gitea-forgejo branch October 26, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:code [issue/PR] affects project code (excluding tests). area:docs [issue/PR] affects documentation (excluding XML documentation that is part of source code). enhancement [issue/PR] requests / implements new or improved functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish releases on Gitea and Forgejo, and run on Gitea Actions

1 participant