gotify通知
Some checks failed
代码更新通知 / update-server (push) Failing after 2s

This commit is contained in:
2024-12-18 16:10:39 +08:00
parent a9ce145256
commit 0e8b02a9b1
6 changed files with 280 additions and 271 deletions

View File

@@ -8,16 +8,14 @@ jobs:
steps: steps:
- name: 输出当前目录环境 - name: 输出当前目录环境
run: pwd && ls -ahl run: pwd && ls -ahl
- name: 输出github环境变量
run: echo 'github相关 ${{ toJSON(github) }}'
- name: 拷贝文件
run: cd ../ && cp -r . /root/runner/
- name: 发送通知 - name: 发送通知
id: use-go-action id: use-go-action
uses: https://git.aweoo.com/action/gotify@latest uses: https://git.aweoo.com/action/gotify@latest
with: with:
username: foo url: https://gotify.aweoo.com
- name: Print Output token: test_token
title: GotifyAction版本更新
- name: 打印上一步的输出
run: echo 'output time is ${{ steps.use-go-action.outputs.time }}' run: echo 'output time is ${{ steps.use-go-action.outputs.time }}'
- name: 错误处理 - name: 错误处理
if: ${{ failure() }} if: ${{ failure() }}

View File

@@ -10,7 +10,4 @@ tasks:
- git push origin --tags - git push origin --tags
- git push - git push
cp:
cmds:
- cp -r ${GITHUB_WORKSPACE}../ /root/runner/

View File

@@ -1,12 +1,29 @@
name: 'Gotify通知' name: 'Gotify通知'
description: '发送Gotify通知' description: '发送Gotify通知'
inputs: inputs:
username: url:
description: 'The username to print' description: '地址 不需要/message'
required: true required: true
token:
description: "token"
required: true
title:
description: "标题"
required: true
msgText:
description: "消息内容"
contentType:
description: "消息格式"
default: "text/markdown"
priority:
description: "优先级"
clickUrl:
description: "点击跳转地址"
bigImageUrl:
description: "大图地址"
outputs: outputs:
time: time:
description: 'The time when the action was called' description: '结束时间(无用)'
runs: runs:
using: 'go' using: 'go'
main: 'main.go' main: 'main.go'

1
go.mod
View File

