summaryrefslogtreecommitdiffstats
path: root/routers/web/repo/badges
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--routers/web/repo/badges/badges.go164
1 files changed, 164 insertions, 0 deletions
diff --git a/routers/web/repo/badges/badges.go b/routers/web/repo/badges/badges.go
new file mode 100644
index 0000000..a2306d5
--- /dev/null
+++ b/routers/web/repo/badges/badges.go
@@ -0,0 +1,164 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package badges
+
+import (
+ "fmt"
+ "net/url"
+ "strings"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
+ "code.gitea.io/gitea/modules/setting"
+ context_module "code.gitea.io/gitea/services/context"
+)
+
+func getBadgeURL(ctx *context_module.Context, label, text, color string) string {
+ sb := &strings.Builder{}
+ _ = setting.Badges.GeneratorURLTemplateTemplate.Execute(sb, map[string]string{
+ "label": url.PathEscape(strings.ReplaceAll(label, "-", "--")),
+ "text": url.PathEscape(strings.ReplaceAll(text, "-", "--")),
+ "color": url.PathEscape(color),
+ })
+
+ badgeURL := sb.String()
+ q := ctx.Req.URL.Query()
+ // Remove any `branch` or `event` query parameters. They're used by the
+ // workflow badge route, and do not need forwarding to the badge generator.
+ delete(q, "branch")
+ delete(q, "event")
+ if len(q) > 0 {
+ return fmt.Sprintf("%s?%s", badgeURL, q.Encode())
+ }
+ return badgeURL
+}
+
+func redirectToBadge(ctx *context_module.Context, label, text, color string) {
+ ctx.Redirect(getBadgeURL(ctx, label, text, color))
+}
+
+func errorBadge(ctx *context_module.Context, label, text string) { //nolint:unparam
+ ctx.Redirect(getBadgeURL(ctx, label, text, "crimson"))
+}
+
+func GetWorkflowBadge(ctx *context_module.Context) {
+ branch := ctx.Req.URL.Query().Get("branch")
+ if branch != "" {
+ branch = fmt.Sprintf("refs/heads/%s", branch)
+ }
+ event := ctx.Req.URL.Query().Get("event")
+
+ workflowFile := ctx.Params("workflow_name")
+ run, err := actions_model.GetLatestRunForBranchAndWorkflow(ctx, ctx.Repo.Repository.ID, branch, workflowFile, event)
+ if err != nil {
+ errorBadge(ctx, workflowFile, "Not found")
+ return
+ }
+
+ var color string
+ switch run.Status {
+ case actions_model.StatusUnknown:
+ color = "lightgrey"
+ case actions_model.StatusWaiting:
+ color = "lightgrey"
+ case actions_model.StatusRunning:
+ color = "gold"
+ case actions_model.StatusSuccess:
+ color = "brightgreen"
+ case actions_model.StatusFailure:
+ color = "crimson"
+ case actions_model.StatusCancelled:
+ color = "orange"
+ case actions_model.StatusSkipped:
+ color = "blue"
+ case actions_model.StatusBlocked:
+ color = "yellow"
+ default:
+ color = "lightgrey"
+ }
+
+ redirectToBadge(ctx, workflowFile, run.Status.String(), color)
+}
+
+func getIssueOrPullBadge(ctx *context_module.Context, label, variant string, num int) {
+ var text string
+ if len(variant) > 0 {
+ text = fmt.Sprintf("%d %s", num, variant)
+ } else {
+ text = fmt.Sprintf("%d", num)
+ }
+ redirectToBadge(ctx, label, text, "blue")
+}
+
+func getIssueBadge(ctx *context_module.Context, variant string, num int) {
+ if !ctx.Repo.CanRead(unit.TypeIssues) &&
+ !ctx.Repo.CanRead(unit.TypeExternalTracker) {
+ errorBadge(ctx, "issues", "Not found")
+ return
+ }
+
+ _, err := ctx.Repo.Repository.GetUnit(ctx, unit.TypeExternalTracker)
+ if err == nil {
+ errorBadge(ctx, "issues", "Not found")
+ return
+ }
+
+ getIssueOrPullBadge(ctx, "issues", variant, num)
+}
+
+func getPullBadge(ctx *context_module.Context, variant string, num int) {
+ if !ctx.Repo.Repository.CanEnablePulls() || !ctx.Repo.CanRead(unit.TypePullRequests) {
+ errorBadge(ctx, "pulls", "Not found")
+ return
+ }
+
+ getIssueOrPullBadge(ctx, "pulls", variant, num)
+}
+
+func GetOpenIssuesBadge(ctx *context_module.Context) {
+ getIssueBadge(ctx, "open", ctx.Repo.Repository.NumOpenIssues)
+}
+
+func GetClosedIssuesBadge(ctx *context_module.Context) {
+ getIssueBadge(ctx, "closed", ctx.Repo.Repository.NumClosedIssues)
+}
+
+func GetTotalIssuesBadge(ctx *context_module.Context) {
+ getIssueBadge(ctx, "", ctx.Repo.Repository.NumIssues)
+}
+
+func GetOpenPullsBadge(ctx *context_module.Context) {
+ getPullBadge(ctx, "open", ctx.Repo.Repository.NumOpenPulls)
+}
+
+func GetClosedPullsBadge(ctx *context_module.Context) {
+ getPullBadge(ctx, "closed", ctx.Repo.Repository.NumClosedPulls)
+}
+
+func GetTotalPullsBadge(ctx *context_module.Context) {
+ getPullBadge(ctx, "", ctx.Repo.Repository.NumPulls)
+}
+
+func GetStarsBadge(ctx *context_module.Context) {
+ redirectToBadge(ctx, "stars", fmt.Sprintf("%d", ctx.Repo.Repository.NumStars), "blue")
+}
+
+func GetLatestReleaseBadge(ctx *context_module.Context) {
+ release, err := repo_model.GetLatestReleaseByRepoID(ctx, ctx.Repo.Repository.ID)
+ if err != nil {
+ if repo_model.IsErrReleaseNotExist(err) {
+ errorBadge(ctx, "release", "Not found")
+ return
+ }
+ ctx.ServerError("GetLatestReleaseByRepoID", err)
+ }
+
+ if err := release.LoadAttributes(ctx); err != nil {
+ ctx.ServerError("LoadAttributes", err)
+ return
+ }
+
+ redirectToBadge(ctx, "release", release.TagName, "blue")
+}