mirror of https://github.com/go-gitea/gitea
Implement actions badge svgs (#28102)
replace #27187 close #23688 The badge has two parts: label(workflow name) and message(action status). 5 colors are provided with 7 statuses. Color mapping: ```go var statusColorMap = map[actions_model.Status]string{ actions_model.StatusSuccess: "#4c1", // Green actions_model.StatusSkipped: "#dfb317", // Yellow actions_model.StatusUnknown: "#97ca00", // Light Green actions_model.StatusFailure: "#e05d44", // Red actions_model.StatusCancelled: "#fe7d37", // Orange actions_model.StatusWaiting: "#dfb317", // Yellow actions_model.StatusRunning: "#dfb317", // Yellow actions_model.StatusBlocked: "#dfb317", // Yellow } ``` preview: ![1](https://github.com/go-gitea/gitea/assets/70063547/5465cbaf-23cd-4437-9848-2738c3cb8985) ![2](https://github.com/go-gitea/gitea/assets/70063547/ec393d26-c6e6-4d38-b72c-51f2494c5e71) ![3](https://github.com/go-gitea/gitea/assets/70063547/3edb4fdf-1b08-4a02-ab2a-6bdd7f532fb2) ![4](https://github.com/go-gitea/gitea/assets/70063547/8c189de2-2169-4251-b115-0e39a52f3df8) ![5](https://github.com/go-gitea/gitea/assets/70063547/3fe22c73-c2d7-4fec-9ea4-c501a1e4e3bd) --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io> Co-authored-by: delvh <dev.lh@web.de>pull/27183/merge
parent
e9f4c2db82
commit
db545b208b
@ -0,0 +1,37 @@ |
||||
--- |
||||
date: "2023-02-25T00:00:00+00:00" |
||||
title: "Badge" |
||||
slug: "badge" |
||||
sidebar_position: 11 |
||||
toc: false |
||||
draft: false |
||||
aliases: |
||||
- /en-us/badge |
||||
menu: |
||||
sidebar: |
||||
parent: "usage" |
||||
name: "Badge" |
||||
sidebar_position: 11 |
||||
identifier: "Badge" |
||||
--- |
||||
|
||||
# Badge |
||||
|
||||
Gitea has its builtin Badge system which allows you to display the status of your repository in other places. You can use the following badges: |
||||
|
||||
## Workflow Badge |
||||
|
||||
The Gitea Actions workflow badge is a badge that shows the status of the latest workflow run. |
||||
It is designed to be compatible with [GitHub Actions workflow badge](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/adding-a-workflow-status-badge). |
||||
|
||||
You can use the following URL to get the badge: |
||||
|
||||
``` |
||||
https://your-gitea-instance.com/{owner}/{repo}/actions/workflows/{workflow_file}?branch={branch}&event={event} |
||||
``` |
||||
|
||||
- `{owner}`: The owner of the repository. |
||||
- `{repo}`: The name of the repository. |
||||
- `{workflow_file}`: The name of the workflow file. |
||||
- `{branch}`: Optional. The branch of the workflow. Default to your repository's default branch. |
||||
- `{event}`: Optional. The event of the workflow. Default to none. |
@ -0,0 +1,104 @@ |
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package badge |
||||
|
||||
import ( |
||||
actions_model "code.gitea.io/gitea/models/actions" |
||||
) |
||||
|
||||
// The Badge layout: |offset|label|message|
|
||||
// We use 10x scale to calculate more precisely
|
||||
// Then scale down to normal size in tmpl file
|
||||
|
||||
type Label struct { |
||||
text string |
||||
width int |
||||
} |
||||
|
||||
func (l Label) Text() string { |
||||
return l.text |
||||
} |
||||
|
||||
func (l Label) Width() int { |
||||
return l.width |
||||
} |
||||
|
||||
func (l Label) TextLength() int { |
||||
return int(float64(l.width-defaultOffset) * 9.5) |
||||
} |
||||
|
||||
func (l Label) X() int { |
||||
return l.width*5 + 10 |
||||
} |
||||
|
||||
type Message struct { |
||||
text string |
||||
width int |
||||
x int |
||||
} |
||||
|
||||
func (m Message) Text() string { |
||||
return m.text |
||||
} |
||||
|
||||
func (m Message) Width() int { |
||||
return m.width |
||||
} |
||||
|
||||
func (m Message) X() int { |
||||
return m.x |
||||
} |
||||
|
||||
func (m Message) TextLength() int { |
||||
return int(float64(m.width-defaultOffset) * 9.5) |
||||
} |
||||
|
||||
type Badge struct { |
||||
Color string |
||||
FontSize int |
||||
Label Label |
||||
Message Message |
||||
} |
||||
|
||||
func (b Badge) Width() int { |
||||
return b.Label.width + b.Message.width |
||||
} |
||||
|
||||
const ( |
||||
defaultOffset = 9 |
||||
defaultFontSize = 11 |
||||
DefaultColor = "#9f9f9f" // Grey
|
||||
defaultFontWidth = 7 // approximate speculation
|
||||
) |
||||
|
||||
var StatusColorMap = map[actions_model.Status]string{ |
||||
actions_model.StatusSuccess: "#4c1", // Green
|
||||
actions_model.StatusSkipped: "#dfb317", // Yellow
|
||||
actions_model.StatusUnknown: "#97ca00", // Light Green
|
||||
actions_model.StatusFailure: "#e05d44", // Red
|
||||
actions_model.StatusCancelled: "#fe7d37", // Orange
|
||||
actions_model.StatusWaiting: "#dfb317", // Yellow
|
||||
actions_model.StatusRunning: "#dfb317", // Yellow
|
||||
actions_model.StatusBlocked: "#dfb317", // Yellow
|
||||
} |
||||
|
||||
// GenerateBadge generates badge with given template
|
||||
func GenerateBadge(label, message, color string) Badge { |
||||
lw := defaultFontWidth*len(label) + defaultOffset |
||||
mw := defaultFontWidth*len(message) + defaultOffset |
||||
x := lw*10 + mw*5 - 10 |
||||
return Badge{ |
||||
Label: Label{ |
||||
text: label, |
||||
width: lw, |
||||
}, |
||||
Message: Message{ |
||||
text: message, |
||||
width: mw, |
||||
x: x, |
||||
}, |
||||
FontSize: defaultFontSize * 10, |
||||
Color: color, |
||||
} |
||||
} |
@ -0,0 +1,56 @@ |
||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions |
||||
|
||||
import ( |
||||
"errors" |
||||
"fmt" |
||||
"net/http" |
||||
"path/filepath" |
||||
"strings" |
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions" |
||||
"code.gitea.io/gitea/modules/badge" |
||||
"code.gitea.io/gitea/modules/util" |
||||
"code.gitea.io/gitea/services/context" |
||||
) |
||||
|
||||
func GetWorkflowBadge(ctx *context.Context) { |
||||
workflowFile := ctx.Params("workflow_name") |
||||
branch := ctx.Req.URL.Query().Get("branch") |
||||
if branch == "" { |
||||
branch = ctx.Repo.Repository.DefaultBranch |
||||
} |
||||
branchRef := fmt.Sprintf("refs/heads/%s", branch) |
||||
event := ctx.Req.URL.Query().Get("event") |
||||
|
||||
badge, err := getWorkflowBadge(ctx, workflowFile, branchRef, event) |
||||
if err != nil { |
||||
ctx.ServerError("GetWorkflowBadge", err) |
||||
return |
||||
} |
||||
|
||||
ctx.Data["Badge"] = badge |
||||
ctx.RespHeader().Set("Content-Type", "image/svg+xml") |
||||
ctx.HTML(http.StatusOK, "shared/actions/runner_badge") |
||||
} |
||||
|
||||
func getWorkflowBadge(ctx *context.Context, workflowFile, branchName, event string) (badge.Badge, error) { |
||||
extension := filepath.Ext(workflowFile) |
||||
workflowName := strings.TrimSuffix(workflowFile, extension) |
||||
|
||||
run, err := actions_model.GetWorkflowLatestRun(ctx, ctx.Repo.Repository.ID, workflowFile, branchName, event) |
||||
if err != nil { |
||||
if errors.Is(err, util.ErrNotExist) { |
||||
return badge.GenerateBadge(workflowName, "no status", badge.DefaultColor), nil |
||||
} |
||||
return badge.Badge{}, err |
||||
} |
||||
|
||||
color, ok := badge.StatusColorMap[run.Status] |
||||
if !ok { |
||||
return badge.GenerateBadge(workflowName, "unknown status", badge.DefaultColor), nil |
||||
} |
||||
return badge.GenerateBadge(workflowName, run.Status.String(), color), nil |
||||
} |
After Width: | Height: | Size: 1.7 KiB |
Loading…
Reference in new issue