@@ -22,6 +22,7 @@ require (
github.com/go-openapi/strfmt v0.17.0 // indirect github.com/go-openapi/strfmt v0.17.0 // indirect
github.com/go-openapi/swag v0.17.0 // indirect github.com/go-openapi/swag v0.17.0 // indirect
github.com/go-openapi/validate v0.17.0 // indirect github.com/go-openapi/validate v0.17.0 // indirect
github.com/golang-cz/devslog v0.0.11 // indirect
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cast v1.7.0 // indirect

2
go.sum
View File

@@ -32,6 +32,8 @@ github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi88
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/validate v0.17.0 h1:pqoViQz3YLOGIhAmD0N4Lt6pa/3Gnj3ymKqQwq8iS6U= github.com/go-openapi/validate v0.17.0 h1:pqoViQz3YLOGIhAmD0N4Lt6pa/3Gnj3ymKqQwq8iS6U=
github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.17.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/golang-cz/devslog v0.0.11 h1:v4Yb9o0ZpuZ/D8ZrtVw1f9q5XrjnkxwHF1XmWwO8IHg=
github.com/golang-cz/devslog v0.0.11/go.mod h1:bSe5bm0A7Nyfqtijf1OMNgVJHlWEuVSXnkuASiE1vV8=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gotify/go-api-client/v2 v2.0.4 h1:0w8skCr8aLBDKaQDg31LKKHUGF7rt7zdRpR+6cqIAlE= github.com/gotify/go-api-client/v2 v2.0.4 h1:0w8skCr8aLBDKaQDg31LKKHUGF7rt7zdRpR+6cqIAlE=

512
main.go
View File

@@ -3,57 +3,57 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/golang-cz/devslog"
"github.com/gotify/go-api-client/v2/auth" "github.com/gotify/go-api-client/v2/auth"
"github.com/gotify/go-api-client/v2/client/message" "github.com/gotify/go-api-client/v2/client/message"
"github.com/gotify/go-api-client/v2/gotify" "github.com/gotify/go-api-client/v2/gotify"
"github.com/gotify/go-api-client/v2/models" "github.com/gotify/go-api-client/v2/models"
"github.com/sethvargo/go-githubactions" "github.com/sethvargo/go-githubactions"
"github.com/spf13/cast" "github.com/spf13/cast"
"io/fs" "log"
"log/slog"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path/filepath" "strings"
"time" "time"
) )
func init() {
slogOpts := &slog.HandlerOptions{
AddSource: false,
Level: slog.LevelDebug,
}
opts := &devslog.Options{
HandlerOptions: slogOpts,
MaxSlicePrintSize: 5,
SortKeys: true,
TimeFormat: "[15:04:05]",
StringerFormatter: true,
}
logger := slog.New(devslog.NewHandler(os.Stdout, opts))
slog.SetDefault(logger)
}
func main() { func main() {
//doPush() if err := doPush(); err != nil {
//return slog.Error("推送失败", slog.Any("err", err))
log.Fatalln(err)
ctx, err := githubactions.Context()
if err != nil {
panic(err)
} }
slog.Info("推送成功")
body, err := json.Marshal(ctx)
if err != nil {
panic(err)
}
fmt.Printf("context: %s\n", string(body))
username := githubactions.GetInput("username")
fmt.Printf("username is %s\n", username)
dir, _ := os.Getwd()
root := filepath.Join(dir, "../")
filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if d.IsDir() {
if d.Name() == ".git" {
return filepath.SkipDir
}
return nil
}
//body, _ = os.ReadFile(path)
fmt.Printf("path: %s\n", path)
//fmt.Printf("path: %s\n%s\n\n", path, string(body))
return nil
})
githubactions.SetOutput("time", time.Now().Format("2006-01-02 15:04:05")) githubactions.SetOutput("time", time.Now().Format("2006-01-02 15:04:05"))
} }
func doPush() { func doPush() error {
ctx, err := githubactions.Context()
if err != nil {
slog.Error("获取上下文失败", slog.Any("err", err))
return err
}
priority := githubactions.GetInput("priority") priority := githubactions.GetInput("priority")
title := githubactions.GetInput("title") title := githubactions.GetInput("title")
@@ -64,6 +64,8 @@ func doPush() {
msgText := githubactions.GetInput("msgText") msgText := githubactions.GetInput("msgText")
stringURL := githubactions.GetInput("url") stringURL := githubactions.GetInput("url")
msgText += "\n\n" + getExtraMsg(ctx)
msg := &models.MessageExternal{ msg := &models.MessageExternal{
Message: msgText, Message: msgText,
Title: title, Title: title,
@@ -91,13 +93,13 @@ func doPush() {
parsedURL, err := url.Parse(stringURL) parsedURL, err := url.Parse(stringURL)
if err != nil { if err != nil {
panic(err) return err
} }
pushMessage(parsedURL, token, msg) return pushMessage(parsedURL, token, msg)
} }
func pushMessage(parsedURL *url.URL, token string, msg *models.MessageExternal) { func pushMessage(parsedURL *url.URL, token string, msg *models.MessageExternal) error {
client := gotify.NewClient(parsedURL, &http.Client{}) client := gotify.NewClient(parsedURL, &http.Client{})
@@ -105,231 +107,223 @@ func pushMessage(parsedURL *url.URL, token string, msg *models.MessageExternal)
params.SetBody(msg) params.SetBody(msg)
res, err := client.Message.CreateMessage(params, auth.TokenAuth(token)) res, err := client.Message.CreateMessage(params, auth.TokenAuth(token))
if err == nil { if err == nil {
// todo成功 slog.Info("推送结果", slog.Any("result", res))
response, _ := json.Marshal(res) return nil
fmt.Println(string(response))
} else { } else {
panic(err) return err
// todo 错误处理
} }
} }
type GithubEnv struct { func getExtraMsg(ctx *githubactions.GitHubContext) (result string) {
Event struct { body, err := os.ReadFile(ctx.EventPath)
After string `json:"after"` if err != nil {
Before string `json:"before"` slog.Error("读取文件失败", slog.Any("err", err), slog.String("path", ctx.EventPath))
Commits []struct { return
Added []interface{} `json:"added"` }
Author struct { event := new(Event)
Email string `json:"email"` if err = json.Unmarshal(body, &event); err != nil {
Name string `json:"name"` slog.Error("解析json失败", slog.Any("err", err), slog.String("path", ctx.EventPath), slog.String("body", string(body)))
Username string `json:"username"` return
} `json:"author"` }
Committer struct {
Email string `json:"email"` result = "**更新内容:**\n%s\n\n[查看更新](%s)\t[查看Action](%s)"
Name string `json:"name"`
Username string `json:"username"` var commits []string
} `json:"committer"` for _, v := range event.Commits {
Id string `json:"id"` commits = append(commits, fmt.Sprintf("- %s [%s](%s)", v.Message, v.Id, v.Url))
Message string `json:"message"` }
Modified []string `json:"modified"`
Removed []interface{} `json:"removed"` action := fmt.Sprintf("%s/%s/actions/runs/%d", ctx.ServerURL, ctx.Repository, ctx.RunNumber)
Timestamp time.Time `json:"timestamp"` result = fmt.Sprintf(result, strings.Join(commits, "\n"), event.CompareUrl, action)
Url string `json:"url"` return
Verification interface{} `json:"verification"` }
} `json:"commits"`
CompareUrl string `json:"compare_url"` type Event struct {
HeadCommit struct { After string `json:"after"`
Added []interface{} `json:"added"` Before string `json:"before"`
Author struct { Commits []struct {
Email string `json:"email"` Added []interface{} `json:"added"`
Name string `json:"name"` Author struct {
Username string `json:"username"` Email string `json:"email"`
} `json:"author"` Name string `json:"name"`
Committer struct { Username string `json:"username"`
Email string `json:"email"` } `json:"author"`
Name string `json:"name"` Committer struct {
Username string `json:"username"` Email string `json:"email"`
} `json:"committer"` Name string `json:"name"`
Id string `json:"id"` Username string `json:"username"`
Message string `json:"message"` } `json:"committer"`
Modified []string `json:"modified"` Id string `json:"id"`
Removed []interface{} `json:"removed"` Message string `json:"message"`
Timestamp time.Time `json:"timestamp"` Modified []string `json:"modified"`
Url string `json:"url"` Removed []interface{} `json:"removed"`
Verification interface{} `json:"verification"` Timestamp time.Time `json:"timestamp"`
} `json:"head_commit"` Url string `json:"url"`
Pusher struct { Verification interface{} `json:"verification"`
Active bool `json:"active"` } `json:"commits"`
AvatarUrl string `json:"avatar_url"` CompareUrl string `json:"compare_url"`
Created time.Time `json:"created"` HeadCommit struct {
Description string `json:"description"` Added []interface{} `json:"added"`
Email string `json:"email"` Author struct {
FollowersCount int `json:"followers_count"` Email string `json:"email"`
FollowingCount int `json:"following_count"` Name string `json:"name"`
FullName string `json:"full_name"` Username string `json:"username"`
HtmlUrl string `json:"html_url"` } `json:"author"`
Id int `json:"id"` Committer struct {
IsAdmin bool `json:"is_admin"` Email string `json:"email"`
Language string `json:"language"` Name string `json:"name"`
LastLogin time.Time `json:"last_login"` Username string `json:"username"`
Location string `json:"location"` } `json:"committer"`
Login string `json:"login"` Id string `json:"id"`
LoginName string `json:"login_name"` Message string `json:"message"`
ProhibitLogin bool `json:"prohibit_login"` Modified []string `json:"modified"`
Restricted bool `json:"restricted"` Removed []interface{} `json:"removed"`
SourceId int `json:"source_id"` Timestamp time.Time `json:"timestamp"`
StarredReposCount int `json:"starred_repos_count"` Url string `json:"url"`
Username string `json:"username"` Verification interface{} `json:"verification"`
Visibility string `json:"visibility"` } `json:"head_commit"`
Website string `json:"website"` Pusher struct {
} `json:"pusher"` Active bool `json:"active"`
Ref string `json:"ref"` AvatarUrl string `json:"avatar_url"`
Repository struct { Created time.Time `json:"created"`
AllowFastForwardOnlyMerge bool `json:"allow_fast_forward_only_merge"` Description string `json:"description"`
AllowMergeCommits bool `json:"allow_merge_commits"` Email string `json:"email"`
AllowRebase bool `json:"allow_rebase"` FollowersCount int `json:"followers_count"`
AllowRebaseExplicit bool `json:"allow_rebase_explicit"` FollowingCount int `json:"following_count"`
AllowRebaseUpdate bool `json:"allow_rebase_update"` FullName string `json:"full_name"`
AllowSquashMerge bool `json:"allow_squash_merge"` HtmlUrl string `json:"html_url"`
Archived bool `json:"archived"` Id int `json:"id"`
ArchivedAt time.Time `json:"archived_at"` IsAdmin bool `json:"is_admin"`
AvatarUrl string `json:"avatar_url"` Language string `json:"language"`
CloneUrl string `json:"clone_url"` LastLogin time.Time `json:"last_login"`
CreatedAt time.Time `json:"created_at"` Location string `json:"location"`
DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"` Login string `json:"login"`
DefaultBranch string `json:"default_branch"` LoginName string `json:"login_name"`
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"` ProhibitLogin bool `json:"prohibit_login"`
DefaultMergeStyle string `json:"default_merge_style"` Restricted bool `json:"restricted"`
Description string `json:"description"` SourceId int `json:"source_id"`
Empty bool `json:"empty"` StarredReposCount int `json:"starred_repos_count"`
Fork bool `json:"fork"` Username string `json:"username"`
ForksCount int `json:"forks_count"` Visibility string `json:"visibility"`
FullName string `json:"full_name"` Website string `json:"website"`
HasActions bool `json:"has_actions"` } `json:"pusher"`
HasIssues bool `json:"has_issues"` Ref string `json:"ref"`
HasPackages bool `json:"has_packages"` Repository struct {
HasProjects bool `json:"has_projects"` AllowFastForwardOnlyMerge bool `json:"allow_fast_forward_only_merge"`
HasPullRequests bool `json:"has_pull_requests"` AllowMergeCommits bool `json:"allow_merge_commits"`
HasReleases bool `json:"has_releases"` AllowRebase bool `json:"allow_rebase"`
HasWiki bool `json:"has_wiki"` AllowRebaseExplicit bool `json:"allow_rebase_explicit"`
HtmlUrl string `json:"html_url"` AllowRebaseUpdate bool `json:"allow_rebase_update"`
Id int `json:"id"` AllowSquashMerge bool `json:"allow_squash_merge"`
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` Archived bool `json:"archived"`
Internal bool `json:"internal"` ArchivedAt time.Time `json:"archived_at"`
InternalTracker struct { AvatarUrl string `json:"avatar_url"`
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` CloneUrl string `json:"clone_url"`
EnableIssueDependencies bool `json:"enable_issue_dependencies"` CreatedAt time.Time `json:"created_at"`
EnableTimeTracker bool `json:"enable_time_tracker"` DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"`
} `json:"internal_tracker"` DefaultBranch string `json:"default_branch"`
Language string `json:"language"` DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
LanguagesUrl string `json:"languages_url"` DefaultMergeStyle string `json:"default_merge_style"`
Link string `json:"link"` Description string `json:"description"`
Mirror bool `json:"mirror"` Empty bool `json:"empty"`
MirrorInterval string `json:"mirror_interval"` Fork bool `json:"fork"`
MirrorUpdated time.Time `json:"mirror_updated"` ForksCount int `json:"forks_count"`
Name string `json:"name"` FullName string `json:"full_name"`
ObjectFormatName string `json:"object_format_name"` HasActions bool `json:"has_actions"`
OpenIssuesCount int `json:"open_issues_count"` HasIssues bool `json:"has_issues"`
OpenPrCounter int `json:"open_pr_counter"` HasPackages bool `json:"has_packages"`
OriginalUrl string `json:"original_url"` HasProjects bool `json:"has_projects"`
Owner struct { HasPullRequests bool `json:"has_pull_requests"`
Active bool `json:"active"` HasReleases bool `json:"has_releases"`
AvatarUrl string `json:"avatar_url"` HasWiki bool `json:"has_wiki"`
Created time.Time `json:"created"` HtmlUrl string `json:"html_url"`
Description string `json:"description"` Id int `json:"id"`
Email string `json:"email"` IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
FollowersCount int `json:"followers_count"` Internal bool `json:"internal"`
FollowingCount int `json:"following_count"` InternalTracker struct {
FullName string `json:"full_name"` AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
HtmlUrl string `json:"html_url"` EnableIssueDependencies bool `json:"enable_issue_dependencies"`
Id int `json:"id"` EnableTimeTracker bool `json:"enable_time_tracker"`
IsAdmin bool `json:"is_admin"` } `json:"internal_tracker"`
Language string `json:"language"` Language string `json:"language"`
LastLogin time.Time `json:"last_login"` LanguagesUrl string `json:"languages_url"`
Location string `json:"location"` Link string `json:"link"`
Login string `json:"login"` Mirror bool `json:"mirror"`
LoginName string `json:"login_name"` MirrorInterval string `json:"mirror_interval"`
ProhibitLogin bool `json:"prohibit_login"` MirrorUpdated time.Time `json:"mirror_updated"`
Restricted bool `json:"restricted"` Name string `json:"name"`
SourceId int `json:"source_id"` ObjectFormatName string `json:"object_format_name"`
StarredReposCount int `json:"starred_repos_count"` OpenIssuesCount int `json:"open_issues_count"`
Username string `json:"username"` OpenPrCounter int `json:"open_pr_counter"`
Visibility string `json:"visibility"` OriginalUrl string `json:"original_url"`
Website string `json:"website"` Owner struct {
} `json:"owner"` Active bool `json:"active"`
Parent interface{} `json:"parent"` AvatarUrl string `json:"avatar_url"`
Permissions struct { Created time.Time `json:"created"`
Admin bool `json:"admin"` Description string `json:"description"`
Pull bool `json:"pull"` Email string `json:"email"`
Push bool `json:"push"` FollowersCount int `json:"followers_count"`
} `json:"permissions"` FollowingCount int `json:"following_count"`
Private bool `json:"private"` FullName string `json:"full_name"`
ProjectsMode string `json:"projects_mode"` HtmlUrl string `json:"html_url"`
ReleaseCounter int `json:"release_counter"` Id int `json:"id"`
RepoTransfer interface{} `json:"repo_transfer"` IsAdmin bool `json:"is_admin"`
Size int `json:"size"` Language string `json:"language"`
SshUrl string `json:"ssh_url"` LastLogin time.Time `json:"last_login"`
StarsCount int `json:"stars_count"` Location string `json:"location"`
Template bool `json:"template"` Login string `json:"login"`
UpdatedAt time.Time `json:"updated_at"` LoginName string `json:"login_name"`
Url string `json:"url"` ProhibitLogin bool `json:"prohibit_login"`
WatchersCount int `json:"watchers_count"` Restricted bool `json:"restricted"`
Website string `json:"website"` SourceId int `json:"source_id"`
} `json:"repository"` StarredReposCount int `json:"starred_repos_count"`
Sender struct { Username string `json:"username"`
Active bool `json:"active"` Visibility string `json:"visibility"`
AvatarUrl string `json:"avatar_url"` Website string `json:"website"`
Created time.Time `json:"created"` } `json:"owner"`
Description string `json:"description"` Parent interface{} `json:"parent"`
Email string `json:"email"` Permissions struct {
FollowersCount int `json:"followers_count"` Admin bool `json:"admin"`
FollowingCount int `json:"following_count"` Pull bool `json:"pull"`
FullName string `json:"full_name"` Push bool `json:"push"`
HtmlUrl string `json:"html_url"` } `json:"permissions"`
Id int `json:"id"` Private bool `json:"private"`
IsAdmin bool `json:"is_admin"` ProjectsMode string `json:"projects_mode"`
Language string `json:"language"` ReleaseCounter int `json:"release_counter"`
LastLogin time.Time `json:"last_login"` RepoTransfer interface{} `json:"repo_transfer"`
Location string `json:"location"` Size int `json:"size"`
Login string `json:"login"` SshUrl string `json:"ssh_url"`
LoginName string `json:"login_name"` StarsCount int `json:"stars_count"`
ProhibitLogin bool `json:"prohibit_login"` Template bool `json:"template"`
Restricted bool `json:"restricted"` UpdatedAt time.Time `json:"updated_at"`
SourceId int `json:"source_id"` Url string `json:"url"`
StarredReposCount int `json:"starred_repos_count"` WatchersCount int `json:"watchers_count"`
Username string `json:"username"` Website string `json:"website"`
Visibility string `json:"visibility"` } `json:"repository"`
Website string `json:"website"` Sender struct {
} `json:"sender"` Active bool `json:"active"`
TotalCommits int `json:"total_commits"` AvatarUrl string `json:"avatar_url"`
} `json:"event"` Created time.Time `json:"created"`
EventPath string `json:"event_path"` Description string `json:"description"`
Workflow string `json:"workflow"` Email string `json:"email"`
RunId string `json:"run_id"` FollowersCount int `json:"followers_count"`
RunNumber string `json:"run_number"` FollowingCount int `json:"following_count"`
Actor string `json:"actor"` FullName string `json:"full_name"`
Repository string `json:"repository"` HtmlUrl string `json:"html_url"`
EventName string `json:"event_name"` Id int `json:"id"`
Sha string `json:"sha"` IsAdmin bool `json:"is_admin"`
Ref string `json:"ref"` Language string `json:"language"`
RefName string `json:"ref_name"` LastLogin time.Time `json:"last_login"`
RefType string `json:"ref_type"` Location string `json:"location"`
HeadRef string `json:"head_ref"` Login string `json:"login"`
BaseRef string `json:"base_ref"` LoginName string `json:"login_name"`
Token string `json:"token"` ProhibitLogin bool `json:"prohibit_login"`
Workspace string `json:"workspace"` Restricted bool `json:"restricted"`
Action string `json:"action"` SourceId int `json:"source_id"`
ActionPath string `json:"action_path"` StarredReposCount int `json:"starred_repos_count"`
ActionRef string `json:"action_ref"` Username string `json:"username"`
ActionRepository string `json:"action_repository"` Visibility string `json:"visibility"`
Job string `json:"job"` Website string `json:"website"`
JobName string `json:"job_name"` } `json:"sender"`
RepositoryOwner string `json:"repository_owner"` TotalCommits int `json:"total_commits"`
RetentionDays string `json:"retention_days"`
RunnerPerflog string `json:"runner_perflog"`
RunnerTrackingId string `json:"runner_tracking_id"`
ServerUrl string `json:"server_url"`
ApiUrl string `json:"api_url"`
GraphqlUrl string `json:"graphql_url"`
} }