Compare commits

..

388 Commits

Author SHA1 Message Date
jmiller f485f14615 Merge pull request 'fix(ui): icons on user settings navbar' (#441) from dev into main
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Deploy MokoGitea / deploy (push) Failing after 1m1s
2026-06-02 22:32:18 +00:00
Jonathan Miller d0e3b3dfd8 fix(ui): add octicon icons to user settings navbar
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Release configuration (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
PR RC Release / Build RC Release (pull_request) Successful in 22s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Profile (person), Account (shield-lock), Notifications (bell),
Appearance (paintbrush), Security (lock), Blocked Users (blocked),
Applications (apps), SSH/GPG Keys (key), Actions (play),
Packages (package), Webhooks (webhook), Organizations (organization),
Repositories (repo).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 17:10:45 -05:00
jmiller 3231ac2707 chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-06-02 21:51:52 +00:00
jmiller b2d2a3b622 Merge pull request 'fix(licenses): allow anonymous download paths on licensed repos' (#440) from dev into main
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Deploy MokoGitea / deploy (push) Failing after 1m11s
2026-06-02 20:51:12 +00:00
Jonathan Miller 963fa6d384 fix(licenses): always allow anonymous download path access on licensed repos
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Release configuration (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 23s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RepoAssignment now always grants LicensedReadOnly for download
paths (/releases/, /archive/) on licensed repos. The actual
download gating (none/prerelease/all) is enforced by
CheckDownloadGating in the handler.

Previously only download_gating=none allowed anonymous access.
Now prerelease gating also allows through (CheckDownloadGating
blocks non-stable downloads without a key).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 15:50:23 -05:00
jmiller ba9907ba41 Merge pull request 'fix(updates): feed always public, downloads gated separately' (#439) from dev into main
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 25s
2026-06-02 20:46:14 +00:00
Jonathan Miller 48ff05d4b3 fix(updates): feed always public, downloads gated separately
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Release configuration (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Report Issues (pull_request) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 24s
The updates.xml/JSON feed is now always fully public with versions
and download URLs visible. The actual file downloads are what get
blocked by CheckDownloadGating (none/prerelease/all).

Previously require_key and feed_visibility controlled the XML
feed visibility. Now the feed is informational only — Joomla can
always see what versions are available. The download gating
setting controls whether the files can actually be downloaded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 15:45:00 -05:00
Moko Consulting 70699b4f2a chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
2026-06-02 20:38:03 +00:00
Moko Consulting 99f5833c25 chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
2026-06-02 20:37:54 +00:00
Moko Consulting 241596361e chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 3s
Generic: Repo Health / Site Health (push) Has been skipped
2026-06-02 20:37:45 +00:00
Moko Consulting b1b64a3b4e chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 3s
Generic: Repo Health / Site Health (push) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 27s
2026-06-02 20:37:36 +00:00
Moko Consulting 3cddb46053 chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 29s
2026-06-02 20:37:28 +00:00
Moko Consulting 0a0cc16528 chore(ci): add CI issue reporter for auto-filing gate failures
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 29s
2026-06-02 20:37:17 +00:00
jmiller da41d7072f Merge pull request 'fix(licenses): restrict downloadsPublic to release paths only' (#438) from dev into main
Deploy MokoGitea / deploy (push) Failing after 17s
2026-06-02 20:31:27 +00:00
Jonathan Miller 6405163e60 fix(licenses): restrict downloadsPublic to release/download paths only
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
PR RC Release / Build RC Release (pull_request) Successful in 21s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
The downloadsPublic flag was granting LicensedReadOnly to all
routes including the main repo page, causing 404 on private repos.
Now only applies to paths containing /releases/ or /archive/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 15:30:23 -05:00
jmiller cb3817f5bc Merge pull request 'fix(licenses): allow anonymous downloads when download_gating=none' (#437) from dev into main
Deploy MokoGitea / deploy (push) Failing after 47s
2026-06-02 20:26:46 +00:00
Jonathan Miller 01011f6115 fix(licenses): allow anonymous downloads when download_gating=none on private repos
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
PR RC Release / Build RC Release (pull_request) Successful in 21s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
RepoAssignment now checks the download_gating setting. When set to
"none" (all downloads public), anonymous users can access release
downloads on licensed private repos without a key.

Previously, anonymous users always got 403 on private repos even
when download gating was set to public.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 15:25:28 -05:00
jmiller f657f58fbb Merge pull request 'fix(ui): octicon-settings to octicon-gear' (#436) from dev into main
Deploy MokoGitea / deploy (push) Failing after 41s
2026-06-02 19:47:07 +00:00
Jonathan Miller ea10e8500c fix(ui): replace invalid octicon-settings with octicon-gear
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 23s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:45:37 -05:00
jmiller 1709566fa6 Merge pull request 'fix(ui): section headers with dividers, icons on all settings navbar items' (#435) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m23s
2026-06-02 19:34:36 +00:00
Jonathan Miller 92bd3f7dc0 fix(ui): clean section headers with dividers instead of accordions, icons on all navbar items
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 22s
Advanced settings: replace collapsible accordions with clean h5
section headers (icon + bold text) separated by dividers. All
sections always visible — no clicking to expand.

Navbar: add octicon icons to every menu item — Options (settings),
Advanced (tools), Licensing (key), Public Access (eye),
Collaboration (people), Webhooks (webhook), Branches (git-branch),
Tags (tag), Git Hooks (terminal), Deploy Keys (key-asterisk),
LFS (file-binary), Actions (play).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:33:23 -05:00
jmiller 95c136d838 Merge pull request 'feat(settings): dedicated advanced settings page at /settings/advanced' (#434) from dev into main
Deploy MokoGitea / deploy (push) Failing after 17s
2026-06-02 19:25:37 +00:00
Jonathan Miller 89fcbda623 feat(settings): move advanced settings to dedicated /settings/advanced page
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
PR RC Release / Build RC Release (pull_request) Failing after 18s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Extract all feature unit settings (Code, Wiki, Issues, Projects,
Releases, Packages, Pull Requests) from options.tmpl into a
separate advanced.tmpl with its own route at /settings/advanced.

Options page now only contains: basic repo settings, avatar,
mirror config, signing settings, and danger zone.

Navbar updated: Advanced Settings link points to /settings/advanced.
Form posts still go through the existing SettingsPost handler.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:23:49 -05:00
Jonathan Miller dd6ee750f0 fix(build): remove extra {{end}} in settings accordion template
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:17:47 -05:00
jmiller 48f32ae961 Merge pull request 'feat(settings): accordion layout for advanced settings' (#433) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m1s
2026-06-02 19:14:08 +00:00
Jonathan Miller ffb9363e3e feat(settings): accordion layout for advanced settings sections
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 21s
Each feature section (Code, Wiki, Issues, Projects, Releases,
Packages, Pull Requests) is now wrapped in a collapsible <details>
accordion with an icon and bold title.

Code section is open by default; others are collapsed. This
reduces visual clutter and lets admins focus on the section
they need.

Licensing section removed from advanced settings (now on its
own /settings/licensing page).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:13:32 -05:00
jmiller dce87fcb5d Merge pull request 'feat(settings): licensing settings page + navbar restructure' (#432) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m40s
2026-06-02 19:03:52 +00:00
Jonathan Miller a1ceac6396 feat(settings): separate licensing settings page with navbar entry
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 23s
Extract licensing/update feed settings to its own page at
/settings/licensing with dedicated template and handler.

Navbar additions:
- Advanced Settings link (points to existing options page)
- Licensing link with key icon (when licensing enabled)

New handler: LicensingSettings/LicensingSettingsPost serves the
standalone licensing form with all fields (platform, gating,
metadata, extensions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 14:02:53 -05:00
jmiller 7004170d64 Merge pull request 'fix(ui): login form on 403 page + visibility badge right-aligned' (#431) from dev into main
Deploy MokoGitea / deploy (push) Failing after 19s
2026-06-02 18:56:17 +00:00
Jonathan Miller a22fa57ab1 fix(ui): embed login form on 403 Access Denied page
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 19s
Anonymous users seeing the 403 page now get an inline login form
with username, password, and submit button. After login, redirects
back to the page they were trying to access.

Compact form centered with tw-max-w-sm, includes CSRF token and
redirect_to hidden field pointing to CurrentURL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 13:55:52 -05:00
jmiller c045c6abfc Merge pull request 'fix(ui): visibility badge floated right of title' (#430) from dev into main
Deploy MokoGitea / deploy (push) Failing after 22s
2026-06-02 18:51:55 +00:00
Jonathan Miller 68736c78a1 fix(ui): float visibility badge to right of title label
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 13:51:31 -05:00
jmiller ce35e3a603 Merge pull request 'fix(build): UpdateRepositoryColsWithAutoTime' (#429) from dev into main
Deploy MokoGitea / deploy (push) Failing after 22s
2026-06-02 18:46:56 +00:00
Jonathan Miller cfea80d3ca fix(build): use UpdateRepositoryColsWithAutoTime for is_hidden
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 21s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 13:46:26 -05:00
jmiller 3e4cb4d2e5 Merge pull request 'feat(repos): three-level visibility Public/Private/Hidden' (#428) from dev into main
Deploy MokoGitea / deploy (push) Failing after 23s
2026-06-02 18:44:15 +00:00
Jonathan Miller e2c738a8d8 feat(repos): three-level visibility — Public, Private, Hidden
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 22s
Add IsHidden field to Repository model. Three visibility modes:

- Public: visible to everyone (green label)
- Private: members only, non-members see 403 Access Denied (orange)
- Hidden: members only, non-members see 404 Not Found (red)

Private mode is for commercial repos — customers know the repo
exists and see a styled 403 page with sign-in button. Licensed
update feeds and key-gated downloads still work.

Hidden mode is for internal/secret repos — complete stealth, as
if the repo doesn't exist.

Settings UI: radio button selector in danger zone replaces the
old binary toggle. Each option shows a colored label with
description.

Migration v342: adds is_hidden column to repository table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 13:42:25 -05:00
jmiller ba361c609f Merge pull request 'fix(licenses): RequireUnitReader allows LicensedReadOnly' (#427) from dev into main
Deploy MokoGitea / deploy (push) Failing after 21s
2026-06-02 15:45:48 +00:00
Jonathan Miller 6c7a6e4061 fix(licenses): RequireUnitReader allows LicensedReadOnly access
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 21s
RequireUnitReader now checks for LicensedReadOnly context flag
before checking standard permissions. This lets the releases
download route pass through for licensed private repos where
RepoAssignment granted read-only access via license key.

Fixes the 404 on /releases/download/ with valid dlid= param.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 10:23:38 -05:00
jmiller 7aaf8dcbb7 Merge pull request 'fix(licenses): bypass attachment perm check for licensed downloads' (#426) from dev into main
Deploy MokoGitea / deploy (push) Failing after 26s
2026-06-02 15:17:40 +00:00
Jonathan Miller 95d93da2bc fix(licenses): bypass attachment permission check for licensed downloads
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 20s
ServeAttachment checks perm.CanRead(unitType) which fails for
licensed read-only access on private repos. Now skips the check
when LicensedReadOnly is set in context (from RepoAssignment).

This allows Joomla/WordPress clients with valid dlid= params to
download release files from private licensed repos.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 10:17:06 -05:00
jmiller 128b120ad9 Merge pull request 'fix(licenses): allow downloads on private repos with license key' (#425) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m3s
2026-06-02 15:13:47 +00:00
Jonathan Miller 02424c3f75 fix(licenses): allow download access on private licensed repos with license key
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 20s
RepoAssignment now checks for dlid/key/download_key query params
when licensing is enabled. Anonymous Joomla/WordPress clients with
valid license keys can access release download routes on private
repos without being signed in.

Access flow for licensed private repos:
- Anonymous + no key → 403 (styled page)
- Anonymous + valid dlid → access granted (CheckDownloadGating validates)
- Signed in + no membership → access granted (releases visible, downloads hidden)
- Org member → full access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 10:12:45 -05:00
jmiller 3f817babd3 Merge pull request 'fix(ui): styled 403 Access Denied page matching 404 layout' (#424) from dev into main
Deploy MokoGitea / deploy (push) Failing after 20s
2026-06-02 15:06:02 +00:00
Jonathan Miller 449af83e2b fix(ui): styled 403 Access Denied page matching the 404 page layout
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 21s
Add templates/status/403.tmpl mirroring the 404 page design with
a centered error message and sign-in button for anonymous users.

New Forbidden() method on Context renders the styled 403 template
for HTML requests, falls back to plain text for API/non-HTML.

RepoAssignment now calls ctx.Forbidden() instead of raw HTTPError
for both anonymous and signed-in users without access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 10:05:24 -05:00
jmiller 6290ff07e4 Merge pull request 'fix(security): 403 for all users on private repos' (#423) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m1s
2026-06-02 14:57:50 +00:00
Jonathan Miller 3ad37e48e1 fix(security): return 403 for all users on private repos, not 404
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 21s
Both anonymous and signed-in users now get 403 Access Denied when
accessing a private repo they lack permission for. Previously
anonymous users got 404 which hid the repo's existence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:57:29 -05:00
jmiller c4e51ff55c Merge pull request 'fix(licenses): licensed private repos allow release viewing for signed-in users' (#422) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m10s
2026-06-02 14:52:29 +00:00
Jonathan Miller 021a054348 fix(licenses): licensed private repos allow signed-in users to view releases
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 19s
When licensing is enabled on a private repo, signed-in users who
are not repo members can now view the releases page (with downloads
hidden). The RepoAssignment permission check detects licensing and
grants read-only access instead of returning 403.

This enables the commercial pattern: private source code, but
release notes visible to any authenticated user. Download files
are gated by license key via HideReleaseDownloads.

Anonymous users still get 404 (no information leak).
Non-licensed private repos still return 403 for non-members.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:52:05 -05:00
jmiller b707c5aff9 Merge pull request 'fix(updates): allow update feeds on private repos' (#421) from dev into main
Deploy MokoGitea / deploy (push) Failing after 2m48s
2026-06-02 14:37:42 +00:00
Jonathan Miller ead620daf9 fix(updates): allow update feeds on private repos via lightweight repo loader
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 20s
Update feed endpoints (updates.xml, dolibarr.json, wordpress.json,
packages.json, prestashop.xml, drupal.xml, whmcs.json, changelog.xml)
now use RepoAssignmentPublicFeed instead of the full RepoAssignment.

The lightweight loader fetches the repo by owner/name without checking
user permissions. Feed handlers gate access via license keys, not repo
membership. This allows private repos to serve update feeds to
anonymous Joomla/WordPress/Composer clients with valid license keys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:36:06 -05:00
jmiller 2db1f4eaf6 Merge pull request 'fix(security): 403 Access Denied for signed-in users on private repos' (#420) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m10s
2026-06-02 14:27:19 +00:00
Jonathan Miller 0add8bda72 fix(security): show 403 Access Denied instead of 404 for signed-in users on private repos
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 19s
Signed-in users who lack permission to a private repo now see a
403 "You do not have permission" instead of a misleading 404.
Anonymous users still get 404 to prevent repo enumeration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:26:21 -05:00
jmiller 25499fb183 Merge pull request 'fix(build): unused import in drupal.go' (#419) from dev into main
Deploy MokoGitea / deploy (push) Failing after 21s
2026-06-02 14:10:45 +00:00
Jonathan Miller bd81616432 fix(build): remove unused time import in drupal.go
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 20s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:10:11 -05:00
jmiller 7c15301228 Merge pull request 'feat(updates): PrestaShop, Drupal, WHMCS update feeds (#352, #353, #355)' (#418) from dev into main
Deploy MokoGitea / deploy (push) Failing after 21s
2026-06-02 14:08:33 +00:00
Jonathan Miller 02f3ed88f1 feat(updates): PrestaShop (#352), Drupal (#353), WHMCS (#355) update feeds
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 18s
PrestaShop: GET /updates/prestashop.xml — module update XML with
name, version, download URL, author, SHA256. Serves stable only.

Drupal: GET /updates/drupal.xml — update status XML per Drupal API
spec. Includes project metadata, all releases with status, download
links, SHA256. Uses TargetVersion config for api_version field.

WHMCS: GET /updates/whmcs.json — simple JSON with latest stable
version, download URL (with dlid), changelog, author. License key
embedded in download URL when provided.

All three use ResolveReleaseStream for manual/auto stream mapping,
readSHA256FromSidecar for integrity hashes, and extractVersion with
stream-name tag fallback.

Routes registered under the update server group alongside Joomla,
Dolibarr, WordPress, and Composer feeds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:08:03 -05:00
jmiller e4718f5036 Merge pull request 'feat(updates): Composer feed (#354), hide Actions/Licenses tabs for guests' (#417) from dev into main
Deploy MokoGitea / deploy (push) Failing after 2m59s
2026-06-02 14:02:23 +00:00
Jonathan Miller 0fb0aea719 feat(updates): Composer packages.json feed (#354), hide menu items for guests
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 20s
Composer feed: new endpoint GET /updates/packages.json serving
Composer/Packagist-compatible packages.json. Includes version,
dist URL with SHA256, authors, PHP requirement. License key
embedded in download URL when provided.

Menu visibility: Actions and Licenses tabs in repo header now
require .IsSigned — anonymous users no longer see tabs they
can't access. Previously the tabs were visible but clicking
redirected to login (confusing UX).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 09:02:00 -05:00
jmiller 581bfa5f31 Merge pull request 'feat(licenses): key prefix (#406), header button (#408), open feed (#409)' (#416) from dev into main
Deploy MokoGitea / deploy (push) Failing after 18s
2026-06-02 13:52:27 +00:00
Jonathan Miller eca929f680 feat(licenses): configurable key prefix (#406), header button (#408), open feed button (#409)
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
PR RC Release / Build RC Release (pull_request) Failing after 18s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
#406: Add KeyPrefix field to UpdateStreamConfig. GenerateKeyString
now accepts a prefix parameter, looked up from org config. Default
remains MOKO if not set. Auto-uppercased, max 20 chars.

#408: Move "New Package" button into the packages header bar,
right-aligned. Uses details/summary pattern — clicking the button
expands the create form below. Cleaner layout on both repo and org.

#409: Add open-in-new-tab button (external link icon) next to every
copy button on feed URLs. All four feeds: Joomla XML, Dolibarr JSON,
WordPress JSON, Changelog XML.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:51:55 -05:00
jmiller 8ae663e15e Merge pull request 'SECURITY: fix release download gating and require login for actions' (#415) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m11s
2026-06-02 13:41:10 +00:00
Jonathan Miller b65b155446 SECURITY: fix release download gating and require login for actions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 21s
Release gating: HideReleaseDownloads now checks download_gating
setting in addition to feed_visibility. When licensing is enabled
and download_gating != "none", anonymous users see "Sign in to
download" instead of download links on the release page.

Actions: changed from optSignIn to reqSignIn on the repo actions
route group. Anonymous users can no longer view CI/CD runs, logs,
or artifacts. This is a MokoGitea policy override — upstream Gitea
allows public actions on public repos.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:40:40 -05:00
jmiller 4bc962adbf Merge pull request 'fix(build): permanent fixes for recurring build errors' (#414) from dev into main
Deploy MokoGitea / deploy (push) Failing after 20s
2026-06-02 13:35:03 +00:00
Jonathan Miller de52ad0fbc fix(build): permanent fixes for recurring build errors
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 26s
- AI migration 339: replaced with noopMigration placeholder
- feed/file.go: add missing comma in struct literal
- license_key.go: remove unused org_model import

These were being applied as server-side hotfixes on every deploy.
Now committed to dev so they persist through merges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:34:14 -05:00
jmiller ca841716db Merge pull request 'SECURITY: require login for licenses page' (#413) from dev into main
Deploy MokoGitea / deploy (push) Failing after 25s
2026-06-02 13:26:17 +00:00
Jonathan Miller 1dfa5d8079 SECURITY: require login for licenses page — was accessible anonymously
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 21s
The repo licenses route used optSignIn (login optional), allowing
anonymous users to view license packages and keys. Changed to
reqSignIn to require authentication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:25:31 -05:00
jmiller 117daf51c3 Merge pull request 'fix(build): org list API and unused import' (#412) from dev into main
Deploy MokoGitea / deploy (push) Failing after 23s
2026-06-02 13:22:10 +00:00
Jonathan Miller 70793075fc fix(build): use db.Find for org list, remove unused org_model import
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 22s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:21:39 -05:00
jmiller a2e0735a26 Merge pull request 'feat(orgs): enterprise sub-org hierarchy (#410)' (#411) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m18s
2026-06-02 13:15:30 +00:00
Jonathan Miller 2799558040 feat(orgs): enterprise sub-org hierarchy with parent-child relationships (#410)
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 26s
Add ParentOrgID field to User model for org hierarchy. Parent orgs
can have child orgs, enabling enterprise structures like
MokoConsulting → client orgs.

Model changes:
- ParentOrgID int64 on User (INDEX, DEFAULT 0)
- GetChildOrgs, GetAncestorOrgIDs, GetParentOrg helpers
- Max 10 hierarchy levels with cycle detection

License integration:
- ListLicensePackagesWithAncestors — shows packages from parent orgs
- ListLicenseKeysWithAncestors — shows keys from parent orgs
- SearchLicenseKeysWithAncestors — searches across hierarchy
- Master keys from parent orgs validate for child org repos

UI:
- Parent org dropdown in org settings (owners/admins only)
- Shows all orgs user owns except self

Migration v341: adds parent_org_id column to user table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 08:14:08 -05:00
jmiller 1a46a8f14f Merge pull request 'fix(build): EditReleaseForm UpdateStream field' (#405) from dev into main
Deploy MokoGitea / deploy (push) Failing after 19s
2026-06-02 12:56:36 +00:00
Jonathan Miller d85ae6aa21 fix(build): add UpdateStream to EditReleaseForm
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 19s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:56:11 -05:00
jmiller b18519e8b9 Merge pull request 'fix(build): pass ctx to WordPress changelog builder' (#404) from dev into main
Deploy MokoGitea / deploy (push) Failing after 1m32s
2026-06-02 12:48:26 +00:00
Jonathan Miller 1b9b82d59a fix(build): pass ctx to buildWordPressChangelog for ResolveReleaseStream
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 24s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:47:42 -05:00
jmiller 94649efed0 Merge pull request 'feat(updates): manual stream mapping, version extraction fixes, feed visibility' (#403) from dev into main
Deploy MokoGitea / deploy (push) Failing after 22s
2026-06-02 12:43:29 +00:00
Jonathan Miller 37322e4212 feat(updates): manual release-to-stream mapping
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 22s
Add release_stream_map table for explicitly assigning releases to
update streams. When a mapping exists, it overrides automatic tag
detection. When absent, falls back to tag name/suffix matching.

New model: ReleaseStreamMap with SetReleaseStream, GetReleaseStream,
ResolveReleaseStream (manual first, auto fallback).

UI: stream selector dropdown on release create/edit page, shown when
licensing is enabled. Options: auto-detect (default) or any
configured stream (stable, release-candidate, beta, etc.).

All three feed generators (Joomla, Dolibarr, WordPress) now use
ResolveReleaseStream instead of MatchStreamFromTag.

Migration v340 updated with release_stream_map table creation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:37:02 -05:00
Jonathan Miller 2f9097a254 fix(updates): check tag name not extracted version for stream name detection
isStreamName was checking the extracted version (empty for stream
tags) instead of the original tag name. Now checks rel.TagName
directly, and also falls through when extractVersion returns empty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:29:43 -05:00
Jonathan Miller ce3af35c40 fix(updates): extract version numbers from release titles via regex
When tags are stream names, extractVersion falls back to finding a
version pattern (digits.digits.digits) anywhere in the release title.
Handles titles like "Package - MokoWaaS (VERSION: 02.31.00)".

Previously the full title was used as the version, producing invalid
entries like "Package - MokoWaaS (VERSION: 02.31.00)" in the XML.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:27:06 -05:00
Jonathan Miller 0a3cd3115f feat(updates): support stream-name tags alongside version tags
MatchStreamFromTag now checks if the tag name directly matches a
stream name (e.g. "stable", "release-candidate", "development")
before falling back to suffix matching. Supports both conventions:

1. Stream-name tags: tag IS the stream (MokoWaaS style)
2. Version tags: tag has version + suffix (v1.0.0-rc1 style)

When a stream-name tag is detected, the version number is extracted
from the release title instead of the tag. Falls back to tag name
if no version found in title.

Applied across all feed generators: Joomla XML, Dolibarr JSON,
WordPress JSON, and Changelog XML.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:21:02 -05:00
Jonathan Miller 3e31b662a6 fix(licenses): remove UNIQUE constraint on PaymentRef, use tw-max-w-lg
PaymentRef UNIQUE constraint causes Error 1062 when creating keys
without a payment reference — empty strings collide. Remove the
DB constraint; idempotency is enforced in code via
GetLicenseKeyByPaymentRef which already filters empty strings.

Also replace inline style with tw-max-w-lg class on search box.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:12:13 -05:00
Jonathan Miller 774ea3842b fix(ui): constrain license key search box width to 400px
The search input was spanning full width (tw-w-full) making it
disproportionately large. Cap at 400px to match other search
inputs in the Gitea UI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 07:10:43 -05:00
jmiller a52ac1bf61 Merge pull request 'feat(licenses): full commercial license management system v1.26.1-moko.06.02.00' (#402) from dev into main
Deploy MokoGitea / deploy (push) Failing after 19s
feat(licenses): full commercial license management system v1.26.1-moko.06.02.00 (#402)
2026-06-02 12:00:19 +00:00
Jonathan Miller 0e7d3c4a34 fix(security): ownership guards, RepoScope parsing, CSRF tokens, XSS escaping
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
PR RC Release / Build RC Release (pull_request) Failing after 17s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
SECURITY: Add verifyPackageOwnership/verifyKeyOwnership checks to
all API handlers that accept ID parameters. Prevents cross-org
access where an admin of org A could modify org B's license data.

FIX: RepoScope validation now properly parses JSON arrays using
json.Unmarshal instead of strings.Contains. The old approach matched
substrings (repo ID "2" matched inside "12"). Now uses typed int64
comparison.

FIX: Add {{$.CsrfTokenHtml}} to both delete confirmation modal
forms (package and key) in repo and org templates. Without CSRF
tokens, the form-fetch-action POST requests would be rejected.

FIX: HTML-escape release notes in WordPress changelog to prevent
XSS via malicious release note content reaching WP admin dashboards.

FIX: Parse AllowedChannels JSON format before comma-split fallback
to avoid garbage values from splitting JSON arrays by comma.

FIX: Add missing third return value (false) on error path in
validateUpdateKey to prevent compile error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:59:29 -05:00
Jonathan Miller 913e919fba docs: update CHANGELOG and wiki for v1.26.1-moko.06.02.00
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 19s
Add changelog entry for full license management system release.
Update wiki with WordPress feed status, feed visibility modes,
and revision 1.4.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:47:09 -05:00
Jonathan Miller a20153a0e0 fix(licenses): no-download mode shows release notes but hides files
In "no-download" feed visibility mode, anonymous users can browse
the release listing page and read release notes, but the download
section (attachments, source archives) is replaced with a "Sign in
to download" message.

Only "hidden" mode redirects anonymous users to login entirely.
"no-download" keeps the page public — release notes, changelogs,
and version info are all visible. Just the actual files are gated.

This matches the commercial pattern: let users see what's available
to motivate purchase, while protecting the actual deliverables.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:42:44 -05:00
Jonathan Miller a149edccd3 feat(licenses): feed visibility modes and login-required releases
Add FeedVisibility field to UpdateStreamConfig with three modes:
- public: full feed with download URLs (default)
- no-download: version info visible but download URLs stripped
- hidden: empty feed returned without a valid license key

The "no-download" mode is the key commercial pattern — customers
see updates exist (motivating purchase/renewal) but cannot download
without a valid key. Joomla shows "update available" in admin.

Applied consistently across all update feed endpoints (Joomla XML,
Dolibarr JSON, WordPress JSON) via the shared validateUpdateKey()
which now returns a stripDownloads flag.

Also: when licensing is enabled, the release listing page requires
login. Anonymous users are redirected to the login page. This
prevents browsing release notes and download links without auth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:38:09 -05:00
Jonathan Miller 01eb9944ca feat(licenses): replace channel checkboxes with combolist picker
Use the existing shared/combolist.tmpl component for channel
selection in create and edit package forms. This mimics the
issue label picker UI — a searchable dropdown with checkmarks
and a selected-items list below.

Replaces raw checkboxes (repo + org templates) and Fomantic
multiple selection dropdowns (edit templates) with the
combo-multiselect component that has proper JS for toggle,
search, and clear functionality.

Handler parsing updated: combolist sends comma-separated values
in a single hidden input (vs multiple checkbox form values).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:30:59 -05:00
Jonathan Miller e3a8ae2595 feat(settings): add extension metadata to repo settings (#335)
Repo settings now include extension metadata fields (element name,
display name, type, target version, maintainer, PHP minimum) under
the Licensing section. These override org-level defaults per-repo.

Empty fields inherit from the organization's update stream config.
Extension type dropdown includes: package, component, module,
plugin, template, library — plus an "(inherit from org)" option.

Also adds form fields to the RepoSettingsForm struct for all
metadata fields.

Closes #335

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 06:19:48 -05:00
Jonathan Miller 1fabdb94ec feat(updates): WordPress PUC-compatible update feed (#351)
New endpoint: GET /{owner}/{repo}/updates/wordpress.json

Generates JSON compatible with the YahnisElsts plugin-update-checker
library — the standard for commercial WordPress plugin self-hosted
updates. Returns name, slug, version, download_url, homepage,
requires_php, author, sections (changelog HTML), icons, and banners.

License key validation: reads from ?license_key=, ?dlid=, or ?key=
query params (PUC sends these via addQueryArgFilter). When RequireKey
is enabled, returns minimal empty response without download_url.

Changelog section built from release notes (last 10 stable releases),
converting markdown list items to HTML <ul>/<li> elements.

Icon/banner URLs point to conventional paths in the repo:
  assets/icon-128x128.png, assets/icon-256x256.png
  assets/banner-772x250.png, assets/banner-1544x500.png

Route registered at /updates/wordpress.json alongside existing
/updates.xml (Joomla) and /updates/dolibarr.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-02 00:01:16 -05:00
Jonathan Miller d204ecb9f0 fix(licenses): enforce RepoScope validation and add API revoke endpoint
SECURITY: ValidateLicenseKeyForRepo() now checks the package's
RepoScope field against the requesting repo ID. A package scoped
to repo A will reject keys when accessed from repo B's update feed.
Update server and download gating both use the new function.

Master/internal keys bypass repo scope checks.

RepoScope supports: "all" (any repo), single repo ID string,
or JSON array of repo IDs like ["1","5","12"].

Also adds POST /license-keys/{id}/revoke API endpoint that was
missing from the API but existed in web handlers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:33:26 -05:00
Jonathan Miller 93d18ab25f feat(licenses): double confirmation modals for permanent deletion (#391)
Replace link-action delete buttons with show-modal pattern that opens
a Fomantic UI modal with a form. Package deletion requires typing
the package name in a required field before the submit button works.
Key deletion shows a warning modal with confirmation.

Uses Gitea's existing form-fetch-action + modal_actions_confirm
pattern, matching how repo deletion works in settings.

Both repo and org templates updated with matching modals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:23:56 -05:00
Jonathan Miller 3e8124a2b7 feat(licenses): API package CRUD, settings API, and repo scope UI
API package endpoints (#388):
- PATCH /license-packages/{id} — edit package (master protected)
- DELETE /license-packages/{id} — delete package (master protected)
- POST /license-packages/{id}/archive — archive package
- POST /license-packages/{id}/unarchive — restore package

Settings API (#349):
- GET /license-settings — read licensing/update stream config
- PUT /license-settings — update config (all metadata fields)
- New LicenseSettings struct in API types

Repo scope UI (#395):
- Dropdown in create/edit package forms listing org repos
- "All repositories" default option
- RepoScope read from form in both repo and org handlers
- OrgRepos loaded via GetOrgRepositories in Licenses handlers

Refs #341, #346, #349, #388, #395

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:21:09 -05:00
Jonathan Miller 7c9215de05 test(licenses): add integration tests for license key API endpoints
Tests cover:
- Package CRUD (list, create, create without name)
- Key CRUD (create, list, edit, renew, delete)
- Purchase webhook (new key, idempotent duplicate)
- Public validation (valid key, invalid key, domain check)

Tests follow existing Gitea integration test patterns using
unittest fixtures, user tokens, and DecodeJSON assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:09:14 -05:00
Jonathan Miller 7da0e025da feat(updates): include SHA256 from sidecar files in Joomla updates.xml
Read the .sha256 sidecar attachment (generated by
GenerateReleaseChecksums) and populate the <sha256> element in the
update XML. This matches the pattern used by Akeeba (sha512) and
JCE (sha256 + sha384 + sha512) for integrity verification.

Also fix zip attachment filter to skip .sha256 sidecar files when
selecting the download URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:04:24 -05:00
Jonathan Miller 0e09723d2a fix(updates): map stream names to Joomla-standard tag values
Joomla only recognizes: dev, alpha, beta, rc, stable. Our internal
stream names use longer forms (development, release-candidate).
Add joomlaTagName() to map between conventions in the <tags><tag>
XML element.

Without this, Joomla's update channel filter ignores entries with
non-standard tag values like "release-candidate" or "development".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:01:59 -05:00
Jonathan Miller 53a5d0b97b feat(licenses): domain lock timer, infourl fix, Akeeba-compatible XML format
Domain lock timer: add DomainLockHours to LicensePackage and
FirstUsedUnix to LicenseKey. During the grace period after first
use, any domain is accepted and auto-added to the restriction list.
After the grace period, only listed domains are allowed. Set 0 for
immediate lock-on-first-use (default).

Fix infourl: default to /releases listing page instead of specific
tag page. Falls back to SupportURL or InfoURL if configured.

Match Akeeba Backup Pro XML format: downloadkey prefix is "dlid="
(not "&dlid="), matching how Joomla stores extra_query. Verified
against production Akeeba/JCE/AdminTools manifests via SSH.

Update migration v340 with FirstUsedUnix and DomainLockHours columns.

Add DomainLockHours field to create/edit package forms for both
repo and org levels with help text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 05:00:50 -05:00
Jonathan Miller 448b7d3ab0 feat(licenses): archive, search, download gating, changelog XML, and expanded permissions
Migration v340: sync all missing columns (key_raw, payment_ref,
last_heartbeat_unix, is_archived, licensing_enabled, download_gating,
support_url, and all extension metadata fields).

Package archiving (#384): add IsArchived field with archive/unarchive
handlers and collapsible "Archived Packages" section in templates.
Existing keys from archived packages continue to work.

Expanded delete permissions (#385): org owners and site admins can
permanently delete packages and keys (previously site admin only).

Search (#392): server-side search across key_prefix, key_raw,
licensee_name, licensee_email, domain_restriction, and payment_ref
via ?q= query parameter on both repo and org licenses pages.

Sortable tables (#390): Fomantic UI sortable class on keys table
with new Domain column showing DomainRestriction per key.

Download gating (#347): three modes — none, prerelease-only, and
all downloads. CheckDownloadGating() intercepts both release
attachment and git archive download handlers.

Support URL (#393): configurable SupportURL field on
UpdateStreamConfig for wiki or external site links.

Changelog XML (#343): ServeChangelogXML endpoint at /changelog.xml
generates Joomla-compatible changelog from release notes. Parses
Keep-a-Changelog markdown sections into <security>, <fix>,
<addition>, <change>, <remove>, <note> XML elements.

API renew (#387): POST /license-keys/{id}/renew endpoint extends
key expiration by package duration.

Closes #384, #385, #386, #387, #389, #390, #392, #393
Refs #343, #346, #347

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-01 04:45:20 -05:00
jmiller 5da4b3b314 Merge pull request 'fix(build): remove unused imports' (#377) from dev into main
Deploy MokoGitea / deploy (push) Failing after 21s
2026-05-31 18:51:42 +00:00
Jonathan Miller e998c494b2 fix: resolve tech-debt batch 7 — dead routes, stale FIXMEs, feed revision
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 20s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- chore: remove stale mustNotBeArchived FIXME (CanEnableEditor no longer exists)
- fix(routes): remove dead /cherry-pick/{sha} route — replaced by /_cherrypick/
- fix(feed): use full ref name instead of ShortName for file feed revision

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:46:06 -05:00
Jonathan Miller eafd5320e3 fix(build): remove unused imports causing compile errors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:41:35 -05:00
jmiller 75e2a21b89 Merge pull request 'chore: merge dev into main — Issue.Ref deprecation, stale TODO cleanup' (#376) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m45s
2026-05-31 18:39:57 +00:00
Jonathan Miller 1ed8e463df chore: remove stale TODO comments (#328, #332)
Branch Policy Check / Verify merge target (pull_request) Successful in 9s
Universal: PR Check / Branch Policy (pull_request) Successful in 9s
Universal: PR Check / Validate PR (pull_request) Failing after 17s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 34s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Remove TODO from OAuth2 regenerate secret template — the
  functionality was already fully implemented
- Remove stub TODO test comments for TestMerge, TestNewPullRequest,
  TestAddTestPullRequestTask — stale for years
- Remove stale GetProjectsMode TODO — method is needed by templates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:38:18 -05:00
jmiller e82fe7d021 Merge pull request 'fix(cron): add missing translation for cleanup_expired_license_keys' (#375) from dev into main
Deploy MokoGitea / deploy (push) Failing after 21s
2026-05-31 18:34:46 +00:00
Jonathan Miller cd0a803341 fix(issues): deprecate Issue.Ref branch selector UI (#307)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Remove the branch/tag selector from the issue sidebar and new issue
form. The Issue.Ref field was added 8 years ago and provides minimal
value — it only saves a branch name and optionally restricts which
branch's commits can auto-close the issue.

Removed:
- Branch selector template (branch_selector_field.tmpl)
- Sidebar and new-form includes
- Ref badge from issue lists
- POST /{index}/ref web route and UpdateIssueRef handler
- GetRefEndNamesAndURLs calls from list renderers
- JS handler for branch selector dropdown

Preserved:
- DB column (Issue.Ref) — still used by commit-close logic
- API response still includes ref for backward compatibility

Closes #307

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:31:11 -05:00
Jonathan Miller 278645113b fix(cron): add missing translation for cleanup_expired_license_keys
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:14:45 -05:00
jmiller 24a9bfb30d Merge pull request 'fix(docker): disable openssh s6 service in Dockerfile' (#374) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m30s
2026-05-31 17:14:36 +00:00
Jonathan Miller 7e312077e7 fix(docker): disable openssh s6 service in Dockerfile
Branch Policy Check / Verify merge target (pull_request) Successful in 9s
Universal: PR Check / Branch Policy (pull_request) Successful in 8s
Universal: PR Check / Validate PR (pull_request) Failing after 18s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 43s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Bake the noop script directly into the image layer so openssh never
starts. We use external SSH (port 2222) via host networking, not the
container's sshd.

Fixes: #372

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 12:13:21 -05:00
jmiller 257908e083 Merge pull request 'chore: merge dev into main — tech-debt, namespace migration, combo-multiselect' (#373) from dev into main
Deploy MokoGitea / deploy (push) Failing after 6m39s
2026-05-31 17:12:39 +00:00
Jonathan Miller 40130d1793 docs: update CHANGELOG for v05.15.00 dev cycle
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 20s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:55:21 -05:00
Jonathan Miller 79724b5bc9 feat(ui): add generic combo-multiselect component
Add a reusable multiselect dropdown component inspired by the issue
sidebar label picker, but decoupled from issue-specific logic.

Components:
- templates/shared/combolist.tmpl — generic template accepting Items,
  Name, Title, SelectedValues parameters
- web_src/js/features/combo-multiselect.ts — lightweight JS init that
  handles check/uncheck, search, and hidden input updates
- web_src/css/modules/combo-multiselect.css — check-mark visibility
  and selected-items list styling

Usage in any template:
  {{template "shared/combolist" dict
    "Name" "channels"
    "Title" "Update Channels"
    "Items" .AvailableChannels
    "SelectedValues" .SelectedChannelIDs
  }}

Items must have .Value and .Label fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:41:08 -05:00
jmiller 2c3aad51af Merge pull request 'fix(build): Go 1.23 maps.Values slices.Collect' (#371) from dev into main
Deploy MokoGitea / deploy (push) Failing after 25s
2026-05-31 16:38:42 +00:00
Jonathan Miller 88e210bffb fix(build): use slices.Collect for maps.Values (Go 1.23+ compat)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Failing after 25s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
In Go 1.23+, maps.Values returns iter.Seq not a slice.
Use slices.Collect() to materialize the iterator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:38:00 -05:00
jmiller 66a6a2afc1 Merge pull request 'fix(build): Go 1.23 maps.Values compatibility' (#370) from dev into main
Deploy MokoGitea / deploy (push) Failing after 22s
2026-05-31 16:31:39 +00:00
jmiller f73f628403 Merge pull request 'fix: tech-debt batch 5 — CSS cleanup' (#361) from fix/tech-debt-batch-5 into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Failing after 21s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 16:19:35 +00:00
Jonathan Miller c07443aa87 fix: resolve tech-debt batch 5 — CSS cleanup
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- fix(css): use calc(infinity * 1px) for --border-radius-full instead
  of magic 99999px value (supported in all modern browsers)
- fix(css): remove legacy .center class from 2015, replace 6 usages
  with tw-text-center utility class

Refs #318

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:19:01 -05:00
jmiller c1c7556916 Merge pull request 'fix: tech-debt batch 4 — parseIssueHref, job limit, stale TODOs' (#360) from fix/tech-debt-batch-4 into dev 2026-05-31 16:13:34 +00:00
Jonathan Miller 889f64009b fix: resolve tech-debt batch 4 — parseIssueHref, job limit, stale TODOs
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- fix(ts): parseIssueHref now uses URL pathname and trims appSubUrl
  for correct issue link parsing with sub-path deployments
- fix(actions): enforce MaxJobNumPerRun (256) limit when creating jobs,
  rejecting workflows that exceed the GitHub-compatible limit
- chore: remove stale TODO comment on OAuth redirect route

Refs #325, #334

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:12:44 -05:00
jmiller 74935e3bed Merge pull request 'fix(licenses): remove duplicate DeleteLicenseKey (build fix)' (#358) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m39s
2026-05-31 16:07:13 +00:00
Jonathan Miller 27c4d176f4 fix(licenses): remove duplicate DeleteLicenseKey declaration
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 26s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:06:41 -05:00
jmiller 53bcb3cdf9 Merge pull request 'fix: tech-debt batch 3 — remove deprecated functions, use stdlib' (#357) from fix/tech-debt-batch-3 into dev 2026-05-31 16:05:15 +00:00
Jonathan Miller b9b3026122 fix: resolve tech-debt batch 3 — remove deprecated functions, use stdlib
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
PR RC Release / Build RC Release (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- refactor(go): replace ValuesRepository with maps.Values (Go 1.21+)
- refactor(go): remove CanEnableEditor wrapper, use CanContentChange directly
- chore: remove stale TODO comments about project column route naming

Refs #311, #317

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 11:03:42 -05:00
jmiller bc95ecf4d5 Merge pull request 'feat(updates): extension metadata settings, tab visibility, platform support' (#356) from dev into main
Deploy MokoGitea / deploy (push) Failing after 28s
2026-05-31 16:01:49 +00:00
Jonathan Miller d30e7d7a5a feat(updates): extension metadata settings for update feed generation
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 7s
PR RC Release / Build RC Release (pull_request) Failing after 27s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Add configurable fields: element name, display name, description,
  extension type, maintainer, maintainer URL, info URL, target version,
  PHP minimum
- Add platform dropdown: joomla, dolibarr, wordpress, prestashop,
  drupal, composer, both
- Update Joomla XML generator to use metadata from config (falls back
  to repo-derived values when not set)
- Add GetEffectiveConfig() for resolving repo → org → nil config chain
- Add locale keys for all new settings fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:58:45 -05:00
Jonathan Miller e0c69d792c fix(licenses): only show licenses tab when licensing is enabled
Uses LicensingEnabled (org config) instead of EnableLicenses/IsRepoAdmin.
Tab is now hidden when the org hasn't enabled the licensing system.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:53:06 -05:00
jmiller d4bb976544 Merge pull request 'fix: tech-debt batch 2 — dropdown validation, editor cleanup, rename' (#350) from fix/tech-debt-batch-2 into dev 2026-05-31 15:52:26 +00:00
Jonathan Miller d74ae92e5b fix: resolve tech-debt batch 2 — dropdown validation, editor cleanup, rename
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- fix(templates): add required validation to issue dropdown fields
- refactor(ts): remove redundant `handled` field from MarkdownHandleIndentionResult
- refactor(go): rename HasOrgOrUserVisible to IsOwnerVisibleToDoer for clarity

Refs #311, #334

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:50:33 -05:00
jmiller a35fb4695c Merge pull request 'chore: sync dev to main (namespace rename + all fixes)' (#348) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m18s
2026-05-31 15:40:34 +00:00
jmiller 2982d2d445 Merge pull request 'fix: tech-debt batch 1 + full namespace migration to code.mokoconsulting.tech' (#344) from fix/tech-debt-batch-1 into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 15:35:31 +00:00
jmiller 70c31a4953 Merge pull request 'fix(updates): correct dlid prefix and Joomla standard alignment' (#345) from dev into main
Deploy MokoGitea / deploy (push) Failing after 2m32s
2026-05-31 15:31:09 +00:00
Jonathan Miller b3488e2715 fix(updates): correct dlid prefix and align XML with Joomla standard
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Fix downloadkey prefix: "&dlid=" → "dlid=" (Joomla handles the separator)
- Reorder XML fields to match Akeeba/Joomla convention
- Add sha512 and php_minimum optional fields to update XML struct

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:30:31 -05:00
Jonathan Miller 9a5720e8ad chore: rename Go module from git. to code.mokoconsulting.tech (#336)
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Full namespace migration: update the Go module path and all import
statements from git.mokoconsulting.tech to code.mokoconsulting.tech.
Also updates all URL references in templates, workflows, configs,
tests, and documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:28:25 -05:00
Jonathan Miller 5e4ac1617e fix(updates): correct dlid prefix and align XML with Joomla standard
- Fix downloadkey prefix: "&dlid=" → "dlid=" (Joomla handles the separator)
- Reorder XML fields to match Akeeba/Joomla convention
- Add sha512 and php_minimum optional fields to update XML struct

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:23:20 -05:00
Jonathan Miller 682ab42888 fix: resolve three tech-debt FIXME/TODO items
- fix(blame): set HasSourceRenderedToggle for renderable files so that
  permalinks include ?display=source for correct line-number linking
- fix(settings): translate team permission strings using data-locale
  attributes instead of raw API values
- fix(dropzone): use relative path for non-image attachment markdown
  links for consistency with image attachments

Refs #318, #334

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:13:51 -05:00
jmiller 6c913abbda Merge pull request 'feat(licenses): plaintext key storage with copy buttons' (#342) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m35s
2026-05-31 15:08:02 +00:00
Jonathan Miller 809c387054 feat(licenses): store keys in plaintext, show full key with copy button
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 8s
PR RC Release / Build RC Release (pull_request) Successful in 27s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
License keys are domain-locked so hashing is unnecessary. Store the
full key in KeyRaw column for permanent visibility. Keys table now
shows the complete key with a clipboard copy button per row.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:07:20 -05:00
jmiller 878671ebc9 Merge pull request 'feat(licenses): platform enforcement, key deletion, expired key cleanup' (#340) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m4s
2026-05-31 15:03:46 +00:00
Jonathan Miller 4efc679c8b feat(licenses): platform enforcement, key deletion, expired key cleanup
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Block update feed endpoints based on repo platform setting:
  Joomla-only repos return 404 on /updates/dolibarr.json and vice versa
- Show feed URLs section only when licensing is enabled
- Add delete button for license keys (site admin only)
- Add weekly cron job to purge expired keys older than 1 year
- Add DeleteLicenseKey and DeleteExpiredKeys model functions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 10:03:23 -05:00
Jonathan Miller 68ee152cfc fix(licenses): show feed URLs based on repo update platform setting
Only show Joomla XML URL when platform is joomla/both/empty.
Only show Dolibarr JSON URL when platform is dolibarr/both.
Also gate the entire feed URLs section behind LicensingEnabled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:54:38 -05:00
jmiller c7cfcf894b Merge pull request 'fix(licenses): remove repo unit requirement causing 404s' (#339) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m35s
2026-05-31 14:48:30 +00:00
jmiller 18510b0da3 Merge pull request 'fix(licenses): remove repo unit requirement causing 404s' (#338) from fix/admin-delete-only into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 9s
PR RC Release / Build RC Release (pull_request) Successful in 31s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 14:48:15 +00:00
Jonathan Miller 1bf51f3aa5 fix(licenses): remove repo unit requirement from licenses routes
Universal: PR Check / Branch Policy (pull_request) Successful in 13s
Branch Policy Check / Verify merge target (pull_request) Successful in 14s
Branch Cleanup / Delete merged branch (pull_request) Successful in 7s
PR RC Release / Build RC Release (pull_request) Successful in 15s
Universal: PR Check / Validate PR (pull_request) Failing after 22s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
The licenses feature is gated by org-level LicensingEnabled config,
not by per-repo unit enablement. Requiring TypeLicenses unit on repos
caused 404s since it wasn't in DefaultRepoUnits.

Write permissions are still enforced in handlers via
CanWrite(TypeLicenses). Org routes retain reqUnitAccess for
team-level permission control.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:47:51 -05:00
jmiller bbe3e570fe Merge pull request 'chore: migrate namespace from git. to code.mokoconsulting.tech' (#337) from chore/namespace-migration into main
Deploy MokoGitea / deploy (push) Failing after 4m27s
2026-05-31 14:46:21 +00:00
Jonathan Miller 26bbe690fd chore: migrate namespace from git. to code.mokoconsulting.tech (#336)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 28s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Update all URLs in manifest.xml and updates.xml to use the new
code.mokoconsulting.tech domain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:45:58 -05:00
Jonathan Miller 80be67b2ef chore: migrate namespace from git. to code.mokoconsulting.tech (#336)
Update all URLs in manifest.xml and updates.xml to use the new
code.mokoconsulting.tech domain.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:37:42 -05:00
jmiller bfa9043bc8 Merge pull request 'feat(licenses): UI/UX cleanup, permissions system, and key management improvements' (#306) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m35s
2026-05-31 14:22:04 +00:00
jmiller e6afc9f8c3 Merge pull request 'feat(licenses): UI/UX cleanup, permissions system, and key management improvements' (#305) from fix/admin-delete-only into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
PR RC Release / Build RC Release (pull_request) Successful in 26s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 14:21:02 +00:00
Jonathan Miller c20139393d fix(licenses): pass IsOrganizationOwner to org licenses template
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Required for the custom key input field visibility check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:04:12 -05:00
Jonathan Miller 1a4d0739db fix(permissions): admin teams implicitly inherit access to all unit types
Admin-level teams (team.authorize >= Admin) now implicitly get admin
access to all unit types in UnitMaxAccess(), even without explicit
TeamUnit records. This resolves the long-standing TEAM-UNIT-PERMISSION
issue where adding new units (like TypeLicenses) left existing admin
teams without access.

Resolves: #304

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 09:00:49 -05:00
Jonathan Miller ed79a48119 feat(licenses): UI/UX cleanup, permissions, renew, auto-domain, custom keys
- Replace confirm() with Gitea modal system (link-action + data-modal-confirm)
- Add confirmation modal to revoke key action
- Fix clipboard copy to use data-clipboard-target with tooltip feedback
- Localize all hardcoded English strings (feed labels, "unlimited", "Master")
- Improve key creation flash with security-focused message + copy button
- Add count badge to org licenses nav tab
- Add icon to org settings navbar for update streams
- Add help text to "Active" checkboxes explaining deactivation impact
- Fix empty state message to reference UI creation (not just API)
- Compact tables for denser license data display
- Add orange "Master" label to master package rows
- Conditional feed buttons on release page (only when licensing enabled)
- Add TypeLicenses unit type with Read/Write/Admin team permissions
- Route-level permission enforcement via RequireUnitReader/Writer
- Add "Renew" action for license keys (extends by package duration)
- Auto-associate domain on first heartbeat (lock-on-first-use)
- Enforce max_sites limit during domain auto-association
- Allow site admins and org owners to set custom license key values

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 08:54:29 -05:00
Jonathan Miller b77da17f38 feat(licenses): implement full commercial license management system
Add key editing, domain enforcement, purchase webhooks, public
validation API, channels multiselect, Joomla downloadkey element,
licensing feature toggle, unified update system, release tag
enforcement, heartbeat tracking, and improved settings UX.

Phase 1: Full key display with AbsoluteShort dates, master package
protection (hide edit/delete in UI, reject in handlers).

Phase 2: Key edit page with template, handlers, and routes for both
repo and org levels. Master keys redirect away.

Phase 3: Domain restriction checking against CSV allowlist,
MaxSites enforcement via CountUniqueDomainsByKey and
IsDomainKnownForKey, dlid query param support for Joomla.

Phase 4: Purchase webhook (POST /license-keys/purchase) with
PaymentRef idempotency. Public validation endpoint
(POST /license-keys/validate) outside auth middleware.
PATCH /license-keys/{id} for API key editing.

Phase 5: Channels multiselect using org UpdateStreamConfig streams
rendered as checkboxes, stored as JSON arrays.

Additional: downloadkey XML element, LicensingEnabled toggle on
UpdateStreamConfig, Dolibarr endpoint unified with key validation,
release tag suffix enforcement, LastHeartbeatUnix field with
TouchHeartbeat, and cleaned-up settings pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 01:31:51 -05:00
jmiller b1a9b09f5b Merge pull request 'chore: merge dev into main — toggle fix' (#295) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m59s
2026-05-31 04:22:47 +00:00
jmiller bec7b70ff5 Merge branch 'main' into dev
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 23s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:22:29 +00:00
jmiller 92b4cd61c2 Merge pull request 'fix(ui): details/summary toggle for create package' (#294) from fix/admin-delete-only into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 5s
Universal: PR Check / Branch Policy (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Failing after 18s
PR RC Release / Build RC Release (pull_request) Successful in 32s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:22:08 +00:00
Jonathan Miller dc2647977c fix(ui): use HTML details/summary for package create toggle
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 5s
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Replace broken JavaScript onclick toggle with native HTML
<details>/<summary> element. Works without JS, accessible,
and styled as a Fomantic UI button.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 23:21:42 -05:00
jmiller 685d89acf9 Merge pull request 'chore: merge dev into main — admin permissions' (#293) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m9s
2026-05-31 04:19:17 +00:00
jmiller 8ceddefbdb Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 25s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:19:04 +00:00
jmiller ea2666948e Merge pull request 'feat(permissions): site admin only for delete' (#292) from fix/admin-delete-only into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 25s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:18:53 +00:00
Jonathan Miller 3aabd1b1f9 feat(permissions): only site admins can delete license packages
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Delete button only visible to site admins (super admins)
- Delete handler checks ctx.IsUserSiteAdmin() and returns 404 otherwise
- Repo admins can still create, edit, revoke — but not delete
- IsSiteAdmin set in both repo and org context data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 23:18:31 -05:00
jmiller 0328258529 Merge pull request 'chore: merge dev into main — org update streams' (#291) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m3s
2026-05-31 04:09:53 +00:00
jmiller e6ff9a99f9 Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:09:42 +00:00
jmiller 4138ab7d47 Merge pull request 'feat(org): Update Streams settings page + package edit/delete' (#290) from feat/repo-update-settings into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
PR RC Release / Build RC Release (pull_request) Successful in 25s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:09:30 +00:00
Jonathan Miller d75e648970 feat(org): add Update Streams settings page in org settings
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add "Licenses & Update Streams" tab to org settings sidebar with:
- Stream mode: Joomla standard or Custom
- Active streams table showing name, suffix, description
- Custom streams JSON editor
- Saves org-level defaults that repos inherit

Ref #265

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 23:09:07 -05:00
jmiller 06a382e82e Merge pull request 'chore: merge dev into main — package edit/delete' (#289) from dev into main
Deploy MokoGitea / deploy (push) Failing after 3m39s
2026-05-31 04:04:41 +00:00
jmiller 0ff4b12f27 Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 23s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:04:29 +00:00
jmiller 53f0472e4f Merge pull request 'feat(licenses): edit and delete packages via web UI' (#288) from feat/repo-update-settings into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 21s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 04:04:18 +00:00
Jonathan Miller 021ddbb17a feat(licenses): edit and delete license packages via web UI
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add edit and delete actions for license packages:
- Edit button (pencil icon) opens edit form with all package fields
- Delete button (trash icon) with confirmation dialog
- Edit form includes active/inactive toggle
- Routes: GET/POST /licenses/packages/{id}/edit, POST /licenses/packages/{id}/delete

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 23:03:44 -05:00
jmiller 12f78e8feb Merge pull request 'chore: merge dev into main — platform settings' (#287) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m8s
2026-05-31 03:57:18 +00:00
jmiller b72d419fb1 Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 28s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:57:06 +00:00
jmiller 865e8b9bfa Merge pull request 'feat(updates): per-repo platform + require-key + platform buttons' (#286) from feat/repo-update-settings into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:56:56 +00:00
Jonathan Miller 3a5ca580db feat(updates): per-repo platform, require-key, platform-aware buttons
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
- Repo settings: platform dropdown (Joomla/Dolibarr/Both) + require key
- Releases page buttons change based on platform setting
- Update feed enforces require-key (empty response without valid key)
- key_plain column stores full key for copy functionality
- DB migrations v337 (key_plain) + v338 (platform, require_key)

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:55:55 -05:00
jmiller 93f186bd1d Merge pull request 'chore: merge dev into main — UI fixes' (#285) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m40s
2026-05-31 03:48:29 +00:00
jmiller 56988e810e Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 47s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:48:11 +00:00
jmiller f8b7af30d9 Merge pull request 'fix(ui): always-visible create package form + org locale strings' (#284) from fix/licenses-ui-v3 into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
PR RC Release / Build RC Release (pull_request) Successful in 39s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:47:53 +00:00
Jonathan Miller df06e11704 fix(ui): always-visible create package form + clearer labels + org locale strings
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
PR RC Release / Build RC Release (pull_request) Successful in 10s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 20s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Replace toggle button with always-visible "Create New License Package"
section. Added org settings locale strings for Update Streams page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:47:29 -05:00
gitea-actions[bot] 51517a5275 chore: update channels for 05.14.00 [skip ci] 2026-05-31 03:46:14 +00:00
gitea-actions[bot] 336338b541 chore(ci): remove update-server.yml for update server migration [skip ci] 2026-05-31 03:46:11 +00:00
gitea-actions[bot] 8f537df6c5 chore(ci): remove cascade-dev.yml for update server migration [skip ci] 2026-05-31 03:46:02 +00:00
gitea-actions[bot] 7ac8c3d0a1 chore(ci): remove auto-bump.yml for update server migration [skip ci] 2026-05-31 03:45:51 +00:00
gitea-actions[bot] 3465b4fa01 chore(ci): remove pre-release.yml for update server migration [skip ci] 2026-05-31 03:45:42 +00:00
gitea-actions[bot] 0b4e7575eb chore(ci): remove auto-release.yml for update server migration [skip ci] 2026-05-31 03:45:33 +00:00
gitea-actions[bot] 508185f7ad chore(release): build 05.14.00 [skip ci] 2026-05-31 03:45:25 +00:00
jmiller c8ba0647d3 Merge pull request 'chore: merge dev into main' (#283) from dev into main
Deploy MokoGitea / deploy (push) Successful in 5m56s
2026-05-31 03:44:31 +00:00
jmiller d55da332cf Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 10s
Universal: Auto Version Bump / Version Bump (push) Failing after 9s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 32s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 5m29s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:44:16 +00:00
jmiller a04e237f17 Merge pull request 'feat(licenses): org settings, copyable keys, master keys' (#282) from feat/org-licensing into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: Build & Release / Promote to RC (pull_request) Failing after 12s
PR RC Release / Build RC Release (pull_request) Successful in 28s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:44:06 +00:00
jmiller e7cc4c120f Merge branch 'dev' into feat/org-licensing
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:43:55 +00:00
jmiller aa54f3834e chore: sync updates.xml 05.13.00 from main [skip ci] 2026-05-31 03:38:14 +00:00
gitea-actions[bot] 4d93f23037 chore: update channels for 05.13.00 [skip ci] 2026-05-31 03:37:46 +00:00
gitea-actions[bot] d7e2ffd02b chore(release): build 05.13.00 [skip ci] 2026-05-31 03:37:12 +00:00
jmiller b9d81ca5c5 Merge pull request 'chore: merge dev into main — URL fix' (#281) from dev into main
Deploy MokoGitea / deploy (push) Successful in 4m34s
2026-05-31 03:36:12 +00:00
jmiller 59c62dc687 Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 5s
Universal: PR Check / Branch Policy (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Universal: Auto Version Bump / Version Bump (push) Failing after 13s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 4m8s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:35:42 +00:00
jmiller b14ffa083e Merge pull request 'fix(ui): full domain URL in update feed fields' (#280) from fix/update-feed-urls into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 20s
Universal: Build & Release / Promote to RC (pull_request) Failing after 30s
PR RC Release / Build RC Release (pull_request) Successful in 50s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:34:56 +00:00
Jonathan Miller 2cc57bbbbc fix(ui): show full domain URL in update feed copy fields
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
PR RC Release / Build RC Release (pull_request) Successful in 5s
Universal: PR Check / Validate PR (pull_request) Failing after 17s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m40s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Use .Repository.HTMLURL instead of AppSubUrl+RepoLink so the
copyable update feed URLs include the full domain name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:34:12 -05:00
jmiller 3cd7687c06 chore: sync updates.xml 05.12.00 from main [skip ci] 2026-05-31 03:32:48 +00:00
gitea-actions[bot] c3b2643b0c chore: update channels for 05.12.00 [skip ci] 2026-05-31 03:32:46 +00:00
gitea-actions[bot] 0159e567e2 chore(release): build 05.12.00 [skip ci] 2026-05-31 03:32:10 +00:00
jmiller f194b204b4 Merge pull request 'chore: merge dev into main — org licenses + master keys' (#279) from dev into main
Deploy MokoGitea / deploy (push) Successful in 5m50s
2026-05-31 03:31:24 +00:00
jmiller f118f084ce Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Failing after 8s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 35s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 5m30s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:31:09 +00:00
jmiller 2821c35326 Merge pull request 'feat(licenses): org licenses page + master keys + menu fixes' (#278) from feat/org-licensing into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Universal: Build & Release / Promote to RC (pull_request) Failing after 17s
PR RC Release / Build RC Release (pull_request) Successful in 29s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:30:59 +00:00
Jonathan Miller 5b02cf188e feat(licenses): org-level licenses page, master keys, and menu fixes
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m13s
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Major licensing UI improvements:
- Org-level Licenses tab in org menu (visible to org members)
- Org-level Licenses page with full CRUD (packages, keys, revoke)
- Auto-created master key: when admin first visits Licenses page,
  a Master (Internal) package + key is auto-generated
- Master keys marked with orange "Master" badge in key list
- Revoking a master key auto-creates a new one on next visit
- Fixed "New Package" button toggle (was using tw-hidden class
  that didn't work, now uses style.display)
- IsRepoAdmin set as context data for template access
- Master keys have IsInternal=true, lifetime, all channels

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:30:33 -05:00
Jonathan Miller 689173ecab feat(licenses): auto-create master key for org/repo
When an admin first visits the Licenses page, a master license package
and key are automatically created:
- Master package: lifetime, unlimited, all channels, all repos
- Master key: IsInternal=true, never expires
- Raw key shown once with copy instructions
- If master key is revoked, a new one is created on next visit

The master key is always present — revoking it and revisiting the page
generates a fresh one.

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:26:24 -05:00
jmiller b2fe44fbc3 chore: sync updates.xml 05.11.00 from main [skip ci] 2026-05-31 03:17:54 +00:00
gitea-actions[bot] 0e89ef9944 chore: update channels for 05.11.00 [skip ci] 2026-05-31 03:17:53 +00:00
gitea-actions[bot] 522dadecf0 chore(release): build 05.11.00 [skip ci] 2026-05-31 03:17:24 +00:00
jmiller f1b9bb2f3d Merge pull request 'chore: merge dev into main — licenses tab fix v2' (#277) from dev into main
Deploy MokoGitea / deploy (push) Failing after 4m28s
2026-05-31 03:16:44 +00:00
jmiller 7bbaf218d5 Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Failing after 8s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 32s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 4m11s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:16:31 +00:00
jmiller 33a550f838 Merge pull request 'fix(ui): IsRepoAdmin for Licenses tab' (#276) from fix/licenses-tab-v2 into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
PR RC Release / Build RC Release (pull_request) Successful in 26s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:16:21 +00:00
Jonathan Miller e29ee5f91b fix(ui): set IsRepoAdmin context data for Licenses tab visibility
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 4s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m9s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
The template couldn't call .Permission.IsAdmin() directly. Set
IsRepoAdmin as a context data variable so the template can use it.
Licenses tab now shows for repo admins even without packages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:15:39 -05:00
jmiller 984a99188e chore: sync updates.xml 05.10.00 from main [skip ci] 2026-05-31 03:07:16 +00:00
gitea-actions[bot] 92fc77a6d1 chore: update channels for 05.10.00 [skip ci] 2026-05-31 03:07:15 +00:00
gitea-actions[bot] ea411e09be chore(release): build 05.10.00 [skip ci] 2026-05-31 03:06:36 +00:00
jmiller 9b141b39c5 Merge pull request 'chore: merge dev into main — licenses tab fix' (#275) from dev into main
Deploy MokoGitea / deploy (push) Successful in 4m35s
chore: merge dev into main — licenses tab fix (#275)
2026-05-31 03:05:51 +00:00
jmiller 85e4356fce Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: Auto Version Bump / Version Bump (push) Failing after 13s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 34s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 4m13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:05:36 +00:00
jmiller 1654181a9e Merge pull request 'fix(ui): show Licenses tab for admins always' (#274) from fix/licenses-tab-always-admin into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Universal: Build & Release / Promote to RC (pull_request) Failing after 14s
PR RC Release / Build RC Release (pull_request) Successful in 28s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 03:05:25 +00:00
Jonathan Miller 282ef8f3e7 fix(ui): show Licenses tab for repo admins even without packages
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m14s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
The Licenses tab was hidden when no packages existed, making it
impossible for admins to find the page to create their first package.
Now shows for repo admins always, and for everyone when packages exist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 22:04:44 -05:00
jmiller a34eb53b2a chore: sync updates.xml 05.09.00 from main [skip ci] 2026-05-31 02:47:56 +00:00
gitea-actions[bot] 75d53c11b4 chore: update channels for 05.09.00 [skip ci] 2026-05-31 02:47:52 +00:00
gitea-actions[bot] 8556314468 chore(release): build 05.09.00 [skip ci] 2026-05-31 02:47:16 +00:00
jmiller 22624d662c Merge pull request 'chore: merge dev into main — licenses UI, update server, visibility' (#273) from dev into main
Deploy MokoGitea / deploy (push) Successful in 5m5s
chore: merge dev into main — all features (#273)
2026-05-31 02:46:35 +00:00
jmiller 91646c505b Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Failing after 8s
Universal: PR Check / Validate PR (pull_request) Failing after 8s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 30s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 4m43s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 02:46:22 +00:00
jmiller b994fcdb9a Merge pull request 'fix(templates): AppSubUrl for feed URLs' (#272) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: Build & Release / Promote to RC (pull_request) Failing after 8s
PR RC Release / Build RC Release (pull_request) Successful in 20s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-31 02:39:45 +00:00
Jonathan Miller 6dc2c1dec7 fix(templates): use AppSubUrl+RepoLink for update feed URLs
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m17s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:39:10 -05:00
jmiller 4372e956de Merge pull request 'fix: Permission.IsAdmin for licenses' (#271) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 02:34:00 +00:00
Jonathan Miller a61cdbe2f1 fix: use ctx.Repo.Permission.IsAdmin() for license admin checks
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m13s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:33:34 -05:00
jmiller ac4092fbab Merge pull request 'feat(licenses): web UI for license management' (#270) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 02:27:36 +00:00
Jonathan Miller 30197e4e97 feat(licenses): web UI for package creation, key generation, and revocation
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m20s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add full license management web forms to the Licenses page:

- "New Package" form: name, description, duration, max sites, channels
- "Generate Key" button per package: creates key with auto-expiry
- "Revoke" button per key: deactivates the key
- New key display: shows raw key once with copy instructions
- Update Feed URLs section: copyable Joomla/Dolibarr endpoint URLs
- Admin-only controls: forms only visible to repo admins

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:27:12 -05:00
jmiller 12132486a0 Merge pull request 'fix(routes): use optSignIn for licenses page' (#269) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 02:20:29 +00:00
Jonathan Miller 3f29562938 fix(routes): use optSignIn for licenses page
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m24s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
The licenses page was using reqSignIn which blocks API token access
and redirects to login. Use optSignIn so the page is accessible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:18:38 -05:00
jmiller 4a931dddab Merge pull request 'fix(templates): use DateUtils.TimeSince in licenses template' (#268) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 02:12:01 +00:00
Jonathan Miller c6f42487b5 fix(templates): use DateUtils.TimeSince instead of DateTime
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 54s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Fix template error: function "DateTime" not defined. Use
DateUtils.TimeSince which is the correct template function.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:11:44 -05:00
jmiller b101a2304a Merge pull request 'feat(licenses): add Licenses tab, page, and stream config' (#267) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 02:04:12 +00:00
Jonathan Miller 381952f6d2 feat(licenses): add Licenses tab and page for repos
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 54s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add a Licenses tab in the repo header that shows when license packages
exist for the repo's owner. The tab displays:
- License packages with name, duration, allowed channels, key count
- Issued keys with prefix, licensee, expiry, and status

Also includes:
- Org-level default update streams with per-repo override (#265)
- Full Joomla channel names in update feeds
- Update Feed button on releases page
- DB migration v336 for update_stream_config table

The Licenses tab appears after Packages in the repo header, gated by
whether any license packages exist for the owner.

Ref #239, #265

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 21:03:52 -05:00
jmiller 1c667d9da9 Merge pull request 'feat(updates): org-level default streams with per-repo override' (#266) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 01:50:03 +00:00
Jonathan Miller a88e3f8787 feat(updates): org-level default streams with per-repo override
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m29s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add configurable update streams at org and repo level:

- UpdateStreamConfig model: stores stream mode (joomla/custom) and
  custom stream definitions (name, suffix, description)
- Resolution chain: repo override → org default → Joomla defaults
- MatchStreamFromTag: matches release tags to streams using configured
  suffixes (longest match wins)
- Both Joomla XML and Dolibarr JSON generators use effective streams
- DB migration v336 creates update_stream_config table
- Default Joomla streams: stable, release-candidate, beta, alpha,
  development
- Custom streams support any tag suffix (e.g. -lts, -nightly, -security)

Ref #265

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 20:49:46 -05:00
jmiller 4012f3bea9 chore: add .mokogitea/workflows/cascade-dev.yml from moko-platform [skip ci] 2026-05-31 01:45:42 +00:00
jmiller 095b78b2a7 chore: add .mokogitea/workflows/cascade-dev.yml from moko-platform [skip ci] 2026-05-31 01:42:13 +00:00
jmiller ff72cd0cb0 Merge pull request 'feat(updates): use full Joomla channel names in update feeds' (#264) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 01:32:01 +00:00
Jonathan Miller 50454db3fb feat(updates): use full Joomla channel names in update feeds
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m0s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Use the full Joomla convention for update stream tag names:
- dev → development
- rc → release-candidate
- alpha, beta, stable unchanged

Add NormalizeChannel() helper that maps shorthand names (dev, rc)
to full names so license key allowed_channels work with either
format. Applied in XML generation, JSON generation, and key
validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 20:31:43 -05:00
jmiller eab36f26aa Merge pull request 'feat(ui): add Update Feed button on releases page' (#263) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 01:24:10 +00:00
Jonathan Miller 4ce332d031 feat(ui): add Update Feed button on releases page
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 50s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add an "Update Feed" button next to the RSS link on the releases page
that links to the repo's updates.xml endpoint. Only shown on the
releases view (not tags).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 20:23:51 -05:00
jmiller 1b1ad35df4 Merge pull request 'fix(api): set IsActive=true when creating license packages' (#262) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 01:19:13 +00:00
Jonathan Miller 426cffc224 fix(api): set IsActive=true when creating license packages
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 53s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Same bug as keys — packages were created with is_active=false
causing all key validation to reject even valid keys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 20:18:11 -05:00
jmiller 0716ad0edd chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-31 01:10:19 +00:00
jmiller 0572e6a164 Merge pull request 'fix(api): set IsActive=true when creating license keys' (#261) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 01:09:00 +00:00
Jonathan Miller 4e51f48285 fix(api): set IsActive=true when creating license keys
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 56s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Keys were created with is_active=false (DB default) because the API
handler didn't explicitly set IsActive. This caused all key validation
to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 20:08:39 -05:00
jmiller aa56925bba Merge pull request 'feat(settings): releases visibility help text + issues dropdown' (#260) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 00:59:26 +00:00
Jonathan Miller fc895aa70d feat(settings): add help text for releases visibility and update feeds
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 49s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Clarify that update feeds (updates.xml, dolibarr.json) are always
accessible regardless of the releases visibility setting. The
visibility dropdown controls whether the releases page is browsable
by anonymous visitors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 19:59:02 -05:00
jmiller 1db8435737 Merge pull request 'feat(settings): add visibility dropdown to issues unit' (#259) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-31 00:50:44 +00:00
Jonathan Miller 71a486b534 feat(settings): add visibility dropdown to issues unit
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m5s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add the same inline visibility control (Private / Public) to the
issues section on the repo settings page. Now wiki, releases, and
issues all have visibility dropdowns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 19:50:13 -05:00
jmiller 90b9af6e3e Merge pull request 'feat(settings): inline visibility controls on repo settings page' (#258) from feat/inline-visibility-settings into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
feat(settings): inline visibility controls on repo settings page (#258)
2026-05-31 00:42:06 +00:00
Jonathan Miller a99af91ab4 feat(settings): inline visibility controls on repo settings page
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 58s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add per-unit visibility dropdown (Private / Public) directly on the
repo settings page next to each unit's enable checkbox. This replaces
the need to navigate to a separate Public Access settings page.

Supported units: Code, Wiki, Issues, Releases. Each gets a dropdown
that controls AnonymousAccessMode — when set to Public, the unit is
readable by anonymous visitors even on private repos.

Closes #238

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 19:35:56 -05:00
gitea-actions[bot] 0eb81f9c1a chore(release): build 05.08.00 [skip ci] 2026-05-30 21:49:04 +00:00
jmiller 6498459e49 Merge pull request 'chore: merge dev into main — all build fixes' (#256) from dev into main
Deploy MokoGitea / deploy (push) Failing after 7m17s
chore: merge dev into main — all build fixes (#256)
2026-05-30 21:47:57 +00:00
jmiller 2b82312b4e Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 11s
Universal: Auto Version Bump / Version Bump (push) Failing after 10s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 47s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 17m51s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-30 21:47:41 +00:00
jmiller 8808dfc3ce Merge pull request 'fix(api): fix route registration for license key API' (#255) from fix/api-route-registration into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 10s
Universal: Build & Release / Promote to RC (pull_request) Failing after 14s
PR RC Release / Build RC Release (pull_request) Successful in 23s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
fix(api): fix route registration for license key API (#255)
2026-05-30 21:44:19 +00:00
Jonathan Miller 470364e50c fix(api): fix route registration — reqAdmin and m.Delete pattern
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Branch Cleanup / Delete merged branch (pull_request) Successful in 1s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 52s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Fix two compilation errors in license key API routes:
- reqRepoAdmin() does not exist, use reqAdmin() instead
- m.Delete(handler) needs route pattern: m.Delete("", handler)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 16:42:22 -05:00
Jonathan Miller 69ad436ebb fix(api): fix route registration errors in license key API
Deploy MokoGitea / deploy (push) Failing after 20m27s
Fix reqRepoAdmin() -> reqAdmin() and m.Delete(handler) -> m.Delete("", handler)
to match the Gitea API route registration patterns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 16:17:37 -05:00
jmiller 65c5e3d213 Merge pull request 'fix(api): fix compilation errors in license key handlers' (#254) from fix/api-build-errors into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 5m1s
2026-05-30 21:08:18 +00:00
Jonathan Miller d40c8e1b85 fix(api): fix compilation errors in license key API handlers
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 9s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m18s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Replace ctx.Bind/ctx.APIErrorValidation (which don't exist on
APIContext) with web.GetForm() pattern used by all other API handlers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 15:56:54 -05:00
jmiller 39c373975e Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: Auto Version Bump / Version Bump (push) Failing after 15s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
PR RC Release / Build RC Release (pull_request) Successful in 47s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Deploy MokoGitea / deploy (push) Failing after 3m35s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-30 20:16:29 +00:00
jmiller b14fcb11f9 Merge pull request 'fix(ci): pre-deploy cleanup for memory' (#252) from fix/deploy-cleanup into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 14s
Universal: Build & Release / Promote to RC (pull_request) Failing after 21s
PR RC Release / Build RC Release (pull_request) Successful in 50s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-30 20:16:18 +00:00
Jonathan Miller 60a686ce63 fix(ci): pre-deploy cleanup — clear Docker cache and swap before build
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m49s
Add automatic cleanup step before Docker build in deploy workflow:
- Prune Docker build cache (can accumulate 30+ GB)
- Remove unused Docker images
- Clear swap to prevent thrashing during Go compilation

Fixes deploy failures caused by server memory exhaustion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 14:30:44 -05:00
jmiller 17ac356100 Merge pull request 'feat(updates): license key API + all remaining phases (Phase 4-6)' (#251) from feat/update-server-phase4-6 into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
feat(updates): license key API (Phase 4) (#251)
2026-05-30 19:09:05 +00:00
Jonathan Miller 68845abd59 feat(updates): license key management API endpoints (Phase 4)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Successful in 3s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 49s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add REST API for managing license packages and keys:

- GET/POST /api/v1/repos/{owner}/{repo}/license-packages
- GET/POST /api/v1/repos/{owner}/{repo}/license-keys
- DELETE /api/v1/repos/{owner}/{repo}/license-keys/{id}
- GET /api/v1/repos/{owner}/{repo}/license-keys/{id}/usage

API structs for create/edit/response, with raw key only returned on
creation. Requires repo admin permissions.

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 14:08:35 -05:00
gitea-actions[bot] ba0fdf3df1 chore(release): build 05.07.00 [skip ci] 2026-05-30 18:59:33 +00:00
jmiller ba0b17d9b5 Merge pull request 'chore: merge dev into main - startup fix' (#250) from dev into main
Deploy MokoGitea / deploy (push) Failing after 8m7s
chore: merge dev into main - startup fix (#250)
2026-05-30 18:57:42 +00:00
jmiller 29341b2b9b Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 4s
Universal: Auto Version Bump / Version Bump (push) Failing after 14s
Universal: PR Check / Validate PR (pull_request) Failing after 13s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
PR RC Release / Build RC Release (pull_request) Successful in 1m27s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 18m27s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-30 18:57:17 +00:00
jmiller eef72a5b00 Merge pull request 'fix(config): remove WithFileConfig from LandingPage option' (#249) from fix/startup-crash into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 4s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
PR RC Release / Build RC Release (pull_request) Successful in 1m22s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
fix(config): remove WithFileConfig from LandingPage (#249)
2026-05-30 18:56:43 +00:00
Jonathan Miller 530cfc91b1 fix(config): remove WithFileConfig from LandingPage option
Branch Policy Check / Verify merge target (pull_request) Successful in 3s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
PR RC Release / Build RC Release (pull_request) Successful in 5s
Universal: PR Check / Validate PR (pull_request) Failing after 12s
Branch Cleanup / Delete merged branch (pull_request) Successful in 4s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 2m30s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
The WithFileConfig for LandingPage tried to parse the app.ini
LANDING_PAGE string value (e.g. "home") as JSON into a struct,
causing a startup hang. The landing page setting should only be
managed through the dynamic config system (admin UI).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 13:55:33 -05:00
gitea-actions[bot] 39249dd0e7 chore(release): build 05.06.00 [skip ci] 2026-05-30 18:12:57 +00:00
jmiller aee484780b Merge pull request 'chore: merge dev into main' (#248) from dev into main
Deploy MokoGitea / deploy (push) Failing after 35m55s
chore: merge dev into main - license keys + dolibarr (#248)
2026-05-30 18:12:24 +00:00
jmiller e9ab1fd01d Merge branch 'main' into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: Build & Release / Promote to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Failing after 5s
PR RC Release / Build RC Release (pull_request) Successful in 26s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 35m56s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
2026-05-30 18:12:15 +00:00
jmiller 6e78d49e5a Merge pull request 'feat(updates): license key system and Dolibarr endpoint (Phase 2-3)' (#247) from feat/update-server-phase2-3 into dev
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: Build & Release / Promote to RC (pull_request) Failing after 12s
PR RC Release / Build RC Release (pull_request) Successful in 25s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
feat(updates): license key system and Dolibarr endpoint (#247)
2026-05-30 18:10:16 +00:00
Jonathan Miller 627a22ee53 feat(updates): license key system and Dolibarr endpoint (Phase 2-3)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 5s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 54s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add license key data model and Dolibarr update feed endpoint:

License key system:
- license_package table: subscription tiers with duration, max sites,
  repo scope (org-wide or specific repos), and allowed update channels
- license_key table: individual keys with SHA-256 hashed storage,
  domain restriction, custom start/end dates, internal/master key flag
- license_key_usage table: tracks update check activity per key
- DB migration v335 creates all three tables

Update server enhancements:
- Dolibarr JSON endpoint at /{owner}/{repo}/updates/dolibarr.json
- License key validation on update endpoints via ?key=MOKO-XXXX param
- Channel filtering: packages restrict which update streams keys access
- Invalid keys get empty XML response (Joomla-compatible "no updates")
- Usage tracking records domain, IP, user agent, version on each check

Key design decisions:
- Org-level master keys: IsInternal=true, package RepoScope="all"
- Keys stored as SHA-256 hashes, raw key only shown at creation
- Packages define allowed channels (e.g. ["stable","rc"] for Pro tier)
- MOKO-XXXX-XXXX-XXXX-XXXX format for license keys

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 13:09:47 -05:00
jmiller 3c5fc21976 chore: sync updates.xml 05.05.00 from main [skip ci] 2026-05-30 17:59:35 +00:00
gitea-actions[bot] 23d453a786 chore: update channels for 05.05.00 [skip ci] 2026-05-30 17:59:34 +00:00
gitea-actions[bot] ef99c7461d chore(release): build 05.05.00 [skip ci] 2026-05-30 17:55:54 +00:00
jmiller 658aa524c6 Merge pull request 'chore: merge dev into main' (#246) from dev into main
Deploy MokoGitea / deploy (push) Successful in 4m5s
chore: merge dev into main - update server + visibility (#246)
2026-05-30 17:55:19 +00:00
jmiller 44f6823292 Merge pull request 'feat(updates): built-in Joomla update server endpoint' (#245) from feat/update-server into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Failing after 12s
PR RC Release / Build RC Release (pull_request) Successful in 27s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 8m27s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
feat(updates): built-in Joomla update server endpoint (#239) (#245)
2026-05-30 17:55:02 +00:00
Jonathan Miller 6c06384966 feat(updates): built-in Joomla update server endpoint
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m4s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add GET /{owner}/{repo}/updates.xml that dynamically generates a
Joomla-compatible updates.xml from the repository's releases.

Features:
- Automatically maps release tags to channels (stable/rc/beta/alpha/dev)
- Finds .zip attachments for download URLs, falls back to archive URL
- Emits one entry per channel (latest release wins)
- Extracts version from tag names, strips common prefixes
- Publicly accessible (no auth required) for Joomla update clients

This is Phase 1 of #239 — the core dynamic update feed generation.
Future phases will add license key gating, Dolibarr support, and
repo settings UI.

Ref #239

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 12:54:31 -05:00
jmiller d4f2dc33b9 chore: sync updates.xml 05.04.00 from main [skip ci] 2026-05-30 17:34:17 +00:00
gitea-actions[bot] 3807dbbb2e chore: update channels for 05.04.00 [skip ci] 2026-05-30 17:34:15 +00:00
gitea-actions[bot] fd481329a5 chore(release): build 05.04.00 [skip ci] 2026-05-30 17:30:43 +00:00
jmiller 04ed2c7ed5 Merge pull request 'chore: merge dev into main' (#244) from dev into main
Deploy MokoGitea / deploy (push) Successful in 3m44s
chore: merge dev into main - visibility + landing page (#244)
2026-05-30 17:30:03 +00:00
jmiller c322bfae23 Merge pull request 'feat(permissions): section-based visibility - public units on private repos' (#243) from feat/section-based-visibility into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Failing after 13s
PR RC Release / Build RC Release (pull_request) Successful in 27s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 8m21s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
feat(permissions): section-based visibility (#238) (#243)
2026-05-30 17:29:45 +00:00
Jonathan Miller 7884e2f141 feat(permissions): section-based visibility — public units on private repos
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m7s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Fix three gaps that prevented per-unit public access from working on
private repositories:

1. Git HTTP handler (githttp.go): allow anonymous git pull for private
   repos when the target unit (code or wiki) has AnonymousAccessMode
   set to read. Previously only checked repo.IsPrivate.

2. Permission engine (repo_permission.go): call
   finalProcessRepoUnitPermission for anonymous users on private repos
   so that unit-level anonymous access modes are populated. Previously
   returned early with AccessModeNone, skipping anonymous mode setup.

3. Search/explore (repo_list.go): include private repos that have at
   least one unit with anonymous_access_mode > 0 in search results,
   so anonymous users can discover repos with public sections.

The existing settings UI at /settings/public_access already allows
configuring per-unit visibility. The home page redirect to the first
readable unit (e.g. wiki) also already works via checkHomeCodeViewable.

Closes #238

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 12:26:24 -05:00
jmiller b0acd521e5 chore: sync updates.xml 05.03.00 from main [skip ci] 2026-05-30 17:23:06 +00:00
gitea-actions[bot] 9c0e2b48cf chore: update channels for 05.03.00 [skip ci] 2026-05-30 17:23:05 +00:00
gitea-actions[bot] 1bff46b220 chore(release): build 05.03.00 [skip ci] 2026-05-30 17:19:34 +00:00
jmiller 44fd865ee6 Merge pull request 'chore: merge dev into main' (#242) from dev into main
Deploy MokoGitea / deploy (push) Successful in 4m8s
chore: merge dev into main - landing page admin setting (#242)
2026-05-30 17:18:44 +00:00
jmiller 4b6df79ae0 Merge pull request 'feat(admin): configurable default landing page from site administration' (#241) from feat/admin-landing-page into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: Build & Release / Promote to RC (pull_request) Failing after 12s
PR RC Release / Build RC Release (pull_request) Successful in 29s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 8m23s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
feat(admin): configurable default landing page (#240) (#241)
2026-05-30 17:18:16 +00:00
Jonathan Miller 1d1482a3dc feat(admin): configurable default landing page from site administration
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m6s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Add a dynamic config option to set the default landing page for
unauthenticated visitors from Site Administration > Settings. Options:
- Home (default explore page)
- Explore (repository explore)
- Organizations (org explore)
- Login (redirect to login)
- Custom path (any internal URL like /MokoConsulting)

The setting takes effect immediately without restart, using the same
dynamic config system as maintenance mode and web banner. Falls back
to the static LANDING_PAGE setting from app.ini if not configured.

Closes #240

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 12:17:40 -05:00
jmiller fba9c7eed9 chore: sync updates.xml 05.02.00 from main [skip ci] 2026-05-30 16:12:32 +00:00
gitea-actions[bot] 0438ed1b73 chore: update channels for 05.02.00 [skip ci] 2026-05-30 16:12:30 +00:00
gitea-actions[bot] 6045bf87d9 chore(release): build 05.02.00 [skip ci] 2026-05-30 16:08:48 +00:00
jmiller 540e3e129a Merge pull request 'chore: merge dev into main' (#237) from dev into main
Deploy MokoGitea / deploy (push) Successful in 4m5s
chore: merge dev into main — deploy trigger + changelog (#237)
2026-05-30 16:08:02 +00:00
jmiller 086c506a10 Merge pull request 'docs: update CHANGELOG for actions bot rebrand and deploy trigger' (#236) from chore/changelog-actions-bot into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote to RC (pull_request) Failing after 13s
PR RC Release / Build RC Release (pull_request) Successful in 33s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 8m28s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
docs: update CHANGELOG for actions bot rebrand and deploy trigger (#236)
2026-05-30 16:07:31 +00:00
Jonathan Miller 5bf2f57f53 docs: update CHANGELOG for actions bot rebrand and deploy trigger
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m9s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 11:06:40 -05:00
jmiller d3bca854e5 chore: add .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-05-30 16:03:30 +00:00
jmiller 203d090123 chore: add .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-05-30 16:01:47 +00:00
jmiller ce344910b2 Merge pull request 'fix(ci): auto-deploy to production on merge to main' (#235) from fix/deploy-on-main-merge into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
fix(ci): auto-deploy to production on merge to main (#235)
2026-05-30 15:59:42 +00:00
Jonathan Miller 2fe549482d fix(ci): auto-deploy to production on merge to main
Branch Policy Check / Verify merge target (pull_request) Successful in 2s
PR RC Release / Build RC Release (pull_request) Successful in 3s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m17s
Add push trigger on main branch to deploy-mokogitea.yml so merges
to main automatically deploy to production. When triggered by push,
the version is derived from git describe and environment defaults to
production. Manual workflow_dispatch still works for explicit version
deployments and dev environment targeting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 10:58:52 -05:00
jmiller 7aa930227e Merge pull request 'chore: merge dev into main [skip ci]' (#104) from dev into main
chore: merge dev into main — actions bot rebrand + branch protection whitelist (#104)
2026-05-30 15:49:05 +00:00
jmiller 524b38f494 Merge pull request 'feat(actions): rebrand actions bot user and add branch protection whitelist' (#234) from feat/actions-bot-rebrand-and-branch-protection into dev
Universal: Auto Version Bump / Version Bump (push) Has been skipped
feat(actions): rebrand actions bot user and add branch protection whitelist (#234)
2026-05-30 15:48:06 +00:00
Jonathan Miller d4824dc05b feat(actions): rebrand actions bot user and add branch protection whitelist
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Successful in 1m13s
Rebrand the built-in actions bot user from upstream Gitea naming to
MokoGitea branding:
- Name: gitea-actions → mokogitea-actions
- FullName: Gitea Actions → MokoGitea Actions
- Email: teabot@gitea.io → mokogitea-actions[bot]@mokoconsulting.tech

Add backward-compatible name recognition so all three bot name variants
(mokogitea-actions, gitea-actions, github-actions) with optional [bot]
suffix resolve to the same system user.

Add WhitelistActionsUser, MergeWhitelistActionsUser, and
ForcePushAllowlistActionsUser toggles to branch protection rules,
allowing CI/CD workflows to push to protected branches when explicitly
enabled. Previously the actions bot (virtual user ID -2) could never be
added to whitelist because updateUserWhitelist() only validates real
database users.

Closes #233

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-30 10:37:43 -05:00
jmiller 33b2ae2d4d chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 15:04:24 +00:00
jmiller 69f1a77459 chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-30 15:01:54 +00:00
jmiller 0cb4ece382 chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-30 14:59:52 +00:00
jmiller 8af880073f chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 14:56:17 +00:00
jmiller 8ee7e9fcde chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-30 14:54:25 +00:00
jmiller 7bd66ae74c chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 05:53:24 +00:00
jmiller d10c6ece9b chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-30 05:51:27 +00:00
jmiller aeda83c664 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 03:41:15 +00:00
jmiller 0915b05b0f chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 01:16:46 +00:00
jmiller e0698e73bc chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 01:15:07 +00:00
jmiller 6f38f89765 chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-29 10:32:14 +00:00
jmiller 25257b9e31 chore: add .mokogitea/branch-protection.yml from moko-platform [skip ci] 2026-05-29 10:30:21 +00:00
jmiller a5bdc89faa chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-29 10:27:49 +00:00
jmiller 0ecba968a0 chore: add .mokogitea/workflows/branch-cleanup.yml from moko-platform [skip ci] 2026-05-29 10:26:11 +00:00
jmiller bed7adcf1c chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-29 10:24:44 +00:00
jmiller df59b5f6d5 chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-29 10:23:14 +00:00
jmiller 5786f0dfc4 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-28 20:53:51 +00:00
jmiller 1b0c86847d chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:51:14 +00:00
jmiller 2de87d8ff4 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:48:43 +00:00
jmiller 789d3c9aa8 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:46:21 +00:00
jmiller b241acf650 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:43:45 +00:00
jmiller 173dfd0f26 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:38:05 +00:00
jmiller 700cc77d0b chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:28:27 +00:00
jmiller c268970505 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-28 20:09:19 +00:00
jmiller 1f09979c19 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:05:59 +00:00
jmiller 7786dee9d4 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:02:47 +00:00
Moko Consulting 7959864835 fix(workflows): rename remaining old secrets in repo-specific workflows [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-28 14:47:27 -05:00
Moko Consulting 20fef17dac fix(workflows): GITHUB_TOKEN→GH_MIRROR_TOKEN (reserved name) [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-28 14:36:39 -05:00
Moko Consulting 4630327b02 chore(workflows): sync universal workflows, rename secrets [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
2026-05-28 14:31:00 -05:00
Jonathan Miller 1ad277cd73 Merge branch 'dev' 2026-05-26 21:11:54 -05:00
Jonathan Miller 4624385501 feat(ci): update version branch on every stable release
Universal: Auto Version Bump / Version Bump (push) Successful in 6s
Add Step 12 to auto-release pipeline that recreates the version branch
from main after each stable release. Also mirrors the version branch
to GitHub alongside main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 21:11:32 -05:00
Jonathan Miller e084c7f4b4 Merge branch 'dev' 2026-05-26 21:07:38 -05:00
Jonathan Miller 9721728b45 Merge remote-tracking branch 'origin/dev' into dev
Universal: Auto Version Bump / Version Bump (push) Successful in 6s
2026-05-26 21:07:04 -05:00
jmiller 38ed8eaeea Merge pull request #2 from mokoconsulting-tech/feat/appname-branding
feat(branding): replace hardcoded Gitea/MokoGitea with APP_NAME setting
2026-05-26 20:37:40 -05:00
Jonathan Miller 1608b5c4b9 feat(branding): replace hardcoded Gitea/MokoGitea with APP_NAME setting
Add runtime ${APP_NAME} placeholder substitution in locale strings so
all user-facing text reflects the configured APP_NAME from app.ini.
Replace 52 hardcoded locale strings, template literals, HTTP auth
realm headers, and Swagger API titles/descriptions with the
configurable value.

Closes #1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 20:19:20 -05:00
jmiller eb15990510 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:51:10 +00:00
jmiller 6654d7605d chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:51:04 +00:00
jmiller 411ba858f5 chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:49:59 +00:00
jmiller a7e39fa992 chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:49:53 +00:00
jmiller bd899bcbb1 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:48:46 +00:00
jmiller 7c014dc4da chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:48:40 +00:00
jmiller d0ca5eff28 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:37:09 +00:00
jmiller 4c4d2ac956 Merge pull request 'rc(v05.06.00): security backports, actions deadlock fix, dep bumps' (#228) from rc/05.06.00 into main
Universal: Auto Version Bump / Patch Bump (push) Successful in 6s
rc(v05.06.00): security backports, actions deadlock fix, dep bumps (#228)
2026-05-26 22:37:06 +00:00
jmiller 47ddd6a277 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:35:53 +00:00
jmiller e946d49bf3 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:35:47 +00:00
Jonathan Miller c3eb57f124 Merge remote-tracking branch 'origin/main' into rc/05.06.00
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 22s
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 1m0s
# Conflicts:
#	.mokogitea/workflows/update-server.yml
2026-05-26 17:35:19 -05:00
jmiller c0662ab118 chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:25:31 +00:00
jmiller fce8389296 chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:25:24 +00:00
jmiller eeaf9f036b chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:24:14 +00:00
jmiller 9957fe56ca chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:24:08 +00:00
jmiller dcc4a49cdb chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:13:35 +00:00
jmiller f15a0ed7e4 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:13:29 +00:00
jmiller 0e0ce94353 chore(ci): add auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:12:24 +00:00
jmiller 455f12e21b chore(ci): add auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:12:18 +00:00
jmiller 360d0b1b1f Merge pull request 'fix(security): backport upstream v1.26.2 security fixes' (#226) from fix/225-security-backports into dev
fix(security): backport upstream v1.26.2 security fixes (#226)
2026-05-26 22:05:08 +00:00
jmiller e8ce4ae60b Merge pull request 'fix(actions): retry workflow insertion on database deadlock' (#221) from fix/220-actions-deadlock-retry into dev
fix(actions): retry workflow insertion on database deadlock (#221)
2026-05-26 22:04:54 +00:00
Jonathan Miller 775766bc64 chore(deps): bump go-git/go-git/v5 to 5.19.0 (security)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Failing after 20s
Addresses security fixes in the go-git library. Upstream backport of
go-gitea/gitea#37608.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 16:49:33 -05:00
Giteabot cc61032697 fix(git): Fix smart http request scope bug (#37583) (#37605)
Backport #37583 by @lunny

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: silverwind <me@silverwind.io>
2026-05-26 16:39:17 -05:00
Nicolas 6d9f0d9727 Fix basic auth bug (#37503)
Backport for #37486
2026-05-26 16:37:50 -05:00
Giteabot 00d862f737 fix: make clone URL respect public URL detection setting (#37615) (#37617)
Backport #37615 by @wxiaoguang

Fix #37614

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2026-05-26 16:28:21 -05:00
Giteabot 233144e33e fix(auth): set User-Agent on avatar fetch and sync avatar on link-account register (#37564) (#37588) (#37726)
Backport #37588 by @pandareen

## Summary

Fixes
[go-gitea/gitea#37564](https://github.com/go-gitea/gitea/issues/37564):
when an OIDC provider returns a `picture` claim, Gitea is supposed to
download that image as the user's avatar (if `[oauth2_client]
UPDATE_AVATAR = true`). Two latent bugs prevented this from working
consistently:

1. **Default Go User-Agent rejected by some image hosts.**
`oauth2UpdateAvatarIfNeed` used `http.Get`, which sends `User-Agent:
Go-http-client/1.1`. Hosts like `upload.wikimedia.org` reject that UA
with `403`, and every error path silently returned, so the user was left
with an identicon and **no log line** to diagnose the issue.
2. **Link-account *register* path skipped avatar sync.** First-time OIDC
sign-ins where auto-registration is disabled (or required a
username/password retype) go through `LinkAccountPostRegister`, which
created the user but never called `oauth2SignInSync`. So the avatar /
full name / SSH keys from the IdP were dropped on the floor for those
users, even though the existing-account-link path (`oauth2LinkAccount`)
and the auto-register path (`handleOAuth2SignIn`) both already did the
sync.

## Changes

- `routers/web/auth/oauth.go` — `oauth2UpdateAvatarIfNeed` now uses
`http.NewRequest` + `http.DefaultClient.Do`, sets `User-Agent: Gitea
<version>`, and logs every failure path at `Warn` (invalid URL, fetch
error, non-200, body read error, oversize body, upload error). No silent
failures.
- `routers/web/auth/linkaccount.go` — `LinkAccountPostRegister` now
calls `oauth2SignInSync` after a successful user creation, mirroring the
auto-register and link-existing-account flows.
- `tests/integration/oauth_avatar_test.go` — new
`TestOAuth2AvatarFromPicture` integration test with five sub-cases:
- `AutoRegister_FetchesAvatarFromPictureWithGiteaUA` — happy path,
asserts `use_custom_avatar=true`, an avatar hash is set, exactly one
HTTP request was made, and the request carried a `Gitea ` UA. The mock
server enforces the UA prefix to mirror real-world hosts that reject
Go's default UA.
- `AutoRegister_NonOK_DoesNotUpdateAvatar` — server returns 403; user's
avatar must remain unset.
- `AutoRegister_EmptyPicture_NoFetch` — empty `picture` claim must not
trigger any HTTP request.
- `AutoRegister_UpdateAvatarFalse_NoFetch` — `UPDATE_AVATAR=false` must
not trigger any HTTP request.
- `LinkAccountRegister_FetchesAvatarFromPicture` — guards the
`linkaccount.go` fix; without the new `oauth2SignInSync` call this
assertion fails.

## Test plan

- [x] `go test -tags 'sqlite sqlite_unlock_notify' -run
'^TestOAuth2AvatarFromPicture$' ./tests/integration/ -v` — 5/5 sub-tests
pass.
- [x] Manual: log in as a Keycloak user with `picture` claim pointing at
`https://avatars.githubusercontent.com/u/9919?v=4` — Gitea avatar is
replaced with the GitHub picture.
- [x] Manual: same flow with `https://upload.wikimedia.org/...` —
request now succeeds (or returns a clearly logged `Warn` line if
rate-limited with `429`); previously it silently 403'd.
- [x] Manual: `UPDATE_AVATAR=false` — user keeps the identicon, no
outbound request in container logs.
- [ ] Reviewer: please double-check that no other call sites of
`oauth2UpdateAvatarIfNeed` rely on the old `http.Get` behaviour.

## Related

- Upstream issue: go-gitea/gitea#37564
--------------------------------------------


AI Editor was used in this PR

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: pandareen <7270563+pandareen@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Nicolas <bircni@icloud.com>
2026-05-26 16:28:21 -05:00
Zettat123 38beba655b fix(actions): wrong assumption that run id always >= job id (#37737) (#37742)
Backport #37737

Fix #37734

Follow up #37008

The `jobNum >= runNum` check is useless. Removed it to support `job_id <
run_id`
2026-05-26 16:28:20 -05:00
Jonathan Miller dd6fc4b69c fix(actions): retry workflow insertion on database deadlock
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || 'development' }}) (pull_request) Failing after 21s
When multiple workflows are triggered by a single event (e.g. a
pull_request with several matching workflow files), each InsertRun
transaction acquires an X-lock on the repository row via
UpdateRepoRunsNumbers and an index lock on action_run. Two concurrent
transactions can deadlock when each holds one lock and waits for the
other. InnoDB kills the lighter transaction, but handleWorkflows only
logged the error and silently dropped the workflow run — making it
appear as though pull_request events were never fired.

This was the root cause of API-created PRs appearing to not trigger
Actions workflows: the notification pipeline was correct, but the DB
insert was lost to an unretried deadlock.

The fix wraps PrepareRunAndInsert in a retry loop (up to 3 attempts
with exponential backoff) that detects deadlock errors across MySQL,
PostgreSQL, and SQLite. On deadlock, the rolled-back run fields are
reset before the next attempt.

Also adds db.IsErrDeadlock() for cross-engine deadlock detection and
unit tests for the same.

Closes #220

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 15:16:30 -05:00
jmiller 3b79d57d45 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 20:12:56 +00:00
jmiller 871cb495b1 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-26 20:11:02 +00:00
jmiller d66ca8db83 chore(ci): add update-server.yml universal workflow [skip ci] 2026-05-26 19:56:49 +00:00
jmiller 01f6722ccc chore(ci): add update-server.yml universal workflow [skip ci] 2026-05-26 19:56:42 +00:00
jmiller 7019f08f74 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 19:35:56 +00:00
jmiller aa6c3fc4ed chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 19:35:48 +00:00
jmiller b577f8f4f4 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 19:35:42 +00:00
jmiller 5ffe68499d chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 19:35:33 +00:00
jmiller 65456962b4 chore: add .mokogitea/manifest.xml
Authored-by: Moko Consulting
2026-05-26 19:19:06 +00:00
jmiller 020b160403 chore: add .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 19:04:20 +00:00
jmiller c633024a9c Merge pull request 'rc(v05.05.00): org 2FA, wiki slugs, http render fix' (#219) from rc/05.05.00 into main 2026-05-26 18:50:40 +00:00
jmiller 8ffdbff72a Merge pull request 'fix: preserve + and . in wiki slugs' (#218) from fix/wiki-slug-polish into dev
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 21s
2026-05-26 18:48:06 +00:00
Jonathan Miller d609b8db8c fix: preserve + and . in wiki slugs, clean stray plus signs
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 1s
Allow C++, .NET, version numbers (2.0.1) in wiki filenames.
Clean up isolated plus signs that appear between hyphens.

Examples:
- C++ vs C# -> C++-vs-C.md
- .NET Guide -> .NET-Guide.md
- version 2.0.1 -> version-2.0.1-release.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 13:47:59 -05:00
jmiller bf35e5510d Merge pull request 'fix: unused import in require2fa.go' (#216) from fix/require2fa-import into dev 2026-05-26 18:39:22 +00:00
Jonathan Miller 0cc7297f23 fix: remove unused net/http import in require2fa.go
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 13:39:15 -05:00
jmiller 9dc85cfc2d Merge pull request 'feat: smart wiki filenames' (#215) from fix/wiki-smart-filenames into dev 2026-05-26 18:28:14 +00:00
jmiller 6bc0cb5bc8 Merge pull request 'feat: org-level 2FA requirement (#208)' (#214) from feat/208-org-2fa-requirement into dev 2026-05-26 18:28:05 +00:00
Jonathan Miller 1032ae4268 feat: organization-level 2FA requirement for members (#208)
Branch Policy Check / Verify merge target (pull_request) Successful in 1s
PR RC Release / Build RC Release (pull_request) Successful in 2s
Adds a Require2FA toggle to organization settings. When enabled,
org members without 2FA are redirected to the security settings
page with a warning flash message.

Changes:
- New Require2FA field on User model (migration v333)
- Org settings UI checkbox with shield-lock icon
- Check2FARequirement middleware on member-required org routes
- UpdateOptions extended with Require2FA field

Closes #208

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-26 13:11:15 -05:00
jmiller 1e1441f8bd Merge pull request 'rc(v05.04.00): login notifications, help footer, login logo, checksum fix' (#210) from rc/05.04.00 into main 2026-05-26 17:47:13 +00:00
jmiller 3c55a3baca Merge pull request 'rc: footer help + login logo' (#206) from rc/05.03.08 into main 2026-05-26 16:12:57 +00:00
jmiller b7f9743ade Merge pull request 'rc: fix dashboard icon' (#203) from rc/05.03.06 into main 2026-05-26 04:39:15 +00:00
2368 changed files with 22968 additions and 19229 deletions
+4 -4
View File
@@ -44,7 +44,7 @@ linters:
desc: use os or io instead
- pkg: golang.org/x/exp
desc: it's experimental and unreliable
- pkg: git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/internal
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/internal
desc: do not use the internal package, use AddXxx function instead
- pkg: gopkg.in/ini.v1
desc: do not use the ini package, use gitea's config system instead
@@ -56,9 +56,9 @@ linters:
files:
- '**/models/migrations/**/*.go'
deny:
- pkg: git.mokoconsulting.tech/MokoConsulting/MokoGitea/models$
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/models$
desc: migrations must not depend on the models package
- pkg: git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs
- pkg: code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs
desc: migrations must not depend on modules/structs (API structures change over time)
nolintlint:
allow-unused: false
@@ -179,7 +179,7 @@ formatters:
custom-order: true
sections:
- standard
- prefix(git.mokoconsulting.tech/MokoConsulting/MokoGitea)
- prefix(code.mokoconsulting.tech/MokoConsulting/MokoGitea)
- blank
- default
gofumpt:
+2 -2
View File
@@ -8,10 +8,10 @@ contact_links:
url: https://mokoconsulting.tech/
about: Get help or ask questions through our website
- name: 📚 MokoStandards Documentation
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
url: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
about: View our coding standards and best practices
- name: 🔒 Report a Security Vulnerability
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
url: https://code.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
about: Report security vulnerabilities privately (for critical issues)
- name: 💡 Community Discussions
url: https://github.com/orgs/mokoconsulting-tech/discussions
+1 -1
View File
@@ -37,7 +37,7 @@ If you have ideas about how this could be implemented, share them here:
Add any other context, mockups, or screenshots about the feature request here.
## Relevant Standards
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
Does this relate to any standards in [MokoStandards](https://code.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] Accessibility (WCAG 2.1 AA)
- [ ] Localization (en_US/en_GB)
- [ ] Security best practices
+1 -1
View File
@@ -35,7 +35,7 @@ Use this template only for:
<!-- Describe how this could be addressed -->
## Standards Reference
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
Does this relate to security standards in [MokoStandards](https://code.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] SPDX license identifiers
- [ ] Secret management
- [ ] Dependency security
+251
View File
@@ -0,0 +1,251 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# REPO: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.gitea/workflows/branch-protection.yml
# BRIEF: Apply standardised branch protection rules to all governed repositories
#
# +========================================================================+
# | BRANCH PROTECTION SETUP |
# +========================================================================+
# | |
# | Applies protection rules for: main, dev, rc, beta, alpha |
# | |
# | main — Require PR, block rejected reviews, no force push |
# | dev — Allow push, no force push, no delete |
# | rc — Allow push, no force push, no delete |
# | beta — Allow push, no force push, no delete |
# | alpha — Allow push, no force push, no delete |
# | |
# | jmiller has override authority on all branches. |
# | |
# +========================================================================+
name: Branch Protection Setup
on:
schedule:
- cron: '0 2 * * 1' # Weekly Monday 02:00 UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Preview mode (no changes)'
required: false
type: boolean
default: false
repos:
description: 'Comma-separated repo names (empty = all governed repos)'
required: false
type: string
default: ''
env:
GITEA_URL: https://code.mokoconsulting.tech
GITEA_ORG: MokoConsulting
permissions:
contents: read
jobs:
protect:
name: Apply Branch Protection Rules
runs-on: ubuntu-latest
steps:
- name: Determine target repos
id: repos
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1"
# Platform/standards/infra repos to exclude
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform MokoTesting"
EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate"
if [ -n "${{ inputs.repos }}" ]; then
# User-specified repos
REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ')
else
# Fetch all org repos
PAGE=1
REPOS=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
REPOS="$REPOS $BATCH"
PAGE=$((PAGE + 1))
done
# Filter out excluded repos
FILTERED=""
for REPO in $REPOS; do
SKIP=false
for EX in $EXCLUDE; do
if [ "$REPO" = "$EX" ]; then
SKIP=true
break
fi
done
if [ "$SKIP" = "false" ]; then
FILTERED="$FILTERED $REPO"
fi
done
REPOS="$FILTERED"
fi
echo "repos=$REPOS" >> "$GITHUB_OUTPUT"
COUNT=$(echo "$REPOS" | wc -w)
echo "📋 Target repos (${COUNT}): $REPOS"
- name: Apply protection rules
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
run: |
API="${GITEA_URL}/api/v1"
REPOS="${{ steps.repos.outputs.repos }}"
SUCCESS=0
FAILED=0
SKIPPED=0
# ── Rule definitions ──────────────────────────────────────
# Only the CI bot (jmiller token) can push directly.
# All human contributors must use PRs.
# Force push disabled on all branches.
RULE_MAIN='{
"rule_name": "main",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"dismiss_stale_approvals": true,
"block_on_rejected_reviews": true,
"block_on_outdated_branch": false,
"priority": 1
}'
RULE_DEV='{
"rule_name": "dev",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 2
}'
RULE_RC='{
"rule_name": "rc",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 3
}'
RULE_BETA='{
"rule_name": "beta",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 4
}'
RULE_ALPHA='{
"rule_name": "alpha",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 5
}'
RULES=("$RULE_MAIN" "$RULE_DEV" "$RULE_RC" "$RULE_BETA" "$RULE_ALPHA")
RULE_NAMES=("main" "dev" "rc" "beta" "alpha")
# ── Apply rules to each repo ──────────────────────────────
for REPO in $REPOS; do
echo ""
echo "═══ ${REPO} ═══"
for i in "${!RULES[@]}"; do
RULE="${RULES[$i]}"
NAME="${RULE_NAMES[$i]}"
if [ "$DRY_RUN" = "true" ]; then
echo " [DRY RUN] Would apply rule: ${NAME}"
SKIPPED=$((SKIPPED + 1))
continue
fi
# Delete existing rule if present (idempotent recreate)
ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g')
curl -sS -o /dev/null -w "" \
-X DELETE \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
# Create rule
RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "$RULE" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
HTTP=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP" = "201" ]; then
echo " ✅ ${NAME}"
SUCCESS=$((SUCCESS + 1))
else
echo " ❌ ${NAME} (HTTP ${HTTP}): $(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)"
FAILED=$((FAILED + 1))
fi
done
done
# ── Summary ───────────────────────────────────────────────
echo ""
echo "════════════════════════════════════════"
echo " ✅ Success: ${SUCCESS}"
echo " ❌ Failed: ${FAILED}"
echo " ⏭️ Skipped: ${SKIPPED}"
echo "════════════════════════════════════════"
if [ "$FAILED" -gt 0 ]; then
echo "::warning::${FAILED} rule(s) failed to apply"
fi
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
<identity>
<name>MokoGitea</name>
<org>MokoConsulting</org>
<description>Moko fork of Gitea — adding project board REST API endpoints and custom enhancements</description>
<version>05.14.00</version>
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
</identity>
<governance>
<platform>go</platform>
<standards-version>05.00.00</standards-version>
<standards-source>https://code.mokoconsulting.tech/MokoConsulting/moko-platform</standards-source>
</governance>
<build>
<language>Go</language>
<package-type>application</package-type>
<entry-point>./</entry-point>
</build>
</moko-platform>
-761
View File
@@ -1,761 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +========================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
# +========================================================================+
# | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
# | |
# | Platform-specific: |
# | joomla: XML manifest, updates.xml, type-prefixed packages |
# | dolibarr: mod*.class.php, update.txt, dev version reset |
# | generic: README-only, no update stream |
# | |
# +========================================================================+
name: "Universal: Build & Release"
on:
push:
branches:
- main
paths:
- 'src/**'
- 'htdocs/**'
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
permissions:
contents: write
jobs:
release:
name: Build & Release Pipeline
runs-on: release
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GA_TOKEN }}
fetch-depth: 0
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
run: |
# Ensure PHP + Composer are available
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/moko-platform-api
cd /tmp/moko-platform-api
composer install --no-dev --no-interaction --quiet
# -- PLATFORM DETECTION ---------------------------------------------------
- name: Detect platform
id: platform
run: |
php /tmp/moko-platform-api/cli/manifest_read.php --path . --github-output
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1 || true)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
- name: "Step 1: Read version"
id: version
run: |
VERSION=$(php /tmp/moko-platform-api/cli/version_read.php --path .)
if [ -z "$VERSION" ]; then
echo "::error::No VERSION in README.md"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
MAJOR=$(echo "$VERSION" | cut -d. -f1)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
- name: "Step 1b: Bump version"
id: bump
if: steps.version.outputs.skip != 'true'
run: |
MOKO_API="/tmp/moko-platform-api/cli"
BUMP=$(php ${MOKO_API}/version_bump.php --path . --minor)
VERSION=$(echo "$BUMP" | grep -oP '\d{2}\.\d{2}\.\d{2}$' || true)
[ -z "$VERSION" ] && VERSION=$(php ${MOKO_API}/version_read.php --path .)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Bumped to: ${VERSION}"
- name: Check if already released
if: steps.version.outputs.skip != 'true'
id: check
run: |
TAG="${{ steps.version.outputs.release_tag }}"
BRANCH="${{ steps.version.outputs.branch }}"
TAG_EXISTS=false
BRANCH_EXISTS=false
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
git ls-remote --heads origin "$BRANCH" 2>/dev/null | grep -q "$BRANCH" && BRANCH_EXISTS=true
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
echo "branch_exists=$BRANCH_EXISTS" >> "$GITHUB_OUTPUT"
# Tag and branch may persist across patch releases — never skip
echo "already_released=false" >> "$GITHUB_OUTPUT"
# -- SANITY CHECKS -------------------------------------------------------
- name: "Sanity: Pre-release validation"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
ERRORS=0
PLATFORM="${{ steps.platform.outputs.platform }}"
MANIFEST="${{ steps.platform.outputs.manifest }}"
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
echo "## Pre-Release Sanity Checks (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# -- Version drift check (must pass before release) --------
README_VER=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
if [ "$README_VER" != "$VERSION" ]; then
echo "- Version drift: README says \`${README_VER}\` but releasing \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "- Version consistent: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
fi
# Check CHANGELOG version matches
CL_VER=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' CHANGELOG.md 2>/dev/null | head -1)
if [ -n "$CL_VER" ] && [ "$CL_VER" != "$VERSION" ]; then
echo "- CHANGELOG drift: \`${CL_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
fi
# Check composer.json version if present
if [ -f "composer.json" ]; then
COMP_VER=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' composer.json 2>/dev/null | head -1)
if [ -n "$COMP_VER" ] && [ "$COMP_VER" != "$VERSION" ]; then
echo "- composer.json drift: \`${COMP_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
fi
fi
# Common checks
if [ ! -f "LICENSE" ]; then
echo "- Missing LICENSE file" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "- LICENSE present" >> $GITHUB_STEP_SUMMARY
fi
if [ ! -d "src" ] && [ ! -d "htdocs" ]; then
echo "- Warning: No src/ or htdocs/ directory" >> $GITHUB_STEP_SUMMARY
else
echo "- Source directory present" >> $GITHUB_STEP_SUMMARY
fi
# -- Platform-specific checks --------
case "$PLATFORM" in
joomla)
if [ -n "$MANIFEST" ]; then
XML_VER=$(sed -n 's/.*<version>\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
if [ -n "$XML_VER" ] && [ "$XML_VER" != "$VERSION" ]; then
echo "- Manifest drift: \`${XML_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "- Manifest version: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
fi
TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" 2>/dev/null)
echo "- Extension type: ${TYPE:-unknown}" >> $GITHUB_STEP_SUMMARY
else
echo "- No Joomla XML manifest (WaaS site)" >> $GITHUB_STEP_SUMMARY
fi ;;
dolibarr)
if [ -n "$MOD_FILE" ]; then
MOD_VER=$(sed -n "s/.*\\\$this->version = '\([^']*\)'.*/\1/p" "$MOD_FILE" 2>/dev/null | head -1)
if [ -n "$MOD_VER" ] && [ "$MOD_VER" != "$VERSION" ]; then
echo "- Module drift: \`${MOD_VER}\` != \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
else
echo "- Module version: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
fi
else
echo "- No mod*.class.php found" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
fi
if [ ! -f "update.txt" ]; then
echo "- Missing update.txt" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS+1))
fi ;;
*) echo "- Generic platform no manifest checks" >> $GITHUB_STEP_SUMMARY ;;
esac
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$ERRORS" -gt 0 ]; then
echo "**${ERRORS} error(s) — release may be incomplete**" >> $GITHUB_STEP_SUMMARY
else
echo "**All sanity checks passed**" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 2: Create or update version/XX.YY archive branch ---------------
# Always runs — every version change on main archives to version/XX.YY
- name: "Step 2: Version archive branch"
if: steps.check.outputs.already_released != 'true'
run: |
BRANCH="${{ steps.version.outputs.branch }}"
IS_MINOR="${{ steps.version.outputs.is_minor }}"
PATCH="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
PATCH_NUM=$(echo "$PATCH" | awk -F. '{print $3}')
# Check if branch exists
if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then
git push origin HEAD:"$BRANCH" --force
echo "Updated archive branch: ${BRANCH} (patch ${PATCH_NUM})" >> $GITHUB_STEP_SUMMARY
else
git checkout -b "$BRANCH" 2>/dev/null || git checkout "$BRANCH"
git push origin "$BRANCH" --force
echo "Created archive branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 3: Set platform version ----------------------------------------
- name: "Step 3: Set platform version"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
php /tmp/moko-platform-api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
# -- STEP 4: Update version badges ----------------------------------------
- name: "Step 4: Update version badges"
if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
- name: "Step 5: Write update stream"
if: >-
steps.version.outputs.skip != 'true' &&
steps.platform.outputs.platform == 'joomla'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
php /tmp/moko-platform-api/cli/updates_xml_build.php \
--path . --version "${VERSION}" --stability stable \
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
--github-output
- name: Commit release changes
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
run: |
if git diff --quiet && git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
# Set push URL with token for branch-protected repos
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git commit -m "chore(release): build ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
git push -u origin HEAD
# -- STEP 6: Create tag ---------------------------------------------------
- name: "Step 6: Create git tag"
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true' &&
steps.version.outputs.is_minor == 'true'
run: |
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
# Only create the major release tag if it doesn't exist yet
if ! git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then
git tag "$RELEASE_TAG"
git push origin "$RELEASE_TAG"
echo "Tag created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
else
echo "Tag ${RELEASE_TAG} already exists" >> $GITHUB_STEP_SUMMARY
fi
echo "Tag: ${TAG}" >> $GITHUB_STEP_SUMMARY
# -- STEP 7: Create or update Gitea Release --------------------------------
- name: "Step 7: Gitea Release"
if: >-
steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
BRANCH="${{ steps.version.outputs.branch }}"
MAJOR="${{ steps.version.outputs.major }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Reuse metadata from Step 5 (single source of truth)
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
EXT_NAME="${{ steps.updates.outputs.ext_name }}"
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
# Fallbacks if Step 5 was skipped
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
[ -z "$EXT_NAME" ] && EXT_NAME="${GITEA_REPO}"
NOTES=$(php /tmp/moko-platform-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
# Build release name: "Pretty Name VERSION (type_element-VERSION)"
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
RELEASE_NAME="${EXT_NAME} ${VERSION} (${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION})"
# Delete existing release if present (overwrite, not append)
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
EXISTING_ID=$(echo "$EXISTING" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
if [ -n "$EXISTING_ID" ]; then
curl -sS -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/${EXISTING_ID}" 2>/dev/null || true
curl -sS -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/tags/${RELEASE_TAG}" 2>/dev/null || true
echo "Deleted previous stable release (id: ${EXISTING_ID})"
fi
# Create fresh release
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/json" \
"${API_BASE}/releases" \
-d "$(python3 -c "import json; print(json.dumps({
'tag_name': '${RELEASE_TAG}',
'name': '${RELEASE_NAME}',
'body': '''## ${VERSION} ($(date +%Y-%m-%d))\n${NOTES}''',
'target_commitish': '${BRANCH}'
}))")"
echo "Release created: ${RELEASE_NAME}" >> $GITHUB_STEP_SUMMARY
# -- STEP 8: Build Joomla install ZIP + SHA-256 checksum ------------------
- name: "Step 8: Build package and update checksum"
if: >-
steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
REPO="${{ github.repository }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# All ZIPs upload to the major release tag (vXX)
RELEASE_JSON=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -z "$RELEASE_ID" ]; then
echo "No release ${RELEASE_TAG} found — skipping ZIP upload"
exit 0
fi
# Find extension element name from manifest
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
[ -z "$MANIFEST" ] && exit 0
# Reuse element from Step 5, with same fallback chain
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(sed -n 's/.*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
# ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip)
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
# -- Build install packages from src/ ----------------------------
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/"; exit 0; }
# ZIP package (type-aware via moko-platform PHP API)
php /tmp/moko-platform-api/cli/joomla_build.php --path . --version "${VERSION}" --output /tmp
# Match the expected ZIP_NAME for upload
BUILT_ZIP=$(ls /tmp/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip 2>/dev/null | head -1 || true)
if [ -n "$BUILT_ZIP" ] && [ "$BUILT_ZIP" != "/tmp/${ZIP_NAME}" ]; then
mv "$BUILT_ZIP" "/tmp/${ZIP_NAME}"
fi
# tar.gz package (flat source archive)
tar -czf "/tmp/${TAR_NAME}" -C "$SOURCE_DIR" --exclude='.ftpignore' --exclude='sftp-config*' --exclude='*.ppk' --exclude='*.pem' --exclude='*.key' --exclude='.env*' .
ZIP_SIZE=$(stat -c%s "/tmp/${ZIP_NAME}" 2>/dev/null || stat -f%z "/tmp/${ZIP_NAME}" 2>/dev/null || echo "unknown")
TAR_SIZE=$(stat -c%s "/tmp/${TAR_NAME}" 2>/dev/null || stat -f%z "/tmp/${TAR_NAME}" 2>/dev/null || echo "unknown")
# -- Calculate SHA-256 for both ----------------------------------
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
# -- Delete existing assets with same name before uploading ------
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
for ASSET_NAME in "$ZIP_NAME" "$TAR_NAME"; do
ASSET_ID=$(echo "$ASSETS" | python3 -c "
import sys,json
assets = json.load(sys.stdin)
for a in assets:
if a['name'] == '${ASSET_NAME}':
print(a['id']); break
" 2>/dev/null || true)
if [ -n "$ASSET_ID" ]; then
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
fi
done
# -- Upload both to release tag ----------------------------------
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"/tmp/${ZIP_NAME}" \
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" > /dev/null 2>&1 || true
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"/tmp/${TAR_NAME}" \
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${TAR_NAME}" > /dev/null 2>&1 || true
# -- Update updates.xml with both download formats ---------------
if [ -f "updates.xml" ]; then
ZIP_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}"
TAR_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${TAR_NAME}"
# Use Python to update only the stable entry's downloads + sha256
export PY_ZIP_URL="$ZIP_URL" PY_TAR_URL="$TAR_URL" PY_SHA="$SHA256_ZIP"
python3 << 'PYEOF'
import re, os
with open("updates.xml") as f:
content = f.read()
zip_url = os.environ["PY_ZIP_URL"]
tar_url = os.environ["PY_TAR_URL"]
sha = os.environ["PY_SHA"]
# Find the stable update block and replace its downloads + sha256
def replace_stable(m):
block = m.group(0)
# Replace downloads block
new_downloads = (
" <downloads>\n"
f" <downloadurl type=\"full\" format=\"zip\">{zip_url}</downloadurl>\n"
" </downloads>"
)
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
# Add or replace sha256
if '<sha256>' in block:
block = re.sub(r' <sha256>.*?</sha256>', f' <sha256>{sha}</sha256>', block)
else:
block = block.replace('</downloads>', f'</downloads>\n <sha256>{sha}</sha256>')
return block
content = re.sub(
r' <update>.*?<tag>stable</tag>.*?</update>',
replace_stable,
content,
flags=re.DOTALL
)
with open("updates.xml", "w") as f:
f.write(content)
PYEOF
CURRENT_BRANCH="${{ github.ref_name }}"
git add updates.xml
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
git push || true
# Sync updates.xml to main via direct API (always runs — may be on version/XX branch)
GA_TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
"${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty')
if [ -n "$FILE_SHA" ]; then
CONTENT=$(base64 -w0 updates.xml)
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/contents/updates.xml" \
-d "$(jq -n \
--arg content "$CONTENT" \
--arg sha "$FILE_SHA" \
--arg msg "chore: sync updates.xml ${VERSION} [skip ci]" \
--arg branch "main" \
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
)" > /dev/null 2>&1 \
&& echo "updates.xml synced to main via API" \
|| echo "WARNING: failed to sync updates.xml to main"
else
echo "WARNING: could not get updates.xml SHA from main"
fi
fi
echo "### Packages" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Package | Size | SHA-256 |" >> $GITHUB_STEP_SUMMARY
echo "|---------|------|---------|" >> $GITHUB_STEP_SUMMARY
echo "| \`${ZIP_NAME}\` | ${ZIP_SIZE} | \`${SHA256_ZIP}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`${TAR_NAME}\` | ${TAR_SIZE} | \`${SHA256_TAR}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
# -- STEP 8b: Update release description with changelog + SHA ----------------
- name: "Step 8b: Update release body with changelog and SHA"
if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
# Build TYPE_PREFIX to match Step 8's ZIP naming
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
# Get SHA from the built files
SHA256_ZIP=""
[ -f "/tmp/${ZIP_NAME}" ] && SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
SHA256_TAR=""
[ -f "/tmp/${TAR_NAME}" ] && SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
# Extract latest changelog entry (strip the ## header to avoid duplicate)
CHANGELOG=""
if [ -f "CHANGELOG.md" ]; then
CHANGELOG=$(sed -n "/^## \[*${VERSION}/,/^## \[*[0-9]/p" CHANGELOG.md | sed '$d' | sed '1d')
[ -z "$CHANGELOG" ] && CHANGELOG=$(sed -n '/^## /,/^## /p' CHANGELOG.md | sed '$d' | sed '1d' | head -30)
fi
# Build release body (single header, no duplicate from changelog)
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n"
if [ -n "$CHANGELOG" ]; then
BODY="${BODY}${CHANGELOG}\n\n"
fi
BODY="${BODY}---\n\n### Checksums\n\n"
BODY="${BODY}| File | SHA-256 |\n|------|--------|\n"
[ -n "$SHA256_ZIP" ] && BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n"
[ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n"
# Get release ID and update body
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
python3 -c "
import json, urllib.request
body = '''$(printf '%b' "$BODY")'''
data = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=data,
headers={'Authorization': 'token ${{ secrets.GA_TOKEN }}', 'Content-Type': 'application/json'},
method='PATCH'
)
urllib.request.urlopen(req)
" 2>/dev/null && echo "Release body updated with changelog + SHA" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- name: "Step 9: Mirror release to GitHub"
if: >-
steps.version.outputs.skip != 'true' &&
steps.version.outputs.stability == 'stable' &&
secrets.GH_TOKEN != ''
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
MAJOR="${{ steps.version.outputs.major }}"
BRANCH="${{ steps.version.outputs.branch }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
NOTES=$(php /tmp/moko-platform-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null || true)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
echo "$NOTES" > /tmp/release_notes.md
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".tag_name // empty" || true)
if [ -z "$EXISTING" ]; then
gh release create "$RELEASE_TAG" \
--repo "$GH_REPO" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md \
--target "$BRANCH" || true
else
gh release edit "$RELEASE_TAG" \
--repo "$GH_REPO" \
--title "v${MAJOR} (latest: ${VERSION})" || true
fi
# Upload assets to GitHub mirror
for PKG in /tmp/${EXT_ELEMENT:-pkg}-${VERSION}.*; do
if [ -f "$PKG" ]; then
_RELID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/tags/$RELEASE_TAG" 2>/dev/null | jq -r ".id // empty")
[ -n "$_RELID" ] && curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" -H "Content-Type: application/octet-stream" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/releases/${_RELID}/assets?name=$(basename $PKG)" --data-binary "@$PKG" > /dev/null 2>&1 || true
fi
done
echo "GitHub mirror updated: ${GH_REPO} ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
- name: "Step 10: Push main to GitHub mirror"
if: >-
steps.version.outputs.skip != 'true' &&
secrets.GH_TOKEN != ''
continue-on-error: true
run: |
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
git remote add github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
git remote set-url github "https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
git fetch origin main --depth=1
git push github origin/main:refs/heads/main --force 2>/dev/null \
&& echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed"
# -- Clean up lesser pre-releases (cascade) ---------------------------------
# stable → deletes all | rc → beta,alpha,dev | beta → alpha,dev | alpha → dev
- name: "Delete lesser pre-release channels"
continue-on-error: true
run: |
php /tmp/moko-platform-api/cli/release_cascade.php \
--stability stable \
--token "${{ secrets.GA_TOKEN }}" \
--org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
--gitea-url "${GITEA_URL}" 2>/dev/null || true
- name: "Step 11: Delete and recreate dev branch from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
# -- Dolibarr post-release: Reset dev version -----------------------------
- name: "Dolibarr: Reset dev version"
if: >-
steps.version.outputs.skip != 'true' &&
steps.platform.outputs.platform == 'dolibarr' &&
steps.platform.outputs.mod_file != ''
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
ENCODED_PATH=$(echo "$MOD_FILE" | sed 's|^\./||' | python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip()))")
FILE_RESP=$(curl -sf -H "Authorization: token ${TOKEN}" "${API_BASE}/contents/${ENCODED_PATH}?ref=dev" 2>/dev/null || true)
FILE_SHA=$(echo "$FILE_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
FILE_CONTENT=$(echo "$FILE_RESP" | python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin).get('content','')).decode())" 2>/dev/null || true)
if [ -n "$FILE_SHA" ] && [ -n "$FILE_CONTENT" ]; then
UPDATED=$(echo "$FILE_CONTENT" | sed "s/\$this->version = '[^']*'/\$this->version = 'development'/")
ENCODED=$(echo "$UPDATED" | base64 -w0)
curl -sf -X PUT -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/contents/${ENCODED_PATH}" \
-d "$(jq -n --arg content \"$ENCODED\" --arg sha \"$FILE_SHA\" --arg msg \"chore(version): reset dev version [skip ci]\" --arg branch \"dev\" '{content:$content,sha:$sha,message:$msg,branch:$branch}')" > /dev/null 2>&1 || true
fi
# -- Summary --------------------------------------------------------------
- name: Pipeline Summary
if: always()
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi
+48
View File
@@ -0,0 +1,48 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://code.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
name: "Branch Cleanup"
on:
pull_request:
types: [closed]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
cleanup:
name: Delete merged branch
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.head.ref != 'dev' &&
github.event.pull_request.head.ref != 'main'
steps:
- name: Delete source branch
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://code.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
elif [ "$STATUS" = "404" ]; then
echo "Branch already deleted: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete branch ${BRANCH} (HTTP ${STATUS})"
fi
+34 -8
View File
@@ -5,6 +5,9 @@
name: Deploy MokoGitea
on:
push:
branches:
- main
workflow_dispatch:
inputs:
version:
@@ -25,9 +28,9 @@ concurrency:
cancel-in-progress: false
env:
REGISTRY: git.mokoconsulting.tech
REGISTRY: code.mokoconsulting.tech
IMAGE: mokoconsulting/mokogitea
DEPLOY_HOST: git.mokoconsulting.tech
DEPLOY_HOST: code.mokoconsulting.tech
DEPLOY_PORT: 2918
DEPLOY_USER: mokoconsulting
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
@@ -36,11 +39,23 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source (for version detection)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine settings
id: config
run: |
VERSION="${{ github.event.inputs.version }}"
ENV="${{ github.event.inputs.environment }}"
# On push to main, auto-deploy to production with git-derived version.
# On workflow_dispatch, use the provided inputs.
if [ "${{ github.event_name }}" = "push" ]; then
VERSION=$(git describe --tags --always 2>/dev/null || echo "dev-$(git rev-parse --short HEAD)")
ENV="production"
else
VERSION="${{ github.event.inputs.version }}"
ENV="${{ github.event.inputs.environment }}"
fi
if [ "$ENV" = "production" ]; then
echo "compose_dir=/opt/gitea" >> $GITHUB_OUTPUT
@@ -48,7 +63,7 @@ jobs:
echo "source_dir=/opt/gitea/source" >> $GITHUB_OUTPUT
echo "branch=main" >> $GITHUB_OUTPUT
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
echo "instance_url=https://git.mokoconsulting.tech" >> $GITHUB_OUTPUT
echo "instance_url=https://code.mokoconsulting.tech" >> $GITHUB_OUTPUT
else
echo "compose_dir=/opt/gitea-dev" >> $GITHUB_OUTPUT
echo "container=mokogitea-dev" >> $GITHUB_OUTPUT
@@ -88,11 +103,22 @@ jobs:
$SSH_CMD "echo 'SSH connected'"
# Pre-deploy cleanup: free disk and memory for the build
$SSH_CMD "
echo 'Cleaning Docker build cache and unused images...'
docker builder prune -af 2>/dev/null || true
docker image prune -af 2>/dev/null || true
echo 'Clearing swap...'
sudo swapoff -a && sudo swapon -a 2>/dev/null || true
echo 'Cleanup complete'
free -m | head -3
"
# Pull latest source
$SSH_CMD "
set -e
if [ ! -d ${SOURCE_DIR}/.git ]; then
git clone -b ${BRANCH} https://git.mokoconsulting.tech/MokoConsulting/MokoGitea.git ${SOURCE_DIR}
git clone -b ${BRANCH} https://code.mokoconsulting.tech/MokoConsulting/MokoGitea.git ${SOURCE_DIR}
fi
cd ${SOURCE_DIR}
git fetch origin ${BRANCH}
@@ -143,10 +169,10 @@ jobs:
- name: Update updates.xml
if: success()
env:
GITEA_TOKEN: ${{ secrets.GA_TOKEN }}
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
TAG: ${{ steps.config.outputs.tag }}
INSTANCE_URL: ${{ steps.config.outputs.instance_url }}
DEPLOY_ENV: ${{ github.event.inputs.environment }}
DEPLOY_ENV: ${{ github.event.inputs.environment || 'production' }}
run: |
# Only update updates.xml for production stable releases
if [ "$DEPLOY_ENV" != "production" ]; then
+3 -3
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# VERSION: 01.00.00
# VERSION: 05.14.00
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://code.mokoconsulting.tech' }}
jobs:
create-branch:
@@ -28,7 +28,7 @@ jobs:
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.GA_TOKEN }}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
+90 -90
View File
@@ -1,90 +1,90 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Enforces branch merge policy:
# feature/* → dev only
# fix/* → dev only
# hotfix/* → dev or main (emergency)
# dev → main only
# alpha/* → dev only
# beta/* → dev only
# rc/* → main only
name: Branch Policy Check
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
check-target:
name: Verify merge target
runs-on: ubuntu-latest
steps:
- name: Check branch policy
run: |
HEAD="${{ github.head_ref }}"
BASE="${{ github.base_ref }}"
echo "PR: ${HEAD} → ${BASE}"
ALLOWED=true
REASON=""
case "$HEAD" in
feature/*|feat/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Feature branches must target 'dev', not '${BASE}'"
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'"
fi
;;
hotfix/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
fi
;;
alpha/*|beta/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Pre-release branches must target 'dev', not '${BASE}'"
fi
;;
rc/*)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Release candidate branches must target 'main', not '${BASE}'"
fi
;;
dev)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Dev branch can only merge into 'main', not '${BASE}'"
fi
;;
esac
if [ "$ALLOWED" = false ]; then
echo "::error::${REASON}"
echo ""
echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "${REASON}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Enforces branch merge policy:
# feature/* → dev only
# fix/* → dev only
# hotfix/* → dev or main (emergency)
# dev → main only
# alpha/* → dev only
# beta/* → dev only
# rc/* → main only
name: Branch Policy Check
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
check-target:
name: Verify merge target
runs-on: ubuntu-latest
steps:
- name: Check branch policy
run: |
HEAD="${{ github.head_ref }}"
BASE="${{ github.base_ref }}"
echo "PR: ${HEAD} → ${BASE}"
ALLOWED=true
REASON=""
case "$HEAD" in
feature/*|feat/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Feature branches must target 'dev', not '${BASE}'"
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'"
fi
;;
hotfix/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
fi
;;
alpha/*|beta/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Pre-release branches must target 'dev', not '${BASE}'"
fi
;;
rc/*)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Release candidate branches must target 'main', not '${BASE}'"
fi
;;
dev)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Dev branch can only merge into 'main', not '${BASE}'"
fi
;;
esac
if [ "$ALLOWED" = false ]; then
echo "::error::${REASON}"
echo ""
echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "${REASON}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
+277
View File
@@ -0,0 +1,277 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/pr-check.yml.template
# VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge
name: "Universal: PR Check"
on:
pull_request:
types: [opened, synchronize, reopened, edited]
permissions:
contents: read
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# ── Branch Policy ──────────────────────────────────────────────────────
branch-policy:
name: Branch Policy
runs-on: ubuntu-latest
steps:
- name: Check branch merge target
run: |
HEAD="${{ github.head_ref }}"
BASE="${{ github.base_ref }}"
echo "PR: ${HEAD} → ${BASE}"
ALLOWED=true
REASON=""
case "$HEAD" in
feature/*|feat/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Feature branches must target 'dev', not '${BASE}'"
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'"
fi
;;
patch/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
ALLOWED=false
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
fi
;;
hotfix/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
fi
;;
rc)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="RC branch can only merge into 'main', not '${BASE}'"
fi
;;
dev)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Dev branch can only merge into 'main', not '${BASE}'"
fi
;;
esac
if [ "$ALLOWED" = false ]; then
echo "::error::${REASON}"
echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "${REASON}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` → \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` → \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` → \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` → \`main\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
# ── Code Validation ────────────────────────────────────────────────────
validate:
name: Validate PR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check for merge conflict markers
run: |
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
if [ -n "$CONFLICTS" ]; then
echo "::error::Merge conflict markers found in source files"
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "No conflict markers found"
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
- name: Setup PHP
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
fi
- name: PHP syntax check
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
run: |
ERRORS=0
while IFS= read -r -d '' file; do
if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -print0)
echo "PHP lint: ${ERRORS} error(s)"
[ "$ERRORS" -eq 0 ] || { echo "::error::PHP syntax errors found"; exit 1; }
- name: Validate platform manifest
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
case "$PLATFORM" in
joomla)
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla manifest found (WaaS site)"
exit 0
fi
echo "Manifest: ${MANIFEST}"
if command -v php &> /dev/null; then
php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$MANIFEST'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::Manifest XML is malformed"; exit 1; }
fi
for ELEMENT in name version description; do
grep -q "<${ELEMENT}>" "$MANIFEST" || { echo "::error::Missing <${ELEMENT}> in manifest"; exit 1; }
done
echo "Joomla manifest valid"
;;
dolibarr)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
if [ -z "$MOD_FILE" ]; then
echo "::error::No mod*.class.php found"
exit 1
fi
echo "Dolibarr module: ${MOD_FILE}"
;;
*)
echo "Generic platform — no manifest validation"
;;
esac
- name: Check update stream format
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
case "$PLATFORM" in
joomla)
if [ -f "updates.xml" ]; then
if command -v php &> /dev/null; then
php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('updates.xml'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::updates.xml is malformed"; exit 1; }
fi
echo "updates.xml valid"
fi
;;
dolibarr)
[ -f "update.txt" ] && echo "update.txt present" || echo "::warning::No update.txt"
;;
esac
- name: Check changelog has unreleased entry
run: |
if [ ! -f "CHANGELOG.md" ]; then
echo "::warning::No CHANGELOG.md found"
exit 0
fi
# Check for content under [Unreleased] section
if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then
echo "::error::CHANGELOG.md missing [Unreleased] section"
exit 1
fi
# Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased
UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true)
if [ "$UNRELEASED_CONTENT" -eq 0 ]; then
echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes."
echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY
echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY
echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]"
- name: Verify package source
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
if [ ! -d "$SOURCE_DIR" ]; then
echo "::warning::No src/ or htdocs/ directory"
exit 0
fi
FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l)
echo "Source: ${FILE_COUNT} files"
[ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; }
# ── Pre-Release RC Build ─────────────────────────────────────────────────
pre-release:
name: Build RC Package
runs-on: ubuntu-latest
needs: [branch-policy, validate]
steps:
- name: Trigger RC pre-release
env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
# ── Issue Reporter ──────────────────────────────────────────────────────
report-issues:
name: Report Issues
runs-on: ubuntu-latest
needs: [branch-policy, validate]
if: >-
always() &&
needs.validate.result == 'failure'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issue for PR validation failure"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
./automation/ci-issue-reporter.sh \
--gate "PR Validation" \
--workflow "PR Check" \
--severity error \
--details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
+3 -3
View File
@@ -10,7 +10,7 @@ on:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
REGISTRY: git.mokoconsulting.tech
REGISTRY: code.mokoconsulting.tech
IMAGE: mokoconsulting/mokogitea
permissions:
@@ -108,7 +108,7 @@ jobs:
- name: Create RC release
if: steps.guard.outputs.skip != 'true'
env:
GITEA_TOKEN: ${{ secrets.GA_TOKEN }}
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
RC_TAG: ${{ steps.version.outputs.tag }}
RC_VERSION: ${{ steps.version.outputs.version }}
PR_TITLE: ${{ github.event.pull_request.title }}
@@ -155,7 +155,7 @@ jobs:
- name: Commit updates.xml
if: steps.guard.outputs.skip != 'true'
env:
GITEA_TOKEN: ${{ secrets.GA_TOKEN }}
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
PR_NUM: ${{ github.event.pull_request.number }}
run: |
-375
View File
@@ -1,375 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
name: "Universal: Pre-Release"
on:
workflow_dispatch:
inputs:
stability:
description: 'Pre-release channel'
required: true
type: choice
options:
- development
- alpha
- beta
- release-candidate
permissions:
contents: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
jobs:
build:
name: "Build Pre-Release (${{ inputs.stability }})"
runs-on: release
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GA_TOKEN }}
- name: Setup tools
run: |
# Update moko-platform CLI tools if available; install PHP if missing
if command -v moko-platform-update &> /dev/null; then
moko-platform-update
elif [ -d "/opt/moko-platform" ]; then
cd /opt/moko-platform && git pull origin main --quiet 2>/dev/null || true
else
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl >/dev/null 2>&1
fi
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/moko-platform.git" \
/tmp/moko-platform-api
fi
# Set MOKO_CLI to whichever path exists
if [ -d "/opt/moko-platform/cli" ]; then
echo "MOKO_CLI=/opt/moko-platform/cli" >> "$GITHUB_ENV"
else
echo "MOKO_CLI=/tmp/moko-platform-api/cli" >> "$GITHUB_ENV"
fi
- name: Detect platform
id: platform
run: |
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
- name: Resolve metadata and bump version
id: meta
run: |
STABILITY="${{ inputs.stability }}"
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
beta) SUFFIX="-beta"; TAG="beta" ;;
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
esac
# Patch bump via CLI tool
php ${MOKO_CLI}/version_bump.php --path .
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null)
[ -z "$VERSION" ] && VERSION="00.00.01"
TODAY=$(date +%Y-%m-%d)
# Update platform-specific manifest
PLATFORM="${{ steps.platform.outputs.platform }}"
MANIFEST="${{ steps.platform.outputs.manifest }}"
MOD_FILE="${{ steps.platform.outputs.mod_file }}"
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true
# Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
git push origin HEAD 2>&1
}
# Auto-detect element (platform-aware)
EXT_ELEMENT=""
case "$PLATFORM" in
joomla)
if [ -n "$MANIFEST" ]; then
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
case "$EXT_ELEMENT" in
templatedetails|manifest) EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
esac
fi
else
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
;;
dolibarr)
if [ -n "$MOD_FILE" ]; then
MOD_BASENAME=$(basename "$MOD_FILE" .class.php)
EXT_ELEMENT=$(echo "$MOD_BASENAME" | sed 's/^mod//' | tr '[:upper:]' '[:lower:]')
else
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
;;
*)
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
;;
esac
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
- name: Build package
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
if [ ! -d "$SOURCE_DIR" ]; then
echo "::error::No src/ or htdocs/ directory"
exit 1
fi
MANIFEST="${{ steps.meta.outputs.manifest }}"
EXT_TYPE=""
if [ -n "$MANIFEST" ]; then
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
EXCLUDES="sftp-config* .ftpignore *.ppk *.pem *.key .env* *.local .build-trigger"
mkdir -p build/package
if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
echo "=== Building Joomla PACKAGE (multi-extension) ==="
for ext_dir in "${SOURCE_DIR}"/packages/*/; do
[ ! -d "$ext_dir" ] && continue
EXT_NAME=$(basename "$ext_dir")
echo " Packaging sub-extension: ${EXT_NAME}"
cd "$ext_dir"
zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES
cd "$OLDPWD"
done
for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
[ -f "$f" ] && cp "$f" build/package/
done
else
echo "=== Building standard extension ==="
rsync -a \
--exclude='sftp-config*' \
--exclude='.ftpignore' \
--exclude='*.ppk' \
--exclude='*.pem' \
--exclude='*.key' \
--exclude='.env*' \
--exclude='*.local' \
--exclude='.build-trigger' \
"${SOURCE_DIR}/" build/package/
fi
- name: Create ZIP
id: zip
run: |
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
cd build/package
zip -r "../${ZIP_NAME}" .
cd ..
SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
echo "ZIP: ${ZIP_NAME} (SHA: ${SHA256:0:16}...)"
- name: Create or replace Gitea release
id: release
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
BRANCH=$(git branch --show-current)
BODY="## ${VERSION} ($(date +%Y-%m-%d))
**Channel:** ${STABILITY}
**SHA-256:** \`${SHA256}\`"
# Delete existing release
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
"${API}/releases/tags/${TAG}" | jq -r '.id // empty' 2>/dev/null)
if [ -n "$EXISTING_ID" ]; then
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
"${API}/releases/${EXISTING_ID}" 2>/dev/null || true
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
"${API}/tags/${TAG}" 2>/dev/null || true
fi
# Create release
RELEASE_ID=$(curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/releases" \
-d "$(jq -n \
--arg tag "$TAG" \
--arg target "$BRANCH" \
--arg name "${EXT_ELEMENT} ${VERSION} (${STABILITY})" \
--arg body "$BODY" \
'{tag_name: $tag, target_commitish: $target, name: $name, body: $body, prerelease: true}'
)" | jq -r '.id')
echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
# Upload ZIP
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/octet-stream" \
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
--data-binary "@build/${ZIP_NAME}"
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
- name: Update updates.xml
if: steps.platform.outputs.platform == 'joomla'
run: |
STABILITY="${{ steps.meta.outputs.stability }}"
VERSION="${{ steps.meta.outputs.version }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
TAG="${{ steps.meta.outputs.tag }}"
if [ ! -f "updates.xml" ]; then
echo "No updates.xml -- skipping"
exit 0
fi
# Map stability to XML tag name
case "$STABILITY" in
development) XML_TAG="development" ;;
alpha) XML_TAG="alpha" ;;
beta) XML_TAG="beta" ;;
release-candidate) XML_TAG="rc" ;;
*) XML_TAG="$STABILITY" ;;
esac
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${TAG}/${ZIP_NAME}"
# Use PHP to update the channel in updates.xml
php -r '
$xml_tag = $argv[1];
$version = $argv[2];
$sha256 = $argv[3];
$url = $argv[4];
$date = date("Y-m-d");
$content = file_get_contents("updates.xml");
$pattern = "/(<update>(?:(?!<\/update>).)*?<tag>" . preg_quote($xml_tag) . "<\/tag>.*?<\/update>)/s";
$content = preg_replace_callback($pattern, function($m) use ($version, $sha256, $url, $date) {
$block = $m[0];
$block = preg_replace("/<version>[^<]*<\/version>/", "<version>{$version}</version>", $block);
if (strpos($block, "<sha256>") !== false) {
$block = preg_replace("/<sha256>[^<]*<\/sha256>/", "<sha256>{$sha256}</sha256>", $block);
} else {
$block = str_replace("</downloads>", "</downloads>\n <sha256>{$sha256}</sha256>", $block);
}
$block = preg_replace("/(<downloadurl[^>]*>)[^<]*(<\/downloadurl>)/", "\${1}{$url}\${2}", $block);
return $block;
}, $content);
file_put_contents("updates.xml", $content);
echo "Updated {$xml_tag} channel: version={$version}\n";
' "$XML_TAG" "$VERSION" "$SHA256" "$DOWNLOAD_URL"
# Commit and push
if ! git diff --quiet updates.xml 2>/dev/null; then
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git add updates.xml
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
git push origin HEAD 2>&1 || echo "WARNING: push failed"
fi
- name: "Sync updates.xml to all branches"
if: steps.platform.outputs.platform == 'joomla'
run: |
CURRENT_BRANCH="${{ github.ref_name }}"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
for BRANCH in main dev; do
[ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
echo "Syncing updates.xml -> ${BRANCH}"
git fetch origin "${BRANCH}" 2>/dev/null || continue
git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
git checkout "${CURRENT_BRANCH}" -- updates.xml
if ! git diff --quiet updates.xml 2>/dev/null; then
git add updates.xml
git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
fi
git checkout "${CURRENT_BRANCH}" 2>/dev/null
done
- name: "Delete lesser pre-release channels (cascade)"
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
php ${MOKO_CLI}/release_cascade.php \
--stability "${{ steps.meta.outputs.stability }}" \
--token "${TOKEN}" \
--api-base "${API_BASE}"
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
+817
View File
@@ -0,0 +1,817 @@
# ============================================================================
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Validation
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/joomla/repo_health.yml.template
# VERSION: 09.23.00
# BRIEF: Enforces repository guardrails by validating release configuration, scripts governance, tooling availability, and core repository health artifacts.
# ============================================================================
name: "Generic: Repo Health"
defaults:
run:
shell: bash
on:
workflow_dispatch:
inputs:
profile:
description: 'Validation profile: all, release, scripts, or repo'
required: true
default: all
type: choice
options:
- all
- release
- scripts
- repo
pull_request:
push:
permissions:
contents: read
env:
# Release policy - Repository Variables Only
RELEASE_REQUIRED_REPO_VARS: RS_FTP_PATH_SUFFIX
RELEASE_OPTIONAL_REPO_VARS: DEV_FTP_SUFFIX
# Scripts governance policy
SCRIPTS_REQUIRED_DIRS:
SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate
# Repo health policy
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
# Extended checks toggles
EXTENDED_CHECKS: "true"
# File / directory variables
DOCS_INDEX: docs/docs-index.md
SCRIPT_DIR: scripts
WORKFLOWS_DIR: .mokogitea/workflows
SHELLCHECK_PATTERN: '*.sh'
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
access_check:
name: Access control
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
outputs:
allowed: ${{ steps.perm.outputs.allowed }}
permission: ${{ steps.perm.outputs.permission }}
steps:
- name: Check actor permission (admin only)
id: perm
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
REPO: ${{ github.repository }}
ACTOR: ${{ github.actor }}
run: |
set -euo pipefail
ALLOWED=false
PERMISSION=unknown
METHOD=""
# Hardcoded authorized users — always allowed
case "$ACTOR" in
jmiller|gitea-actions[bot])
ALLOWED=true
PERMISSION=admin
METHOD="hardcoded allowlist"
;;
*)
# Detect platform and check permissions via API
API_BASE="${GITHUB_API_URL:-${GITEA_API_URL:-https://api.github.com}}"
RESP=$(curl -sf -H "Authorization: token ${TOKEN}" \
"${API_BASE}/repos/${REPO}/collaborators/${ACTOR}/permission" 2>/dev/null || echo '{}')
PERMISSION=$(echo "$RESP" | grep -oP '"permission"\s*:\s*"\K[^"]+' || echo "unknown")
if [ "$PERMISSION" = "admin" ] || [ "$PERMISSION" = "maintain" ] || [ "$PERMISSION" = "owner" ]; then
ALLOWED=true
fi
METHOD="collaborator API"
;;
esac
echo "permission=${PERMISSION}" >> "$GITHUB_OUTPUT"
echo "allowed=${ALLOWED}" >> "$GITHUB_OUTPUT"
{
echo "## Access Authorization"
echo ""
echo "| Field | Value |"
echo "|-------|-------|"
echo "| **Actor** | \`${ACTOR}\` |"
echo "| **Repository** | \`${REPO}\` |"
echo "| **Permission** | \`${PERMISSION}\` |"
echo "| **Method** | ${METHOD} |"
echo "| **Authorized** | ${ALLOWED} |"
echo ""
if [ "$ALLOWED" = "true" ]; then
echo "${ACTOR} authorized (${METHOD})"
else
echo "${ACTOR} is NOT authorized. Requires admin or maintain role."
fi
} >> "${GITHUB_STEP_SUMMARY}"
- name: Deny execution when not permitted
if: ${{ steps.perm.outputs.allowed != 'true' }}
run: |
set -euo pipefail
printf '%s\n' 'ERROR: Access denied. Admin permission required.' >> "${GITHUB_STEP_SUMMARY}"
exit 1
release_config:
name: Release configuration
needs: access_check
if: ${{ needs.access_check.outputs.allowed == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Guardrails release vars
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
RS_FTP_PATH_SUFFIX: ${{ vars.RS_FTP_PATH_SUFFIX }}
DEV_FTP_SUFFIX: ${{ vars.DEV_FTP_SUFFIX }}
run: |
set -euo pipefail
profile="${PROFILE_RAW:-all}"
case "${profile}" in
all|release|scripts|repo) ;;
*)
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
if [ "${profile}" = 'scripts' ] || [ "${profile}" = 'repo' ]; then
{
printf '%s\n' '### Release configuration (Repository Variables)'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' 'Status: SKIPPED'
printf '%s\n' 'Reason: profile excludes release validation'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
IFS=',' read -r -a required <<< "${RELEASE_REQUIRED_REPO_VARS}"
IFS=',' read -r -a optional <<< "${RELEASE_OPTIONAL_REPO_VARS}"
missing=()
missing_optional=()
for k in "${required[@]}"; do
v="${!k:-}"
[ -z "${v}" ] && missing+=("${k}")
done
for k in "${optional[@]}"; do
v="${!k:-}"
[ -z "${v}" ] && missing_optional+=("${k}")
done
{
printf '%s\n' '### Release configuration (Repository Variables)'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' '| Variable | Status |'
printf '%s\n' '|---|---|'
printf '%s\n' "| RS_FTP_PATH_SUFFIX | ${RS_FTP_PATH_SUFFIX:-NOT SET} |"
printf '%s\n' "| DEV_FTP_SUFFIX | ${DEV_FTP_SUFFIX:-NOT SET} |"
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
if [ "${#missing_optional[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing optional repository variables'
for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
if [ "${#missing[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing required repository variables'
for m in "${missing[@]}"; do printf '%s\n' "- ${m}"; done
printf '%s\n' 'ERROR: Guardrails failed. Missing required repository variables.'
} >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
{
printf '%s\n' '### Repository variables validation result'
printf '%s\n' 'Status: OK'
printf '%s\n' 'All required repository variables present.'
printf '%s\n' ''
printf '%s\n' '**Note**: Organization secrets (RS_FTP_HOST, RS_FTP_USER, etc.) are validated at deployment time, not in repository health checks.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
scripts_governance:
name: Scripts governance
needs: access_check
if: ${{ needs.access_check.outputs.allowed == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Scripts folder checks
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
run: |
set -euo pipefail
profile="${PROFILE_RAW:-all}"
case "${profile}" in
all|release|scripts|repo) ;;
*)
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
if [ "${profile}" = 'release' ] || [ "${profile}" = 'repo' ]; then
{
printf '%s\n' '### Scripts governance'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' 'Status: SKIPPED'
printf '%s\n' 'Reason: profile excludes scripts governance'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
if [ ! -d "${SCRIPT_DIR}" ]; then
{
printf '%s\n' '### Scripts governance'
printf '%s\n' 'Status: OK (advisory)'
printf '%s\n' 'scripts/ directory not present. No scripts governance enforced.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
if [ -n "${SCRIPTS_REQUIRED_DIRS:-}" ]; then IFS=',' read -r -a required_dirs <<< "${SCRIPTS_REQUIRED_DIRS}"; else required_dirs=(); fi
IFS=',' read -r -a allowed_dirs <<< "${SCRIPTS_ALLOWED_DIRS}"
missing_dirs=()
unapproved_dirs=()
for d in "${required_dirs[@]}"; do
req="${d%/}"
[ ! -d "${req}" ] && missing_dirs+=("${req}/")
done
while IFS= read -r d; do
allowed=false
for a in "${allowed_dirs[@]}"; do
a_norm="${a%/}"
[ "${d%/}" = "${a_norm}" ] && allowed=true
done
[ "${allowed}" = false ] && unapproved_dirs+=("${d%/}/")
done < <(find "${SCRIPT_DIR}" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sed 's#^\./##')
{
printf '%s\n' '### Scripts governance'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' '| Area | Status | Notes |'
printf '%s\n' '|---|---|---|'
if [ "${#missing_dirs[@]}" -gt 0 ]; then
printf '%s\n' '| Required directories | Warning | Missing required subfolders |'
else
printf '%s\n' '| Required directories | OK | All required subfolders present |'
fi
if [ "${#unapproved_dirs[@]}" -gt 0 ]; then
printf '%s\n' '| Directory policy | Warning | Unapproved directories detected |'
else
printf '%s\n' '| Directory policy | OK | No unapproved directories |'
fi
printf '%s\n' '| Enforcement mode | Advisory | scripts folder is optional |'
printf '\n'
if [ "${#missing_dirs[@]}" -gt 0 ]; then
printf '%s\n' 'Missing required script directories:'
for m in "${missing_dirs[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
else
printf '%s\n' 'Missing required script directories: none.'
printf '\n'
fi
if [ "${#unapproved_dirs[@]}" -gt 0 ]; then
printf '%s\n' 'Unapproved script directories detected:'
for m in "${unapproved_dirs[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
else
printf '%s\n' 'Unapproved script directories detected: none.'
printf '\n'
fi
printf '%s\n' 'Scripts governance completed in advisory mode.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
repo_health:
name: Repository health
needs: access_check
if: ${{ needs.access_check.outputs.allowed == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Repository health checks
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
run: |
set -euo pipefail
profile="${PROFILE_RAW:-all}"
case "${profile}" in
all|release|scripts|repo) ;;
*)
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
if [ "${profile}" = 'release' ] || [ "${profile}" = 'scripts' ]; then
{
printf '%s\n' '### Repository health'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' 'Status: SKIPPED'
printf '%s\n' 'Reason: profile excludes repository health'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}"
IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}"
if [ -n "${REPO_DISALLOWED_DIRS:-}" ]; then IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"; else disallowed_dirs=(); fi
IFS=',' read -r -a disallowed_files <<< "${REPO_DISALLOWED_FILES:-}"
missing_required=()
missing_optional=()
# Source directory: src/ or htdocs/ (either is valid for extension repos)
SOURCE_DIR=""
if [ -d "src" ]; then
SOURCE_DIR="src"
elif [ -d "htdocs" ]; then
SOURCE_DIR="htdocs"
elif [ -d "deploy" ] || [ -d "cli" ] || [ -d "monitoring" ]; then
# Platform/tooling repos don't need src/
SOURCE_DIR=""
else
missing_required+=("src/ or htdocs/ (source directory required)")
fi
for item in "${required_artifacts[@]}"; do
if printf '%s' "${item}" | grep -q '/$'; then
d="${item%/}"
[ ! -d "${d}" ] && missing_required+=("${item}")
else
[ ! -f "${item}" ] && missing_required+=("${item}")
fi
done
for f in "${optional_files[@]}"; do
if printf '%s' "${f}" | grep -q '/$'; then
d="${f%/}"
[ ! -d "${d}" ] && missing_optional+=("${f}")
else
[ ! -f "${f}" ] && missing_optional+=("${f}")
fi
done
for d in "${disallowed_dirs[@]}"; do
d_norm="${d%/}"
[ -d "${d_norm}" ] && missing_required+=("${d_norm}/ (disallowed)")
done
for f in "${disallowed_files[@]}"; do
[ -f "${f}" ] && missing_required+=("${f} (disallowed)")
done
git fetch origin --prune
dev_paths=()
dev_branches=()
while IFS= read -r b; do
name="${b#origin/}"
if [ "${name}" = 'dev' ]; then
dev_branches+=("${name}")
else
dev_paths+=("${name}")
fi
done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//')
if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then
missing_required+=("dev or dev/* branch")
fi
content_warnings=()
if [ -f 'CHANGELOG.md' ] && ! grep -Eq '^# Changelog' CHANGELOG.md; then
content_warnings+=("CHANGELOG.md missing '# Changelog' header")
fi
if [ -f 'CHANGELOG.md' ] && grep -Eq '^[# ]*Unreleased' CHANGELOG.md; then
content_warnings+=("CHANGELOG.md contains Unreleased section (review release readiness)")
fi
if [ -f 'LICENSE' ] && ! grep -qiE 'GNU GENERAL PUBLIC LICENSE|GPL' LICENSE; then
content_warnings+=("LICENSE does not look like a GPL text")
fi
if [ -f 'README.md' ] && ! grep -qiE 'moko|Moko' README.md; then
content_warnings+=("README.md missing expected brand keyword")
fi
export PROFILE_RAW="${profile}"
export MISSING_REQUIRED="$(printf '%s\n' "${missing_required[@]:-}")"
export MISSING_OPTIONAL="$(printf '%s\n' "${missing_optional[@]:-}")"
export CONTENT_WARNINGS="$(printf '%s\n' "${content_warnings[@]:-}")"
report_json=$(printf '{"profile":"%s","missing_required":%d,"missing_optional":%d,"content_warnings":%d}' "$profile" "${#missing_required[@]}" "${#missing_optional[@]}" "${#content_warnings[@]}")
{
printf '%s\n' '### Repository health'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' '| Metric | Value |'
printf '%s\n' '|---|---|'
printf '%s\n' "| Missing required | ${#missing_required[@]} |"
printf '%s\n' "| Missing optional | ${#missing_optional[@]} |"
printf '%s\n' "| Content warnings | ${#content_warnings[@]} |"
printf '\n'
printf '%s\n' '### Guardrails report (JSON)'
printf '%s\n' '```json'
printf '%s\n' "${report_json}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
if [ "${#missing_required[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing required repo artifacts'
for m in "${missing_required[@]}"; do printf '%s\n' "- ${m}"; done
printf '%s\n' 'ERROR: Guardrails failed. Missing required repository artifacts.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
if [ "${#missing_optional[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing optional repo artifacts'
for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
if [ "${#content_warnings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Repo content warnings'
for m in "${content_warnings[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
# -- Joomla-specific checks --
joomla_findings=()
MANIFEST="$(find . -maxdepth 2 -name '*.xml' -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)"
if [ -z "${MANIFEST}" ]; then
joomla_findings+=("Joomla XML manifest not found (no *.xml with <extension> tag)")
else
if ! grep -qP '<version>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <version> tag missing")
fi
if ! grep -qP 'type="(component|module|plugin|library|package|template|language)"' "${MANIFEST}"; then
joomla_findings+=("XML manifest: type attribute missing or invalid")
fi
if ! grep -qP '<name>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <name> tag missing")
fi
if ! grep -qP '<author>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <author> tag missing")
fi
if ! grep -qP '<namespace' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <namespace> missing (required for Joomla 5+)")
fi
fi
INI_COUNT="$(find . -name '*.ini' -type f 2>/dev/null | wc -l)"
if [ "${INI_COUNT}" -eq 0 ]; then
joomla_findings+=("No .ini language files found")
fi
if [ ! -f 'updates.xml' ]; then
joomla_findings+=("updates.xml missing in root (required for Joomla update server)")
fi
if [ -n "${SOURCE_DIR}" ]; then
INDEX_DIRS=("${SOURCE_DIR}" "${SOURCE_DIR}/admin" "${SOURCE_DIR}/site")
for dir in "${INDEX_DIRS[@]}"; do
if [ -d "${dir}" ] && [ ! -f "${dir}/index.html" ]; then
joomla_findings+=("${dir}/index.html missing (directory listing protection)")
fi
done
fi
if [ "${#joomla_findings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Joomla extension checks'
printf '%s\n' '| Check | Status |'
printf '%s\n' '|---|---|'
for f in "${joomla_findings[@]}"; do
printf '%s\n' "| ${f} | Warning |"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
else
{
printf '%s\n' '### Joomla extension checks'
printf '%s\n' 'All Joomla-specific checks passed.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
extended_enabled="${EXTENDED_CHECKS:-true}"
extended_findings=()
if [ "${extended_enabled}" = 'true' ]; then
if [ -f '.github/CODEOWNERS' ] || [ -f 'CODEOWNERS' ] || [ -f 'docs/CODEOWNERS' ]; then
:
else
extended_findings+=("CODEOWNERS not found (.github/CODEOWNERS preferred)")
fi
if ls "${WORKFLOWS_DIR}"/*.yml >/dev/null 2>&1 || ls "${WORKFLOWS_DIR}"/*.yaml >/dev/null 2>&1; then
bad_refs="$(grep -RIn --include='*.yml' --include='*.yaml' -E '^[[:space:]]*uses:[[:space:]]*[^#]+@(main|master)\b' "${WORKFLOWS_DIR}" 2>/dev/null || true)"
if [ -n "${bad_refs}" ]; then
extended_findings+=("Workflows reference actions @main/@master (pin versions): see log excerpt")
{
printf '%s\n' '### Workflow pinning advisory'
printf '%s\n' 'Found uses: entries pinned to main/master:'
printf '%s\n' '```'
printf '%s\n' "${bad_refs}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
if [ -f "${DOCS_INDEX}" ]; then
missing_links=""
while IFS= read -r docline; do
for link in $(echo "$docline" | grep -oE '\]\([^)]+\)' | sed 's/\](//' | sed 's/)$//' || true); do
case "$link" in http://*|https://*|"#"*|mailto:*) continue ;; esac
linkpath="${link%%#*}"
linkpath="${linkpath%%\?*}"
[ -z "$linkpath" ] && continue
if [ "${linkpath:0:1}" = "/" ]; then
testpath="${linkpath#/}"
else
testpath="$(dirname "${DOCS_INDEX}")/${linkpath}"
fi
[ ! -e "$testpath" ] && missing_links="${missing_links}${testpath} "
done
done < "${DOCS_INDEX}"
if [ -n "${missing_links}" ]; then
extended_findings+=("docs/docs-index.md contains broken relative links")
{
printf '%s\n' '### Docs index link integrity'
printf '%s\n' 'Broken relative links:'
for bl in ${missing_links}; do
printf '%s\n' "- ${bl}"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
if [ -d "${SCRIPT_DIR}" ]; then
if ! command -v shellcheck >/dev/null 2>&1; then
sudo apt-get update -qq
sudo apt-get install -y shellcheck >/dev/null
fi
sc_out=''
while IFS= read -r shf; do
[ -z "${shf}" ] && continue
out_one="$(shellcheck -S warning -x "${shf}" 2>/dev/null || true)"
if [ -n "${out_one}" ]; then
sc_out="${sc_out}${out_one}\n"
fi
done < <(find "${SCRIPT_DIR}" -type f -name "${SHELLCHECK_PATTERN}" 2>/dev/null | sort)
if [ -n "${sc_out}" ]; then
extended_findings+=("ShellCheck warnings detected (advisory)")
sc_head="$(printf '%s' "${sc_out}" | head -n 200)"
{
printf '%s\n' '### ShellCheck (advisory)'
printf '%s\n' '```'
printf '%s\n' "${sc_head}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
spdx_missing=()
IFS=',' read -r -a spdx_globs <<< "${SPDX_FILE_GLOBS}"
spdx_args=()
for g in "${spdx_globs[@]}"; do spdx_args+=("${g}"); done
while IFS= read -r f; do
[ -z "${f}" ] && continue
if ! head -n 40 "${f}" | grep -q 'SPDX-License-Identifier:'; then
spdx_missing+=("${f}")
fi
done < <(git ls-files "${spdx_args[@]}" 2>/dev/null || true)
if [ "${#spdx_missing[@]}" -gt 0 ]; then
extended_findings+=("SPDX header missing in some tracked files (advisory)")
{
printf '%s\n' '### SPDX header advisory'
printf '%s\n' 'Files missing SPDX-License-Identifier (first 40 lines scan):'
for f in "${spdx_missing[@]}"; do printf '%s\n' "- ${f}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
stale_cutoff_days=180
stale_branches="$(git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/remotes/origin 2>/dev/null | awk -v now="$(date +%s)" -v days="${stale_cutoff_days}" '{if (now-$2 > days*86400) print $1}' | head -50)"
if [ -n "${stale_branches}" ]; then
extended_findings+=("Stale remote branches detected (advisory)")
{
printf '%s\n' '### Git hygiene advisory'
printf '%s\n' "Branches with last commit older than ${stale_cutoff_days} days (sample up to 50):"
while IFS= read -r b; do [ -n "${b}" ] && printf '%s\n' "- ${b}"; done <<< "${stale_branches}"
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
{
printf '%s\n' '### Guardrails coverage matrix'
printf '%s\n' '| Domain | Status | Notes |'
printf '%s\n' '|---|---|---|'
printf '%s\n' '| Access control | OK | Admin-only execution gate |'
printf '%s\n' '| Release variables | OK | Repository variables validation |'
printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |'
printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |'
printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |'
if [ "${extended_enabled}" = 'true' ]; then
if [ "${#extended_findings[@]}" -gt 0 ]; then
printf '%s\n' '| Extended checks | Warning | See extended findings below |'
else
printf '%s\n' '| Extended checks | OK | No findings |'
fi
else
printf '%s\n' '| Extended checks | SKIPPED | EXTENDED_CHECKS disabled |'
fi
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
if [ "${extended_enabled}" = 'true' ] && [ "${#extended_findings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Extended findings (advisory)'
for f in "${extended_findings[@]}"; do printf '%s\n' "- ${f}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
printf '%s\n' 'Repository health guardrails passed.' >> "${GITHUB_STEP_SUMMARY}"
site-health:
name: Site Health
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- name: Uptime check
if: env.URLS != ''
run: |
echo "$URLS" > /tmp/urls.txt
php monitoring/uptime-probe.php --urls /tmp/urls.txt --timeout 15 || echo "::warning::Some sites are down"
rm -f /tmp/urls.txt
env:
URLS: ${{ vars.MONITORED_URLS }}
- name: SSL certificate check
if: env.DOMAINS != ''
run: |
echo "$DOMAINS" > /tmp/domains.txt
php monitoring/ssl-check.php --domains /tmp/domains.txt --warn-days 30 || echo "::warning::SSL certificates expiring soon"
rm -f /tmp/domains.txt
env:
DOMAINS: ${{ vars.MONITORED_DOMAINS }}
- name: Summary
if: always()
run: |
echo "### Site Health" >> $GITHUB_STEP_SUMMARY
echo "Uptime and SSL checks completed." >> $GITHUB_STEP_SUMMARY
# ═══════════════════════════════════════════════════════════════════════
# Issue Reporter — file issues for failed gates
# ═══════════════════════════════════════════════════════════════════════
report-issues:
name: "Report Issues"
runs-on: ubuntu-latest
needs: [access_check, release_config, scripts_governance, repo_health]
if: >-
always() &&
(needs.release_config.result == 'failure' ||
needs.scripts_governance.result == 'failure' ||
needs.repo_health.result == 'failure')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issues for failed gates"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
REPORTER="./automation/ci-issue-reporter.sh"
WF="Repo Health"
report_gate() {
local gate="$1" result="$2" details="$3"
if [ "$result" = "failure" ]; then
"$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error
fi
}
report_gate "Release Configuration" \
"${{ needs.release_config.result }}" \
"Required repository variables are missing (RS_FTP_PATH_SUFFIX). Check repository settings."
report_gate "Scripts Governance" \
"${{ needs.scripts_governance.result }}" \
"Scripts directory policy violations detected. Review required and allowed directories."
report_gate "Repository Health" \
"${{ needs.repo_health.result }}" \
"Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
+2 -2
View File
@@ -23,9 +23,9 @@ jobs:
steps:
- name: Sync upstream bugs
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
MOKOGITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
MOKOGITEA_URL: https://git.mokoconsulting.tech
MOKOGITEA_URL: https://code.mokoconsulting.tech
MOKOGITEA_REPO: MokoConsulting/MokoGitea
UPSTREAM_BRANCH: release/v1.26
DAYS_BACK: ${{ github.event.inputs.days_back || '7' }}
+88 -5375
View File
File diff suppressed because it is too large Load Diff
+113 -245
View File
@@ -1,293 +1,161 @@
# Contribution Guidelines
# Contributing to Moko Consulting Projects
This document explains how to contribute changes to the Gitea project. Topic-specific guides live in separate files so the essentials are easier to find.
Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy.
| Topic | Document |
| :---- | :------- |
| Backend (Go modules, API v1) | [docs/guideline-backend.md](docs/guideline-backend.md) |
| Frontend (npm, UI guidelines) | [docs/guideline-frontend.md](docs/guideline-frontend.md) |
| Maintainers, TOC, labels, merge queue, commit format for mergers | [docs/community-governance.md](docs/community-governance.md) |
| Release cycle, backports, tagging releases | [docs/release-management.md](docs/release-management.md) |
<details><summary>Table of Contents</summary>
- [Contribution Guidelines](#contribution-guidelines)
- [Introduction](#introduction)
- [AI Contribution Policy](#ai-contribution-policy)
- [Issues](#issues)
- [How to report issues](#how-to-report-issues)
- [Types of issues](#types-of-issues)
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
- [Issue locking](#issue-locking)
- [Building Gitea](#building-gitea)
- [Styleguide](#styleguide)
- [Copyright](#copyright)
- [Testing](#testing)
- [Translation](#translation)
- [Code review](#code-review)
- [Pull request format](#pull-request-format)
- [PR title and summary](#pr-title-and-summary)
- [Breaking PRs](#breaking-prs)
- [What is a breaking PR?](#what-is-a-breaking-pr)
- [How to handle breaking PRs?](#how-to-handle-breaking-prs)
- [Maintaining open PRs](#maintaining-open-prs)
- [Reviewing PRs](#reviewing-prs)
- [For PR authors](#for-pr-authors)
- [Documentation](#documentation)
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
</details>
## Introduction
It assumes you have followed the [installation instructions](https://docs.gitea.com/category/installation). \
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
## AI Contribution Policy
Contributions made with the assistance of AI tools are welcome, but contributors must use them responsibly and disclose that use clearly.
1. Review AI-generated code closely before marking a pull request ready for review.
2. Manually test the changes and add appropriate automated tests where feasible.
3. Only use AI to assist in contributions that you understand well enough to explain, defend, and revise yourself during review.
4. Disclose AI-assisted content clearly.
5. Do not use AI to reply to questions about your issue or pull request. The questions are for you, not an AI model.
6. AI may be used to help draft issues and pull requests, but contributors remain responsible for the accuracy, completeness, and intent of what they submit.
Maintainers reserve the right to close pull requests and issues that do not disclose AI assistance, that appear to be low-quality AI-generated content, or where the contributor cannot explain or defend the proposed changes themselves.
We welcome new contributors, but cannot sustain the effort of supporting contributors who primarily defer to AI rather than engaging substantively with the review process.
## Issues
### How to report issues
Please search the issues on the issue tracker with a variety of related keywords to ensure that your issue has not already been reported.
If your issue has not been reported yet, [open an issue](https://github.com/go-gitea/gitea/issues/new)
and answer the questions so we can understand and reproduce the problematic behavior. \
Please write clear and concise instructions so that we can reproduce the behavior — even if it seems obvious. \
The more detailed and specific you are, the faster we can fix the issue. \
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://demo.gitea.com>, as perhaps your problem has already been fixed on a current version. \
Please follow the guidelines described in [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for your report.
Please be kind—remember that Gitea comes at no cost to you, and you're getting free help.
### Types of issues
Typically, issues fall in one of the following categories:
- `bug`: Something in the frontend or backend behaves unexpectedly
- `security issue`: bug that has serious implications such as leaking another users data. Please do not file such issues on the public tracker and send a mail to security@gitea.io instead
- `feature`: Completely new functionality. You should describe this feature in enough detail that anyone who reads the issue can understand how it is supposed to be implemented
- `enhancement`: An existing feature should get an upgrade
- `refactoring`: Parts of the code base don't conform with other parts and should be changed to improve Gitea's maintainability
### Discuss your design before the implementation
We welcome submissions. \
If you want to change or add something, please let everyone know what you're working on — [file an issue](https://github.com/go-gitea/gitea/issues/new) or comment on an existing one before starting your work!
Significant changes such as new features must go through the change proposal process before they can be accepted. \
This is mainly to save yourself the trouble of implementing it, only to find out that your proposed implementation has some potential problems. \
Furthermore, this process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside
the goals for the project and tools.
Pull requests should not be the place for architecture discussions.
### Issue locking
Commenting on closed or merged issues/PRs is strongly discouraged.
Such comments will likely be overlooked as some maintainers may not view notifications on closed issues, thinking that the item is resolved.
As such, commenting on closed/merged issues/PRs may be disabled prior to the scheduled auto-locking if a discussion starts or if unrelated comments are posted.
If further discussion is needed, we encourage you to open a new issue instead and we recommend linking to the issue/PR in question for context.
## Building Gitea
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
## Styleguide
You should always run `make fmt` before committing to conform to Gitea's styleguide.
## Copyright
New code files that you contribute should use the standard copyright header:
## Branching Workflow
```
// Copyright <current year> The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main
```
Afterwards, copyright should only be modified when the copyright author changes.
### Step by step
## Testing
1. **Create a feature branch** from `dev`:
```bash
git checkout dev && git pull
git checkout -b feature/my-change
```
Before submitting a pull request, run all tests to make sure your changes don't cause a regression elsewhere.
2. **Work and commit** on your feature branch. Push to origin.
Here's how to run the test suite:
3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it.
- code lint
4. **When ready for release**, open a **draft PR**: `dev` → `main`.
- This automatically renames the source branch to `rc` (release candidate)
- An RC pre-release is built and uploaded
| | |
| :-------------------- | :--------------------------------------------------------------------------- |
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|``make lint-frontend`` | lint frontend files |
|``make lint-backend`` | lint backend files |
5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage:
- Rename `dev` to `alpha` for early testing → alpha pre-release is built
- Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built
- When the draft PR is created, the branch is renamed to `rc`
- run tests (we suggest running them on Linux)
6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`.
| Command | Action | |
|:----------------------------------------------|:-----------------------------------------------------| ------------------------------------------- |
| ``make test-backend[\#SpecificTestName]`` | run unit test(s) | |
| ``make test-integration[\#SpecificTestName]`` | run [integration](tests/integration) test(s) | [More details](tests/integration/README.md) |
| ``make test-e2e`` | run [end-to-end](tests/e2e) test(s) using Playwright | |
7. **Merging to main** triggers the stable release pipeline:
- Minor version bump (e.g., `02.09.xx` → `02.10.00`)
- Stability suffix stripped (clean version)
- Gitea release created with ZIP/tar.gz packages
- `updates.xml` updated (Joomla extensions)
- `dev` branch recreated from `main`
- E2E test environment variables
### Branch summary
| Variable | Description |
| :-------------------------------- | :---------------------------------------------------------- |
| ``GITEA_TEST_E2E_DEBUG`` | When set, show Gitea server output |
| ``GITEA_TEST_E2E_FLAGS`` | Additional flags passed to Playwright, for example ``--ui`` |
| ``GITEA_TEST_E2E_TIMEOUT_FACTOR`` | Timeout multiplier (default: 4 on CI, 1 locally) |
| Branch | Purpose | Created by |
|--------|---------|-----------|
| `feature/*` | New features and fixes | Developer |
| `dev` | Integration branch | Auto-recreated after release |
| `alpha` | Alpha pre-release testing | Manual rename from `dev` |
| `beta` | Beta pre-release testing | Manual rename from `alpha` |
| `rc` | Release candidate | Auto-renamed on draft PR to main |
| `main` | Stable releases | Protected, merge only |
| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI |
## Translation
### Protected branches
All translation work happens on [Crowdin](https://translate.gitea.com).
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.json).
It is synced regularly with Crowdin. \
Other locales on main branch **should not** be updated manually as they will be overwritten with each sync. \
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
| Branch | Direct push | Merge via |
|--------|------------|-----------|
| `main` | Blocked (CI bot whitelisted) | PR merge only |
| `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* |
| `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR |
| `alpha` | Blocked (CI bot whitelisted) | Manual rename |
| `beta` | Blocked (CI bot whitelisted) | Manual rename |
| `feature/*` | Open | N/A (source branch) |
The tool `go run build/backport-locale.go` can be used to backport locales from the main branch to release branches that were missed.
## Version Policy
## Code review
### Format
How labels, milestones, and the merge queue work is documented in [docs/community-governance.md](docs/community-governance.md).
All versions use `XX.YY.ZZ` — three two-digit segments, zero-padded:
### Pull request format
- **XX** — Major version (breaking changes)
- **YY** — Minor version (new features, bumped on release to main)
- **ZZ** — Patch version (auto-incremented on every push to dev/feature branches)
Please try to make your pull request easy to review for us. \
For that, please read the [*Best Practices for Faster Reviews*](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) guide. \
It has lots of useful tips for any project you may want to contribute to. \
Some of the key points:
Rollover: patch `99` → `00` increments minor; minor `99` → `00` increments major.
- Make small pull requests. \
The smaller, the faster to review and the more likely it will be merged soon.
- Don't make changes unrelated to your PR. \
Maybe there are typos on some comments, maybe refactoring would be welcome on a function... \
but if that is not related to your PR, please make *another* PR for that.
- Split big pull requests into multiple small ones. \
An incremental change will be faster to review than a huge PR.
- Allow edits by maintainers. This way, the maintainers will take care of merging the PR later on instead of you.
### Stability suffixes
### PR title and summary
Each branch appends a suffix to indicate stability:
In the PR title, describe the problem you are fixing, not how you are fixing it. \
Use the first comment as a summary of your PR. \
In the PR summary, you can describe exactly how you are fixing this problem.
| Branch | Suffix | Example |
|--------|--------|---------|
| `main` | (none) | `02.09.00` |
| `dev` | `-dev` | `02.09.01-dev` |
| `feature/*` | `-dev` | `02.09.01-dev` |
| `alpha` | `-alpha` | `02.09.01-alpha` |
| `beta` | `-beta` | `02.09.01-beta` |
| `rc` | `-rc` | `02.09.01-rc` |
PR titles must follow the [Conventional Commits](https://www.conventionalcommits.org/) format, because PRs are squash-merged and the PR title becomes the resulting commit message:
### Auto version bump
```text
type(scope)!: subject
```
On every push to `dev`, `feature/*`, or `patch/*`:
The allowed types are `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, and `test`. The generic `chore` type is intentionally not accepted; pick a more descriptive type instead.
1. Patch version incremented
2. Stability suffix `-dev` applied
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
4. Commit created with `[skip ci]` to avoid loops
Examples:
### Release version flow
```text
fix(web): prevent avatar upload crash on empty file
feat(api): add pagination to repo hooks list
ci(workflows): lint PR titles with commitlint
```
Version bumps happen at specific release events:
Keep this summary up-to-date as the PR evolves. \
If your PR changes the UI, you must add **after** screenshots in the PR summary. \
If you are not implementing a new feature, you should also post **before** screenshots for comparison.
| Event | Bump | Example |
|-------|------|---------|
| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` |
| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` |
| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) |
| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` |
If you are implementing a new feature, your PR will only be merged if your screenshots are up to date.\
Furthermore, feature PRs will only be merged if their summary contains a clear usage description (understandable for users) and testing description (understandable for reviewers).
You should strive to combine both into a single description.
### Release stream copies
Another requirement for merging PRs is that the PR is labeled correctly.\
However, this is not your job as a contributor, but the job of the person merging your PR.\
If you think that your PR was labeled incorrectly, or notice that it was merged without labels, please let us know.
When a higher-stability release is published, copies are created for all lesser streams with the same base version:
If your PR closes some issues, you must note that in a way that both GitHub and Gitea understand, i.e. by appending a paragraph like
- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta`
- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc`
```text
Fixes/Closes/Resolves #<ISSUE_NR_X>.
Fixes/Closes/Resolves #<ISSUE_NR_Y>.
```
This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed).
to your summary. \
Each issue that will be closed must stand on a separate line.
### Version files
### Breaking PRs
The version tools update all files containing version stamps:
#### What is a breaking PR?
- `.mokogitea/manifest.xml` (canonical source)
- Joomla XML manifests (`<version>` tag)
- `README.md`, `CHANGELOG.md` (`VERSION:` pattern)
- `package.json`, `pyproject.toml`
- Any text file with a `VERSION: XX.YY.ZZ` label
A PR is breaking if it meets one of the following criteria:
Files synced from other repos (with a `# REPO:` header) are not touched.
- It changes API output in an incompatible way for existing users
- It removes a setting that an admin could previously set (i.e. via `app.ini`)
- An admin must do something manually to restore the old behavior
## Code Standards
In particular, this means that adding new settings is not breaking.\
Changing the default value of a setting or replacing the setting with another one is breaking, however.
- **PHP**: PSR-12, tabs for indentation
- **Copyright**: all files must include the Moko Consulting copyright header
- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo)
- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names
#### How to handle breaking PRs?
## Commit Messages
If your PR has a breaking change, you must add two things to the summary of your PR:
1. A reasoning why this breaking change is necessary
2. A `BREAKING` section explaining in simple terms (understandable for a typical user) how this PR affects users and how to mitigate these changes. This section can look for example like
```md
## :warning: BREAKING :warning:
```
Breaking PRs will not be merged as long as not both of these requirements are met.
### Maintaining open PRs
Code review starts when you open a non-draft PR or move a draft out of draft state. After that, do not rebase or squash your branch; it makes new changes harder to review.
Merge the base branch into yours only when you need to, for example because of conflicting changes elsewhere. That limits unnecessary CI runs.
Every PR is squash-merged, so merge commits on your branch do not matter for final history. The squash produces a single commit; mergers follow the [commit message format](docs/community-governance.md#commit-messages) in the governance guide.
### Reviewing PRs
Maintainers are encouraged to review pull requests in areas where they have expertise or particular interest.
#### For PR authors
- **Response**: When answering reviewer questions, use real-world cases or examples and avoid speculation.
- **Discussion**: A discussion is always welcome and should be used to clarify the changes and the intent of the PR.
- **Help**: If you need help with the PR or comments are unclear, ask for clarification.
Guidance for reviewers, the merge queue, and the squash commit message format is in [docs/community-governance.md](docs/community-governance.md).
## Documentation
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in another PR at [https://gitea.com/gitea/docs](https://gitea.com/gitea/docs).
**The docs directory on main repository will be removed at some time. We will have a yaml file to store configuration file's meta data. After that completed, configuration documentation should be in the main repository.**
## Developer Certificate of Origin (DCO)
We consider the act of contributing to the code by submitting a Pull Request as the "Sign off" or agreement to the certifications and terms of the [DCO](DCO) and [MIT license](LICENSE). \
No further action is required. \
You can also decide to sign off your commits by adding the following line at the end of your commit messages:
Use conventional commit format:
```
Signed-off-by: Joe Smith <joe.smith@email.com>
type(scope): short description
Optional body with context.
Authored-by: Moko Consulting
```
If you set the `user.name` and `user.email` Git config options, you can add the line to the end of your commits automatically with `git commit -s`.
Types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `ci`
We assume in good faith that the information you provide is legally binding.
Special flags in commit messages:
- `[skip ci]` — skip all CI workflows
- `[skip bump]` — skip auto version bump only
## Reporting Issues
Use the repository's issue tracker with the appropriate template.
---
*Moko Consulting <hello@mokoconsulting.tech>*
+6 -3
View File
@@ -21,7 +21,7 @@ RUN apk --no-cache add \
build-base \
git
WORKDIR ${GOPATH}/src/git.mokoconsulting.tech/MokoConsulting/MokoGitea
WORKDIR ${GOPATH}/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea
COPY go.mod go.sum ./
RUN go mod download
# Use COPY instead of bind mount as read-only one breaks makefile state tracking
@@ -43,7 +43,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
/tmp/local/etc/s6/gitea/* \
/tmp/local/etc/s6/openssh/* \
/tmp/local/etc/s6/.s6-svscan/* \
/go/src/git.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea
/go/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea
FROM docker.io/library/alpine:3.23 AS gitea
@@ -75,7 +75,10 @@ RUN addgroup \
echo "git:*" | chpasswd -e
COPY --from=build-env /tmp/local /
COPY --from=build-env /go/src/git.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea /app/gitea/gitea
COPY --from=build-env /go/src/code.mokoconsulting.tech/MokoConsulting/MokoGitea/gitea /app/gitea/gitea
# Disable openssh s6 service — we use external SSH (port 2222 via host).
RUN printf '#!/bin/sh\nexec sleep infinity\n' > /etc/s6/openssh/run && chmod 755 /etc/s6/openssh/run
ENV USER=git
ENV GITEA_CUSTOM=/data/gitea
+6 -6
View File
@@ -11,14 +11,14 @@ Custom Gitea fork with Project Board API
## Pages
- [Branding](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Branding)
- [Deployment](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Deployment)
- [Branding](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Branding)
- [Deployment](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/Deployment)
- [Project API](Project API)
- [roadmap](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/roadmap)
- [roadmap](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki/roadmap)
---
**Category:** Infrastructure | **Platform:** [moko-platform wiki](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)
**Category:** Infrastructure | **Platform:** [moko-platform wiki](https://code.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)
---
@@ -28,7 +28,7 @@ Custom Gitea fork with Project Board API
## Documentation
Full documentation is available on the [Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki).
Full documentation is available on the [Wiki](https://code.mokoconsulting.tech/MokoConsulting/MokoGitea/wiki).
## Contributing
@@ -40,4 +40,4 @@ This project is licensed under the GNU General Public License v3.0 or later -- s
---
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://code.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
+237
View File
@@ -0,0 +1,237 @@
#!/usr/bin/env bash
# ============================================================================
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Automation.CI
# INGROUP: moko-platform.Automation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /automation/ci-issue-reporter.sh
# VERSION: 09.23.00
# BRIEF: Creates or updates a Gitea issue when a CI gate fails.
# Deduplicates by searching open issues with the "ci-auto" label
# whose title matches the gate. If a matching issue exists, a comment
# is appended instead of opening a duplicate.
# ============================================================================
set -euo pipefail
# ── Defaults ────────────────────────────────────────────────────────────────
GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}"
GITEA_TOKEN="${GITEA_TOKEN:-}"
REPO="${GITHUB_REPOSITORY:-}"
RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
LABEL_NAME="ci-auto"
LABEL_COLOR="#e11d48"
GATE=""
DETAILS=""
SEVERITY="error"
WORKFLOW=""
# ── Parse arguments ─────────────────────────────────────────────────────────
usage() {
cat <<EOF
Usage: ci-issue-reporter.sh --gate NAME --details TEXT [OPTIONS]
Required:
--gate CI gate name (e.g. "Code Quality", "Self-Health")
--details Human-readable failure description
Optional:
--severity "error" (default) or "warning"
--workflow Workflow name for the issue title
--repo owner/repo (default: \$GITHUB_REPOSITORY)
--run-url URL to the CI run (auto-detected from env)
--token Gitea API token (default: \$GITEA_TOKEN)
--url Gitea base URL (default: \$GITEA_URL)
EOF
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--gate) GATE="$2"; shift 2 ;;
--details) DETAILS="$2"; shift 2 ;;
--severity) SEVERITY="$2"; shift 2 ;;
--workflow) WORKFLOW="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--run-url) RUN_URL="$2"; shift 2 ;;
--token) GITEA_TOKEN="$2"; shift 2 ;;
--url) GITEA_URL="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
done
[[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
[[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
[[ -z "$GITEA_TOKEN" ]] && { echo "ERROR: GITEA_TOKEN not set"; exit 1; }
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
API="${GITEA_URL}/api/v1/repos/${REPO}"
# ── Build title ─────────────────────────────────────────────────────────────
if [[ -n "$WORKFLOW" ]]; then
TITLE="[CI] ${WORKFLOW}: ${GATE} failed"
else
TITLE="[CI] ${GATE} failed"
fi
# ── Ensure label exists ─────────────────────────────────────────────────────
ensure_label() {
local exists
exists=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null || echo "000")
if [[ "$exists" == "200" ]]; then
# Check if label already exists
local found
found=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null \
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
if [[ -z "$found" ]]; then
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/labels" \
-d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
> /dev/null 2>&1 || true
fi
fi
}
# ── Search for existing open issue ──────────────────────────────────────────
find_existing_issue() {
# URL-encode the gate name for the query
local query
query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g')
local response
response=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
2>/dev/null || echo "[]")
# Extract the first matching issue number
echo "$response" \
| grep -oP '"number":\s*\K[0-9]+' \
| head -1
}
# ── Build issue body ────────────────────────────────────────────────────────
build_body() {
local severity_badge
if [[ "$SEVERITY" == "error" ]]; then
severity_badge="**Severity:** Error"
else
severity_badge="**Severity:** Warning"
fi
cat <<BODY
## CI Gate Failure: ${GATE}
${severity_badge}
**Workflow:** ${WORKFLOW:-unknown}
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
### Details
${DETAILS}
### Resolution
Fix the issue described above and push a new commit. This issue will be closed automatically when the gate passes, or can be closed manually.
---
*Auto-created by [ci-issue-reporter](${GITEA_URL}/${REPO}/src/branch/main/automation/ci-issue-reporter.sh)*
BODY
}
# ── Build comment body (for existing issues) ────────────────────────────────
build_comment() {
cat <<COMMENT
### CI failure recurrence
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
${DETAILS}
COMMENT
}
# ── Main ────────────────────────────────────────────────────────────────────
ensure_label
EXISTING=$(find_existing_issue)
if [[ -n "$EXISTING" ]]; then
# Append comment to existing issue
COMMENT_BODY=$(build_comment)
COMMENT_JSON=$(printf '%s' "$COMMENT_BODY" | python3 -c "
import sys, json
print(json.dumps({'body': sys.stdin.read()}))" 2>/dev/null)
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${EXISTING}/comments" \
-d "${COMMENT_JSON}" 2>/dev/null || echo "000")
if [[ "$HTTP" == "201" ]]; then
echo "Commented on existing issue #${EXISTING}"
else
echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})"
fi
else
# Create new issue
ISSUE_BODY=$(build_body)
ISSUE_JSON=$(python3 -c "
import sys, json
body = sys.stdin.read()
print(json.dumps({
'title': sys.argv[1],
'body': body,
'labels': []
}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
# Create the issue
RESPONSE=$(curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues" \
-d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1)
if [[ -n "$ISSUE_NUM" ]]; then
# Apply label (separate call — more reliable across Gitea versions)
LABEL_ID=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null \
| grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
| head -1 || true)
if [[ -n "$LABEL_ID" ]]; then
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${ISSUE_NUM}/labels" \
-d "{\"labels\":[${LABEL_ID}]}" \
> /dev/null 2>&1 || true
fi
echo "Created issue #${ISSUE_NUM}: ${TITLE}"
else
echo "WARNING: Failed to create issue"
echo "Response: ${RESPONSE}"
fi
fi
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
)
func main() {
+1 -1
View File
@@ -20,7 +20,7 @@ import (
"strings"
"unicode/utf8"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
)
const (
+1 -1
View File
@@ -15,7 +15,7 @@ import (
"path/filepath"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
)
func main() {
+1 -1
View File
@@ -30,7 +30,7 @@ var primaryLicenseRe = regexp.MustCompile(`^(?i)(LICEN[SC]E|COPYING)$`)
// ignoredNames are LicenseEntry.Name values to exclude from the output.
var ignoredNames = map[string]bool{
"code.gitea.io/gitea": true,
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/options/license": true,
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/options/license": true,
}
var excludedExt = map[string]bool{
+10 -5
View File
@@ -25,7 +25,7 @@ import (
"sort"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/build/openapi3gen"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/build/openapi3gen"
"github.com/getkin/kin-openapi/openapi3"
)
@@ -34,16 +34,19 @@ const (
swaggerSpecPath = "templates/swagger/v1_json.tmpl"
openapi3OutPath = "templates/swagger/v1_openapi3_json.tmpl"
appSubUrlVar = "{{.SwaggerAppSubUrl}}"
appVerVar = "{{.SwaggerAppVer}}"
appSubUrlVar = "{{.SwaggerAppSubUrl}}"
appVerVar = "{{.SwaggerAppVer}}"
appNameVar = "{{.SwaggerAppName}}"
appSubUrlPlaceholder = "GITEA_APP_SUB_URL_PLACEHOLDER"
appVerPlaceholder = "0.0.0-gitea-placeholder"
appSubUrlPlaceholder = "GITEA_APP_SUB_URL_PLACEHOLDER"
appVerPlaceholder = "0.0.0-gitea-placeholder"
appNamePlaceholder = "GiteaAppNamePlaceholder"
)
var (
appSubUrlRe = regexp.MustCompile(regexp.QuoteMeta(appSubUrlVar))
appVerRe = regexp.MustCompile(regexp.QuoteMeta(appVerVar))
appNameRe = regexp.MustCompile(regexp.QuoteMeta(appNameVar))
enumScanDirs = []string{
"modules/structs",
@@ -70,6 +73,7 @@ func main() {
cleaned := appSubUrlRe.ReplaceAll(data, []byte(appSubUrlPlaceholder))
cleaned = appVerRe.ReplaceAll(cleaned, []byte(appVerPlaceholder))
cleaned = appNameRe.ReplaceAll(cleaned, []byte(appNamePlaceholder))
oas3, err := openapi3gen.Convert(cleaned, astEnumMap)
if err != nil {
@@ -87,6 +91,7 @@ func main() {
result := strings.ReplaceAll(string(out), appSubUrlPlaceholder, appSubUrlVar)
result = strings.ReplaceAll(result, appVerPlaceholder, appVerVar)
result = strings.ReplaceAll(result, appNamePlaceholder, appNameVar)
result = strings.TrimSpace(result)
if err := os.WriteFile(openapi3OutPath, []byte(result), 0o644); err != nil {
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"regexp"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"github.com/getkin/kin-openapi/openapi2"
"github.com/getkin/kin-openapi/openapi2conv"
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+6 -6
View File
@@ -8,12 +8,12 @@ import (
"context"
"fmt"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/gitrepo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
repo_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/gitrepo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -10,9 +10,9 @@ import (
"os"
"text/tabwriter"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
auth_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
auth_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"fmt"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"context"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/ldap"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"fmt"
"net/url"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/oauth2"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"errors"
"strings"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/auth/source/smtp"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -6,9 +6,9 @@ package cmd
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
asymkey_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/asymkey"
repo_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
asymkey_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/asymkey"
repo_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/repository"
"github.com/urfave/cli/v3"
)
+5 -5
View File
@@ -8,11 +8,11 @@ import (
"errors"
"fmt"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
user_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"io"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+6 -6
View File
@@ -9,12 +9,12 @@ import (
"fmt"
"strings"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
pwd "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
pwd "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/auth/password"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"strings"
"testing"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+4 -4
View File
@@ -9,10 +9,10 @@ import (
"fmt"
"strings"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
user_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
user_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/user"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -8,10 +8,10 @@ import (
"strings"
"testing"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/require"
)
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"errors"
"fmt"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"os"
"text/tabwriter"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -8,8 +8,8 @@ import (
"errors"
"fmt"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+3 -3
View File
@@ -6,9 +6,9 @@ package cmd
import (
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+5 -5
View File
@@ -15,11 +15,11 @@ import (
"strings"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/cmd"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/cmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+7 -7
View File
@@ -12,13 +12,13 @@ import (
"strings"
"text/tabwriter"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations"
migrate_base "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations/base"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations"
migrate_base "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/migrations/base"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"github.com/urfave/cli/v3"
"xorm.io/xorm"
+3 -3
View File
@@ -7,9 +7,9 @@ import (
"context"
"fmt"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/doctor"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+7 -7
View File
@@ -11,13 +11,13 @@ import (
"path/filepath"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/dump"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/dump"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"gitea.com/go-chi/session"
"github.com/urfave/cli/v3"
+8 -8
View File
@@ -10,14 +10,14 @@ import (
"os"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
base "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/migration"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/convert"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/migrations"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
base "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/migration"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/convert"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/migrations"
"github.com/urfave/cli/v3"
)
+8 -8
View File
@@ -11,14 +11,14 @@ import (
"path/filepath"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/glob"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/options"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/public"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/assetfs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/glob"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/options"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/public"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"fmt"
"os"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/generate"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/generate"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v3"
+3 -3
View File
@@ -15,9 +15,9 @@ import (
"strings"
"syscall"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+6 -6
View File
@@ -14,12 +14,12 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/gitcmd"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
repo_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/gitcmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"fmt"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"fmt"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -10,8 +10,8 @@ import (
"os"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"context"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/urfave/cli/v3"
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+2 -2
View File
@@ -9,8 +9,8 @@ import (
"fmt"
"os"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -6,10 +6,10 @@ package cmd
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
"github.com/urfave/cli/v3"
)
+11 -11
View File
@@ -10,17 +10,17 @@ import (
"io/fs"
"strings"
actions_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/actions"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
git_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
packages_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
packages_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
actions_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/actions"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
git_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
packages_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/versioned_migration"
"github.com/urfave/cli/v3"
)
+7 -7
View File
@@ -8,13 +8,13 @@ import (
"strings"
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
packages_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
packages_service "git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
packages_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/packages"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage"
packages_service "code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/packages"
"github.com/stretchr/testify/assert"
)
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/urfave/cli/v3"
)
+15 -15
View File
@@ -15,21 +15,21 @@ import (
"strings"
"unicode"
asymkey_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/asymkey"
git_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/perm"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/gitcmd"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/lfstransfer"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/pprof"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
repo_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/services/lfs"
asymkey_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/asymkey"
git_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/perm"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git/gitcmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/lfstransfer"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/pprof"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/private"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
repo_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/repository"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/services/lfs"
"github.com/kballard/go-shellquote"
"github.com/urfave/cli/v3"
+11 -11
View File
@@ -15,17 +15,17 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/gtprof"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/public"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/routers"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/routers/install"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/gtprof"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/public"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/templates"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/routers"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/routers/install"
"github.com/felixge/fgprof"
"github.com/urfave/cli/v3"
+5 -5
View File
@@ -13,11 +13,11 @@ import (
"strconv"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/process"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"github.com/caddyserver/certmagic"
)
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"net/http/fcgi"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
)
func runHTTP(network, listenAddr, name string, m http.Handler, useProxyProtocol bool) error {
+3 -3
View File
@@ -9,9 +9,9 @@ import (
"os"
"strings"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/graceful"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"github.com/klauspost/cpuid/v2"
)
+8 -9
View File
@@ -1,6 +1,6 @@
module git.mokoconsulting.tech/MokoConsulting/MokoGitea
module code.mokoconsulting.tech/MokoConsulting/MokoGitea
go 1.26.2
go 1.26.3
// rfc5280 said: "The serial number is an integer assigned by the CA to each certificate."
// But some CAs use negative serial number, just relax the check. related:
@@ -9,6 +9,7 @@ godebug x509negativeserial=1
require (
code.gitea.io/actions-proto-go v0.4.1
code.gitea.io/gitea v1.26.2
code.gitea.io/sdk/gitea v0.24.1
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
connectrpc.com/connect v1.19.1
@@ -52,8 +53,8 @@ require (
github.com/go-chi/cors v1.2.2
github.com/go-co-op/gocron/v2 v2.19.1
github.com/go-enry/go-enry/v2 v2.9.5
github.com/go-git/go-billy/v5 v5.8.0
github.com/go-git/go-git/v5 v5.18.0
github.com/go-git/go-billy/v5 v5.9.0
github.com/go-git/go-git/v5 v5.19.0
github.com/go-ldap/ldap/v3 v3.4.13
github.com/go-redsync/redsync/v4 v4.16.0
github.com/go-sql-driver/mysql v1.9.3
@@ -242,17 +243,18 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/nwaples/rardecode/v2 v2.2.2 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/oasdiff/yaml v0.0.9 // indirect
github.com/oasdiff/yaml3 v0.0.12 // indirect
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
github.com/olekukonko/errors v1.2.0 // indirect
github.com/olekukonko/ll v0.1.8 // indirect
github.com/olekukonko/tablewriter v1.1.4 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/olivere/elastic/v7 v7.0.32 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.26 // indirect
github.com/pjbgf/sha1cd v0.5.0 // indirect
github.com/pjbgf/sha1cd v0.6.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
@@ -265,7 +267,6 @@ require (
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/skeema/knownhosts v1.3.2 // indirect
github.com/smartystreets/assertions v1.1.1 // indirect
github.com/sorairolake/lzip-go v0.3.8 // indirect
github.com/spf13/afero v1.15.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
@@ -277,7 +278,6 @@ require (
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/zeebo/assert v1.3.0 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
go.uber.org/atomic v1.11.0 // indirect
@@ -287,7 +287,6 @@ require (
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
go4.org v0.0.0-20260112195520-a5071408f32f // indirect
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
golang.org/x/mod v0.35.0 // indirect
golang.org/x/time v0.15.0 // indirect
golang.org/x/tools v0.44.0 // indirect
+14 -38
View File
@@ -2,6 +2,8 @@ cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdB
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
code.gitea.io/gitea v1.26.2 h1:i0oTSOGXnB3WLILa0lRzwi4KFIkKIEZnoyCtYiajtYY=
code.gitea.io/gitea v1.26.2/go.mod h1:K2pVuCKcxMzEl/KBD3b4GsWIOu6ZH74g8lJYiACcnsM=
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
code.gitea.io/sdk/gitea v0.24.1 h1:hpaqcdGcBmfMpV7JSbBJVwE99qo+WqGreJYKrDKEyW8=
@@ -269,6 +271,8 @@ github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w=
github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE=
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
@@ -300,12 +304,12 @@ github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5Hql
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA=
github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM=
github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo=
github.com/go-git/go-git/v5 v5.19.0 h1:+WkVUQZSy/F1Gb13udrMKjIM2PrzsNfDKFSfo5tkMtc=
github.com/go-git/go-git/v5 v5.19.0/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
@@ -326,7 +330,6 @@ github.com/go-redsync/redsync/v4 v4.16.0 h1:bNcOzeHH9d3s6pghU9NJFMPrQa41f5Nx3L4Y
github.com/go-redsync/redsync/v4 v4.16.0/go.mod h1:V4gagqgyASWBZuwx4xGzu72aZNb/6Mo05byUa3mVmKQ=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
@@ -354,12 +357,6 @@ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8J
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -373,9 +370,6 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/flatbuffers v25.12.19+incompatible h1:haMV2JRRJCe1998HeW/p0X9UaMTK6SDo0ffLn2+DbLs=
github.com/google/flatbuffers v25.12.19+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -570,7 +564,6 @@ github.com/niklasfasching/go-org v1.9.1 h1:/3s4uTPOF06pImGa2Yvlp24yKXZoTYM+nsIlM
github.com/niklasfasching/go-org v1.9.1/go.mod h1:ZAGFFkWvUQcpazmi/8nHqwvARpr1xpb+Es67oUGX/48=
github.com/nwaples/rardecode/v2 v2.2.2 h1:/5oL8dzYivRM/tqX9VcTSWfbpwcbwKG1QtSJr3b3KcU=
github.com/nwaples/rardecode/v2 v2.2.2/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oasdiff/yaml v0.0.9 h1:zQOvd2UKoozsSsAknnWoDJlSK4lC0mpmjfDsfqNwX48=
@@ -585,14 +578,13 @@ github.com/olekukonko/ll v0.1.8 h1:ysHCJRGHYKzmBSdz9w5AySztx7lG8SQY+naTGYUbsz8=
github.com/olekukonko/ll v0.1.8/go.mod h1:RPRC6UcscfFZgjo1nulkfMH5IM0QAYim0LfnMvUuozw=
github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I=
github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY=
github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E=
github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -608,8 +600,8 @@ github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU=
github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -693,7 +685,6 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@@ -801,8 +792,8 @@ golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ss
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
golang.org/x/image v0.40.0 h1:Tw4GyDXMo+daZN1znreBRC3VayR1aLFUyUEOLUdW1a8=
golang.org/x/image v0.40.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
@@ -820,9 +811,7 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -841,7 +830,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -857,16 +845,12 @@ golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -915,7 +899,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200928182047-19e03678916f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
@@ -930,12 +913,6 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401020348-3a24fdc17823/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -953,7 +930,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+8 -8
View File
@@ -10,16 +10,16 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/cmd"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/cmd"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
// register supported doc types
_ "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/asciicast"
_ "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/console"
_ "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/csv"
_ "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/markdown"
_ "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/orgmode"
_ "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/asciicast"
_ "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/console"
_ "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/csv"
_ "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/markdown"
_ "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/markup/orgmode"
"github.com/urfave/cli/v3"
)
+4 -4
View File
@@ -11,10 +11,10 @@ import (
"errors"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"xorm.io/builder"
)
+5 -5
View File
@@ -6,11 +6,11 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/perm"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/perm"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"xorm.io/xorm/convert"
)
+1 -1
View File
@@ -6,7 +6,7 @@ package actions
import (
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
)
func TestMain(m *testing.M) {
+11 -11
View File
@@ -11,17 +11,17 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
api "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
webhook_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/git"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/json"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
api "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/structs"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
webhook_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
"xorm.io/builder"
)
+5 -5
View File
@@ -9,11 +9,11 @@ import (
"slices"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
)
// ActionRunAttempt represents a single execution attempt of an ActionRun.
+3 -3
View File
@@ -6,9 +6,9 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
)
type ActionRunAttemptList []*ActionRunAttempt
+5 -6
View File
@@ -9,18 +9,17 @@ import (
"slices"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/actions/jobparser"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/actions/jobparser"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"xorm.io/builder"
)
// MaxJobNumPerRun is the maximum number of jobs in a single run.
// https://docs.github.com/en/actions/reference/limits#existing-system-limits
// TODO: check this limit when creating jobs
const MaxJobNumPerRun = 256
// ActionRunJob represents a job of a run
+5 -5
View File
@@ -6,11 +6,11 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"xorm.io/builder"
)
+6 -6
View File
@@ -6,12 +6,12 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
webhook_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
webhook_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
"xorm.io/builder"
)
+4 -4
View File
@@ -7,10 +7,10 @@ import (
"testing"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"github.com/stretchr/testify/assert"
)
+10 -10
View File
@@ -10,16 +10,16 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/shared/types"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/shared/types"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/optional"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
"xorm.io/builder"
+4 -4
View File
@@ -6,10 +6,10 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
)
type RunnerList []*ActionRunner
+5 -5
View File
@@ -7,11 +7,11 @@ import (
"context"
"fmt"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
)
// ActionRunnerToken represents runner tokens
+1 -1
View File
@@ -6,7 +6,7 @@ package actions
import (
"testing"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unittest"
"github.com/stretchr/testify/assert"
)
+6 -6
View File
@@ -8,12 +8,12 @@ import (
"fmt"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
webhook_module "git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
webhook_module "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/webhook"
)
// ActionSchedule represents a schedule of a workflow file
+1 -1
View File
@@ -4,7 +4,7 @@
package actions
import (
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"xorm.io/builder"
)
+3 -3
View File
@@ -8,9 +8,9 @@ import (
"strings"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"github.com/robfig/cron/v3"
)
+3 -3
View File
@@ -6,9 +6,9 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"xorm.io/builder"
)
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"testing"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
+1 -1
View File
@@ -6,7 +6,7 @@ package actions
import (
"slices"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/translation"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
)
+8 -8
View File
@@ -11,14 +11,14 @@ import (
"strings"
"time"
auth_model "git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unit"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/actions/jobparser"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
auth_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/auth"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unit"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/actions/jobparser"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/util"
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
lru "github.com/hashicorp/golang-lru/v2"
+3 -3
View File
@@ -6,9 +6,9 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/container"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"xorm.io/builder"
)
+1 -1
View File
@@ -6,7 +6,7 @@ package actions
import (
"context"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
)
// ActionTaskOutput represents an output of ActionTask.
+2 -2
View File
@@ -7,8 +7,8 @@ import (
"context"
"time"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"git.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db"
"code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil"
)
// ActionTaskStep represents a step of ActionTask

Some files were not shown because too many files have changed in this diff Show More