From 774ea3842b54851460182be933a812ff569a46fb Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:09:31 -0500 Subject: [PATCH 1/6] 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) --- templates/org/licenses.tmpl | 6 ++++-- templates/repo/licenses.tmpl | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/templates/org/licenses.tmpl b/templates/org/licenses.tmpl index 27fbc82a85..70aedc2666 100644 --- a/templates/org/licenses.tmpl +++ b/templates/org/licenses.tmpl @@ -149,8 +149,10 @@
-
- +
+
+ +
{{if .SearchQuery}}{{ctx.Locale.Tr "repo.licenses.clear_search"}}{{end}}
diff --git a/templates/repo/licenses.tmpl b/templates/repo/licenses.tmpl index a0b7a710c6..b086e98d49 100644 --- a/templates/repo/licenses.tmpl +++ b/templates/repo/licenses.tmpl @@ -155,8 +155,10 @@
-
- +
+
+ +
{{if .SearchQuery}}{{ctx.Locale.Tr "repo.licenses.clear_search"}}{{end}}
-- 2.52.0 From 3e31b662a694b04063c26861becd9fae10fefdbe Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:12:13 -0500 Subject: [PATCH 2/6] fix(licenses): remove UNIQUE constraint on PaymentRef, use tw-max-w-lg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- models/licenses/license_key.go | 2 +- models/migrations/v1_27/v340.go | 2 +- templates/org/licenses.tmpl | 2 +- templates/repo/licenses.tmpl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/models/licenses/license_key.go b/models/licenses/license_key.go index 13ef323b9f..5344e660a0 100644 --- a/models/licenses/license_key.go +++ b/models/licenses/license_key.go @@ -33,7 +33,7 @@ type LicenseKey struct { LicenseeEmail string `xorm:""` // customer email DomainRestriction string `xorm:"TEXT"` // comma-separated allowed domains MaxSites int `xorm:"NOT NULL DEFAULT 0"` // 0 = use package default - PaymentRef string `xorm:"UNIQUE"` // idempotency key from payment system + PaymentRef string `xorm:""` // idempotency key from payment system IsInternal bool `xorm:"NOT NULL DEFAULT false"` // true = base org/repo key IsActive bool `xorm:"NOT NULL DEFAULT true"` StartsUnix timeutil.TimeStamp `xorm:"NOT NULL DEFAULT 0"` // custom start, 0 = creation diff --git a/models/migrations/v1_27/v340.go b/models/migrations/v1_27/v340.go index 1f26764e00..3502f063b9 100644 --- a/models/migrations/v1_27/v340.go +++ b/models/migrations/v1_27/v340.go @@ -13,7 +13,7 @@ import ( type licenseKey340 struct { ID int64 `xorm:"pk autoincr"` KeyRaw string `xorm:"TEXT"` - PaymentRef string `xorm:"UNIQUE"` + PaymentRef string `xorm:""` LastHeartbeatUnix timeutil.TimeStamp `xorm:"NOT NULL DEFAULT 0"` FirstUsedUnix timeutil.TimeStamp `xorm:"NOT NULL DEFAULT 0"` } diff --git a/templates/org/licenses.tmpl b/templates/org/licenses.tmpl index 70aedc2666..ef0ae1da53 100644 --- a/templates/org/licenses.tmpl +++ b/templates/org/licenses.tmpl @@ -149,7 +149,7 @@
-
+
diff --git a/templates/repo/licenses.tmpl b/templates/repo/licenses.tmpl index b086e98d49..4e4e028d43 100644 --- a/templates/repo/licenses.tmpl +++ b/templates/repo/licenses.tmpl @@ -155,7 +155,7 @@
-
+
-- 2.52.0 From 0a3cd3115fdba4e0bda256215e6e5069f6ffddad Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:21:02 -0500 Subject: [PATCH 3/6] 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) --- models/licenses/update_stream_config.go | 12 +++++++++++- routers/web/repo/changelog_xml.go | 6 ++++++ services/updateserver/dolibarr.go | 6 ++++++ services/updateserver/joomla.go | 19 +++++++++++++++++++ services/updateserver/wordpress.go | 6 ++++++ 5 files changed, 48 insertions(+), 1 deletion(-) diff --git a/models/licenses/update_stream_config.go b/models/licenses/update_stream_config.go index a411416507..ed63f52467 100644 --- a/models/licenses/update_stream_config.go +++ b/models/licenses/update_stream_config.go @@ -171,10 +171,20 @@ func SaveConfig(ctx context.Context, cfg *UpdateStreamConfig) error { } // MatchStreamFromTag determines which stream a tag belongs to based on the given stream definitions. +// Supports two conventions: +// - Stream-name tags: tag IS the stream name (e.g. "stable", "release-candidate", "development") +// - Version tags: tag contains a version + optional suffix (e.g. "v1.0.0", "v1.0.0-rc1") func MatchStreamFromTag(tagName string, isPrerelease bool, streams []StreamDef) string { lower := strings.ToLower(tagName) - // Check custom suffixes (longest match first to avoid "-rc" matching before "-rc-special"). + // First: check if the tag name directly matches a stream name (stream-name convention). + for _, s := range streams { + if strings.EqualFold(s.Name, tagName) { + return s.Name + } + } + + // Second: check suffixes in the tag (version-tag convention, longest match first). var bestMatch string bestLen := 0 for _, s := range streams { diff --git a/routers/web/repo/changelog_xml.go b/routers/web/repo/changelog_xml.go index 3f56b0e005..dc054919f8 100644 --- a/routers/web/repo/changelog_xml.go +++ b/routers/web/repo/changelog_xml.go @@ -77,6 +77,12 @@ func ServeChangelogXML(ctx *context.Context) { } version := extractVersionFromTag(rel.TagName) + // If the tag is a stream name, try the release title for the version. + if version == rel.TagName && (version == "stable" || version == "release-candidate" || version == "beta" || version == "alpha" || version == "development") { + if titleVer := extractVersionFromTag(rel.Title); titleVer != "" { + version = titleVer + } + } cl := xmlChangelog{ Element: element, Type: extType, diff --git a/services/updateserver/dolibarr.go b/services/updateserver/dolibarr.go index c31a517275..a7ef546a59 100644 --- a/services/updateserver/dolibarr.go +++ b/services/updateserver/dolibarr.go @@ -108,6 +108,12 @@ func GenerateDolibarrJSON(ctx context.Context, repo *repo_model.Repository, allo } version := extractVersion(rel.TagName) + if isStreamName(version, streams) { + version = extractVersion(rel.Title) + } + if version == "" { + version = rel.TagName + } suffix := stream.Suffix if suffix == "" { suffix = channelSuffix(ch) diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index 808f644887..45c7b9cbad 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -107,6 +107,17 @@ func channelFromTag(tagName string, isPrerelease bool) string { } } +// isStreamName checks if a string matches any stream name (indicating the tag +// is a stream name, not a version number). +func isStreamName(s string, streams []licenses.StreamDef) bool { + for _, st := range streams { + if strings.EqualFold(st.Name, s) { + return true + } + } + return false +} + // joomlaTagName maps internal stream names to Joomla-standard tag values. // Joomla recognizes: dev, alpha, beta, rc, stable. func joomlaTagName(channel string) string { @@ -273,6 +284,14 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require } version := extractVersion(rel.TagName) + // If the tag is a stream name (not a version), try the release title instead. + if isStreamName(version, streams) { + version = extractVersion(rel.Title) + } + // Last resort: use the tag name as-is. + if version == "" { + version = rel.TagName + } suffix := stream.Suffix if suffix == "" { suffix = channelSuffix(ch) // fallback for Joomla defaults diff --git a/services/updateserver/wordpress.go b/services/updateserver/wordpress.go index 9fb469252d..c6f961ec88 100644 --- a/services/updateserver/wordpress.go +++ b/services/updateserver/wordpress.go @@ -139,6 +139,12 @@ func GenerateWordPressJSON(ctx context.Context, repo *repo_model.Repository, lic } version := extractVersion(latestStable.TagName) + if isStreamName(version, streams) { + version = extractVersion(latestStable.Title) + } + if version == "" { + version = latestStable.TagName + } lastUpdated := time.Unix(int64(latestStable.CreatedUnix), 0).Format("2006-01-02 3:04pm MST") // Build sections from release notes. -- 2.52.0 From ce3af35c40414caa80c1485288db6a4c0c0534ab Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:27:06 -0500 Subject: [PATCH 4/6] 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) --- services/updateserver/joomla.go | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index 45c7b9cbad..a9b8749cb4 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -8,6 +8,7 @@ import ( "encoding/xml" "fmt" "io" + "regexp" "strings" "time" @@ -359,20 +360,35 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require return append([]byte(xml.Header), output...), nil } -// extractVersion strips common tag prefixes (v, release-, etc.) to get the version. -func extractVersion(tagName string) string { - v := tagName +// versionRegex matches semantic version patterns like 1.0.0, 02.29.04, etc. +var versionRegex = regexp.MustCompile(`(\d+\.\d+(?:\.\d+)?)`) + +// extractVersion finds a version number from a tag name or release title. +// Tries: (1) strip common prefixes for version-style tags, (2) regex match for embedded versions. +func extractVersion(s string) string { + // Try prefix stripping first (works for "v1.0.0", "release-1.0.0"). + v := s v = strings.TrimPrefix(v, "v") v = strings.TrimPrefix(v, "release-") v = strings.TrimPrefix(v, "release/") - // Strip channel suffixes to get base version. + // Strip channel suffixes. for _, suffix := range []string{"-dev", "-alpha", "-beta", "-rc", "-development", "-release-candidate"} { if idx := strings.Index(strings.ToLower(v), suffix); idx > 0 { v = v[:idx] break } } - return v + // If result looks like a version (starts with digit), use it. + if len(v) > 0 && v[0] >= '0' && v[0] <= '9' { + return strings.TrimSpace(v) + } + + // Fallback: extract version pattern from anywhere in the string. + if m := versionRegex.FindString(s); m != "" { + return m + } + + return "" } // channelSuffix returns the version suffix for a channel. -- 2.52.0 From 2f9097a2542adfdee5ec37a3eac6ff8733015257 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:29:43 -0500 Subject: [PATCH 5/6] 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) --- services/updateserver/dolibarr.go | 2 +- services/updateserver/joomla.go | 2 +- services/updateserver/wordpress.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/updateserver/dolibarr.go b/services/updateserver/dolibarr.go index a7ef546a59..48bcc02021 100644 --- a/services/updateserver/dolibarr.go +++ b/services/updateserver/dolibarr.go @@ -108,7 +108,7 @@ func GenerateDolibarrJSON(ctx context.Context, repo *repo_model.Repository, allo } version := extractVersion(rel.TagName) - if isStreamName(version, streams) { + if version == "" || isStreamName(rel.TagName, streams) { version = extractVersion(rel.Title) } if version == "" { diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index a9b8749cb4..8f40422e79 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -286,7 +286,7 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require version := extractVersion(rel.TagName) // If the tag is a stream name (not a version), try the release title instead. - if isStreamName(version, streams) { + if version == "" || isStreamName(rel.TagName, streams) { version = extractVersion(rel.Title) } // Last resort: use the tag name as-is. diff --git a/services/updateserver/wordpress.go b/services/updateserver/wordpress.go index c6f961ec88..919e4bf8c3 100644 --- a/services/updateserver/wordpress.go +++ b/services/updateserver/wordpress.go @@ -139,7 +139,7 @@ func GenerateWordPressJSON(ctx context.Context, repo *repo_model.Repository, lic } version := extractVersion(latestStable.TagName) - if isStreamName(version, streams) { + if version == "" || isStreamName(latestStable.TagName, streams) { version = extractVersion(latestStable.Title) } if version == "" { -- 2.52.0 From 37322e42129c6dc7b522e9215484727be230e9a4 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Tue, 2 Jun 2026 07:37:02 -0500 Subject: [PATCH 6/6] feat(updates): manual release-to-stream mapping 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) --- models/licenses/release_stream_map.go | 88 +++++++++++++++++++++++++++ models/migrations/v1_27/v340.go | 17 +++++- options/locale/locale_en-US.json | 3 + routers/web/repo/release.go | 23 +++++++ services/forms/repo_form.go | 5 +- services/updateserver/dolibarr.go | 2 +- services/updateserver/joomla.go | 2 +- services/updateserver/wordpress.go | 4 +- templates/repo/release/new.tmpl | 13 ++++ 9 files changed, 149 insertions(+), 8 deletions(-) create mode 100644 models/licenses/release_stream_map.go diff --git a/models/licenses/release_stream_map.go b/models/licenses/release_stream_map.go new file mode 100644 index 0000000000..5a4a7b8e68 --- /dev/null +++ b/models/licenses/release_stream_map.go @@ -0,0 +1,88 @@ +// Copyright 2026 Moko Consulting +// SPDX-License-Identifier: GPL-3.0-or-later + +package licenses + +import ( + "context" + + "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db" + "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/timeutil" +) + +func init() { + db.RegisterModel(new(ReleaseStreamMap)) +} + +// ReleaseStreamMap manually assigns a release to an update stream. +// When present, overrides automatic stream detection from tag names. +type ReleaseStreamMap struct { + ID int64 `xorm:"pk autoincr"` + ReleaseID int64 `xorm:"UNIQUE NOT NULL INDEX"` // FK to release + RepoID int64 `xorm:"NOT NULL INDEX"` // for fast repo-scoped queries + StreamName string `xorm:"NOT NULL"` // e.g. "stable", "release-candidate" + CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` +} + +func (ReleaseStreamMap) TableName() string { + return "release_stream_map" +} + +// SetReleaseStream assigns or updates the stream for a release. +func SetReleaseStream(ctx context.Context, releaseID, repoID int64, streamName string) error { + existing := new(ReleaseStreamMap) + has, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Get(existing) + if err != nil { + return err + } + + if has { + existing.StreamName = streamName + _, err = db.GetEngine(ctx).ID(existing.ID).Cols("stream_name").Update(existing) + return err + } + + _, err = db.GetEngine(ctx).Insert(&ReleaseStreamMap{ + ReleaseID: releaseID, + RepoID: repoID, + StreamName: streamName, + }) + return err +} + +// GetReleaseStream returns the manually assigned stream for a release, or empty string. +func GetReleaseStream(ctx context.Context, releaseID int64) string { + m := new(ReleaseStreamMap) + has, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Get(m) + if err != nil || !has { + return "" + } + return m.StreamName +} + +// GetStreamMapForRepo returns all manual stream assignments for a repo. +func GetStreamMapForRepo(ctx context.Context, repoID int64) (map[int64]string, error) { + var maps []ReleaseStreamMap + if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&maps); err != nil { + return nil, err + } + result := make(map[int64]string, len(maps)) + for _, m := range maps { + result[m.ReleaseID] = m.StreamName + } + return result, nil +} + +// ResolveReleaseStream returns the stream for a release: manual mapping first, auto-detect fallback. +func ResolveReleaseStream(ctx context.Context, releaseID int64, tagName string, isPrerelease bool, streams []StreamDef) string { + if manual := GetReleaseStream(ctx, releaseID); manual != "" { + return manual + } + return MatchStreamFromTag(tagName, isPrerelease, streams) +} + +// DeleteReleaseStream removes the manual stream assignment for a release. +func DeleteReleaseStream(ctx context.Context, releaseID int64) error { + _, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Delete(new(ReleaseStreamMap)) + return err +} diff --git a/models/migrations/v1_27/v340.go b/models/migrations/v1_27/v340.go index 3502f063b9..3dc3df6e38 100644 --- a/models/migrations/v1_27/v340.go +++ b/models/migrations/v1_27/v340.go @@ -55,12 +55,25 @@ func (updateStreamConfig340) TableName() string { return "update_stream_config" } -// SyncLicenseSystemColumns adds missing columns to license_key, -// license_package, and update_stream_config tables. +// releaseStreamMap340 creates the release-to-stream manual mapping table. +type releaseStreamMap340 struct { + ID int64 `xorm:"pk autoincr"` + ReleaseID int64 `xorm:"UNIQUE NOT NULL INDEX"` + RepoID int64 `xorm:"NOT NULL INDEX"` + StreamName string `xorm:"NOT NULL"` + CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` +} + +func (releaseStreamMap340) TableName() string { + return "release_stream_map" +} + +// SyncLicenseSystemColumns adds missing columns and creates new tables. func SyncLicenseSystemColumns(x *xorm.Engine) error { return x.Sync( new(licenseKey340), new(licensePackage340), new(updateStreamConfig340), + new(releaseStreamMap340), ) } diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index ccc4e31619..1e840e6c90 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -2714,6 +2714,9 @@ "repo.settings.download_gating": "Download Gating", "repo.settings.support_url": "Support / Product Page URL", "repo.settings.support_url_help": "Shown when downloads are gated. Can point to your wiki, product page, or external support site.", + "repo.release.update_stream": "Update Stream", + "repo.release.update_stream_auto": "(auto-detect from tag name)", + "repo.release.update_stream_help": "Assign this release to an update stream. The update feed will serve the latest release per stream.", "repo.release.downloads_require_login": "Sign in to download release files.", "repo.settings.extension_metadata": "Extension Metadata", "repo.settings.extension_metadata_desc": "Override the org-level extension metadata for this repository. Empty fields inherit from the organization settings.", diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 22a15913c0..6f7484112a 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -14,6 +14,7 @@ import ( "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db" git_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/git" + licenses_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/licenses" "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/renderhelper" repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo" "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/unit" @@ -355,6 +356,17 @@ func newReleaseCommon(ctx *context.Context) { upload.AddUploadContext(ctx, "release") + // Load available streams for the stream selector (when licensing enabled). + if ctx.Data["LicensingEnabled"] == true { + ownerID := ctx.Repo.Repository.OwnerID + orgCfg, _ := licenses_model.GetOrgConfig(ctx, ownerID) + if orgCfg != nil { + ctx.Data["AvailableStreams"] = orgCfg.GetActiveStreams() + } else { + ctx.Data["AvailableStreams"] = licenses_model.DefaultJoomlaStreams() + } + } + PrepareBranchList(ctx) // for New Release page } @@ -520,6 +532,10 @@ func NewReleasePost(ctx *context.Context) { handleTagReleaseError(err) return } + // Save manual stream assignment if specified. + if streamName := form.UpdateStream; streamName != "" { + _ = licenses_model.SetReleaseStream(ctx, rel.ID, rel.RepoID, streamName) + } ctx.Redirect(ctx.Repo.RepoLink + "/releases") return } @@ -580,6 +596,7 @@ func EditRelease(ctx *context.Context) { ctx.Data["content"] = rel.Note ctx.Data["prerelease"] = rel.IsPrerelease ctx.Data["IsDraft"] = rel.IsDraft + ctx.Data["ReleaseStream"] = licenses_model.GetReleaseStream(ctx, rel.ID) rel.Repo = ctx.Repo.Repository if err := rel.LoadAttributes(ctx); err != nil { @@ -660,6 +677,12 @@ func EditReleasePost(ctx *context.Context) { ctx.ServerError("UpdateRelease", err) return } + // Save manual stream assignment. + if streamName := form.UpdateStream; streamName != "" { + _ = licenses_model.SetReleaseStream(ctx, rel.ID, rel.RepoID, streamName) + } else { + _ = licenses_model.DeleteReleaseStream(ctx, rel.ID) + } ctx.Redirect(ctx.Repo.RepoLink + "/releases") } diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index f8b4cce9c5..7216850633 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -670,8 +670,9 @@ type NewReleaseForm struct { Draft bool TagOnly bool Prerelease bool - AddTagMsg bool - Files []string + AddTagMsg bool + Files []string + UpdateStream string } // Validate validates the fields diff --git a/services/updateserver/dolibarr.go b/services/updateserver/dolibarr.go index 48bcc02021..d93c68a6ac 100644 --- a/services/updateserver/dolibarr.go +++ b/services/updateserver/dolibarr.go @@ -67,7 +67,7 @@ func GenerateDolibarrJSON(ctx context.Context, repo *repo_model.Repository, allo if rel.IsDraft || rel.IsTag { continue } - ch := licenses.MatchStreamFromTag(rel.TagName, rel.IsPrerelease, streams) + ch := licenses.ResolveReleaseStream(ctx, rel.ID, rel.TagName, rel.IsPrerelease, streams) existing, ok := bestByChannel[ch] if !ok || rel.CreatedUnix > existing.CreatedUnix { bestByChannel[ch] = rel diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index 8f40422e79..2513b7bc47 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -227,7 +227,7 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require if rel.IsDraft || rel.IsTag { continue } - ch := licenses.MatchStreamFromTag(rel.TagName, rel.IsPrerelease, streams) + ch := licenses.ResolveReleaseStream(ctx, rel.ID, rel.TagName, rel.IsPrerelease, streams) existing, ok := bestByChannel[ch] if !ok || rel.CreatedUnix > existing.CreatedUnix { bestByChannel[ch] = rel diff --git a/services/updateserver/wordpress.go b/services/updateserver/wordpress.go index 919e4bf8c3..cf245ab068 100644 --- a/services/updateserver/wordpress.go +++ b/services/updateserver/wordpress.go @@ -96,7 +96,7 @@ func GenerateWordPressJSON(ctx context.Context, repo *repo_model.Repository, lic if rel.IsDraft || rel.IsTag { continue } - ch := licenses.MatchStreamFromTag(rel.TagName, rel.IsPrerelease, streams) + ch := licenses.ResolveReleaseStream(ctx, rel.ID, rel.TagName, rel.IsPrerelease, streams) if ch == "stable" { if latestStable == nil || rel.CreatedUnix > latestStable.CreatedUnix { latestStable = rel @@ -184,7 +184,7 @@ func buildWordPressChangelog(releases []*repo_model.Release, streams []licenses. if rel.IsDraft || rel.IsTag || rel.Note == "" { continue } - ch := licenses.MatchStreamFromTag(rel.TagName, rel.IsPrerelease, streams) + ch := licenses.ResolveReleaseStream(ctx, rel.ID, rel.TagName, rel.IsPrerelease, streams) if ch != "stable" { continue } diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl index cc73bdf13c..d23e103c3d 100644 --- a/templates/repo/release/new.tmpl +++ b/templates/repo/release/new.tmpl @@ -117,6 +117,19 @@
{{ctx.Locale.Tr "repo.release.prerelease_helper"}}
+ {{if .LicensingEnabled}} +
+ + +
{{ctx.Locale.Tr "repo.release.update_stream_help"}}
+
+ {{end}} +
{{if .PageIsEditRelease}} -- 2.52.0