mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-22 01:41:02 +00:00
Access repos by their ids (#1691)
closes #1295 closes #648 # TODO - [x] add new routes with `:repoID` - [x] load repo in middleware using `:repoID` if present - [x] update UI routes `:owner/:name` to `:repoID` - [x] load repos using id in UI - [x] add lookup endpoint `:owner/:name` to `:repoID` - [x] redirect `:owner/:name` to `:repoID` in UI - [x] use badge with `:repoID` route in UI - [x] update `woodpecker-go` - [x] check cli - [x] add migrations / deprecation notes - [x] check if #648 got solved directly - [x] Test - [x] create repo - [x] repo pages - [x] ui redirects - [x] forge status links
This commit is contained in:
parent
e3593cd9a4
commit
ff01a9ff1d
98 changed files with 1402 additions and 1676 deletions
|
@ -70,5 +70,5 @@ func FormatFlag(tmpl string, hidden ...bool) *cli.StringFlag {
|
|||
var RepoFlag = &cli.StringFlag{
|
||||
Name: "repository",
|
||||
Aliases: []string{"repo"},
|
||||
Usage: "repository name (e.g. octocat/hello-world)",
|
||||
Usage: "repository id or full-name (e.g. 134 or octocat/hello-world)",
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var cronCreateCmd = &cli.Command{
|
||||
Name: "add",
|
||||
Usage: "add a cron job",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: cronCreate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -38,29 +38,32 @@ var cronCreateCmd = &cli.Command{
|
|||
|
||||
func cronCreate(c *cli.Context) error {
|
||||
var (
|
||||
jobName = c.String("name")
|
||||
branch = c.String("branch")
|
||||
schedule = c.String("schedule")
|
||||
reponame = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
jobName = c.String("name")
|
||||
branch = c.String("branch")
|
||||
schedule = c.String("schedule")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cron := &woodpecker.Cron{
|
||||
Name: jobName,
|
||||
Branch: branch,
|
||||
Schedule: schedule,
|
||||
}
|
||||
cron, err = client.CronCreate(owner, name, cron)
|
||||
cron, err = client.CronCreate(repoID, cron)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
var cronInfoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "display info about a cron job",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: cronInfo,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -28,22 +28,23 @@ var cronInfoCmd = &cli.Command{
|
|||
|
||||
func cronInfo(c *cli.Context) error {
|
||||
var (
|
||||
jobID = c.Int64("id")
|
||||
reponame = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
jobID = c.Int64("id")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cron, err := client.CronGet(owner, name, jobID)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cron, err := client.CronGet(repoID, jobID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
var cronListCmd = &cli.Command{
|
||||
Name: "ls",
|
||||
Usage: "list cron jobs",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: cronList,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -37,21 +37,21 @@ var cronListCmd = &cli.Command{
|
|||
|
||||
func cronList(c *cli.Context) error {
|
||||
var (
|
||||
format = c.String("format") + "\n"
|
||||
reponame = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list, err := client.CronList(owner, name)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list, err := client.CronList(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
var cronDeleteCmd = &cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "remove a cron job",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: cronDelete,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -26,21 +26,21 @@ var cronDeleteCmd = &cli.Command{
|
|||
|
||||
func cronDelete(c *cli.Context) error {
|
||||
var (
|
||||
jobID = c.Int64("id")
|
||||
reponame = c.String("repository")
|
||||
jobID = c.Int64("id")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = client.CronDelete(owner, name, jobID)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = client.CronDelete(repoID, jobID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var cronUpdateCmd = &cli.Command{
|
||||
Name: "update",
|
||||
Usage: "update a cron job",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: cronUpdate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -41,21 +41,21 @@ var cronUpdateCmd = &cli.Command{
|
|||
|
||||
func cronUpdate(c *cli.Context) error {
|
||||
var (
|
||||
reponame = c.String("repository")
|
||||
jobID = c.Int64("id")
|
||||
jobName = c.String("name")
|
||||
branch = c.String("branch")
|
||||
schedule = c.String("schedule")
|
||||
format = c.String("format") + "\n"
|
||||
repoIDOrFullName = c.String("repository")
|
||||
jobID = c.Int64("id")
|
||||
jobName = c.String("name")
|
||||
branch = c.String("branch")
|
||||
schedule = c.String("schedule")
|
||||
format = c.String("format") + "\n"
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func cronUpdate(c *cli.Context) error {
|
|||
Branch: branch,
|
||||
Schedule: schedule,
|
||||
}
|
||||
cron, err = client.CronUpdate(owner, name, cron)
|
||||
cron, err = client.CronUpdate(repoID, cron)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
var Command = &cli.Command{
|
||||
Name: "deploy",
|
||||
Usage: "deploy code",
|
||||
ArgsUsage: "<repo/name> <pipeline> <environment>",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline> <environment>",
|
||||
Action: deploy,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplDeployInfo),
|
||||
|
@ -59,13 +59,13 @@ var Command = &cli.Command{
|
|||
}
|
||||
|
||||
func deploy(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
repo := c.Args().First()
|
||||
repoID, err := internal.ParseRepo(client, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func deploy(c *cli.Context) error {
|
|||
var number int
|
||||
if pipelineArg == "last" {
|
||||
// Fetch the pipeline number from the last pipeline
|
||||
pipelines, berr := client.PipelineList(owner, name)
|
||||
pipelines, berr := client.PipelineList(repoID)
|
||||
if berr != nil {
|
||||
return berr
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func deploy(c *cli.Context) error {
|
|||
|
||||
params := internal.ParseKeyPair(c.StringSlice("param"))
|
||||
|
||||
deploy, err := client.Deploy(owner, name, number, env, params)
|
||||
deploy, err := client.Deploy(repoID, number, env, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -76,15 +77,16 @@ func NewClient(c *cli.Context) (woodpecker.Client, error) {
|
|||
}
|
||||
|
||||
// ParseRepo parses the repository owner and name from a string.
|
||||
func ParseRepo(str string) (user, repo string, err error) {
|
||||
parts := strings.Split(str, "/")
|
||||
if len(parts) != 2 {
|
||||
err = fmt.Errorf("Error: Invalid or missing repository. eg octocat/hello-world")
|
||||
return
|
||||
func ParseRepo(client woodpecker.Client, str string) (repoID int64, err error) {
|
||||
if strings.Contains(str, "/") {
|
||||
repo, err := client.RepoLookup(str)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return repo.ID, nil
|
||||
}
|
||||
user = parts[0]
|
||||
repo = parts[1]
|
||||
return
|
||||
|
||||
return strconv.ParseInt(str, 10, 64)
|
||||
}
|
||||
|
||||
// ParseKeyPair parses a key=value pair.
|
||||
|
|
|
@ -27,14 +27,18 @@ import (
|
|||
var logPurgeCmd = &cli.Command{
|
||||
Name: "purge",
|
||||
Usage: "purge a log",
|
||||
ArgsUsage: "<repo/name> <pipeline>",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline>",
|
||||
Action: logPurge,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func logPurge(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoIDOrFullName := c.Args().First()
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -43,16 +47,11 @@ func logPurge(c *cli.Context) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
err = client.LogsPurge(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.LogsPurge(owner, name, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Purging logs for pipeline %s/%s#%d\n", owner, name, number)
|
||||
fmt.Printf("Purging logs for pipeline %s#%d\n", repoIDOrFullName, number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,14 +27,18 @@ import (
|
|||
var pipelineApproveCmd = &cli.Command{
|
||||
Name: "approve",
|
||||
Usage: "approve a pipeline",
|
||||
ArgsUsage: "<repo/name> <pipeline>",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline>",
|
||||
Action: pipelineApprove,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func pipelineApprove(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -43,16 +47,11 @@ func pipelineApprove(c *cli.Context) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
_, err = client.PipelineApprove(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.PipelineApprove(owner, name, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Approving pipeline %s/%s#%d\n", owner, name, number)
|
||||
fmt.Printf("Approving pipeline %s#%d\n", repoIDOrFullName, number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
var pipelineCreateCmd = &cli.Command{
|
||||
Name: "create",
|
||||
Usage: "create new pipeline",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: pipelineCreate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplPipelineList),
|
||||
|
@ -47,14 +47,12 @@ var pipelineCreateCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelineCreate(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -74,7 +72,7 @@ func pipelineCreate(c *cli.Context) error {
|
|||
Variables: variables,
|
||||
}
|
||||
|
||||
pipeline, err := client.PipelineCreate(owner, name, options)
|
||||
pipeline, err := client.PipelineCreate(repoID, options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,32 +27,32 @@ import (
|
|||
var pipelineDeclineCmd = &cli.Command{
|
||||
Name: "decline",
|
||||
Usage: "decline a pipeline",
|
||||
ArgsUsage: "<repo/name> <pipeline>",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline>",
|
||||
Action: pipelineDecline,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func pipelineDecline(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
number, err := strconv.Atoi(c.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
_, err = client.PipelineDecline(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = client.PipelineDecline(owner, name, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Declining pipeline %s/%s#%d\n", owner, name, number)
|
||||
fmt.Printf("Declining pipeline %s#%d\n", repoIDOrFullName, number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
var pipelineInfoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "show pipeline details",
|
||||
ArgsUsage: "<repo/name> [pipeline]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline]",
|
||||
Action: pipelineInfo,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplPipelineInfo),
|
||||
|
@ -36,22 +36,21 @@ var pipelineInfoCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelineInfo(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pipelineArg := c.Args().Get(1)
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var number int
|
||||
if pipelineArg == "last" || len(pipelineArg) == 0 {
|
||||
// Fetch the pipeline number from the last pipeline
|
||||
pipeline, err := client.PipelineLast(owner, name, "")
|
||||
pipeline, err := client.PipelineLast(repoID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -63,7 +62,7 @@ func pipelineInfo(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
pipeline, err := client.Pipeline(owner, name, number)
|
||||
pipeline, err := client.Pipeline(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,33 +27,33 @@ import (
|
|||
var pipelineKillCmd = &cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "force kill a pipeline",
|
||||
ArgsUsage: "<repo/name> <pipeline>",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline>",
|
||||
Action: pipelineKill,
|
||||
Hidden: true,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func pipelineKill(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
number, err := strconv.Atoi(c.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.PipelineKill(owner, name, number)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Force killing pipeline %s/%s#%d\n", owner, name, number)
|
||||
err = client.PipelineKill(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Force killing pipeline %s#%d\n", repoIDOrFullName, number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
var pipelineLastCmd = &cli.Command{
|
||||
Name: "last",
|
||||
Usage: "show latest pipeline details",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: pipelineLast,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplPipelineInfo),
|
||||
|
@ -40,18 +40,17 @@ var pipelineLastCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelineLast(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pipeline, err := client.PipelineLast(owner, name, c.String("branch"))
|
||||
pipeline, err := client.PipelineLast(repoID, c.String("branch"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
var pipelineListCmd = &cli.Command{
|
||||
Name: "ls",
|
||||
Usage: "show pipeline history",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: pipelineList,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplPipelineList),
|
||||
|
@ -52,18 +52,17 @@ var pipelineListCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelineList(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pipelines, err := client.PipelineList(owner, name)
|
||||
pipelines, err := client.PipelineList(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -101,7 +100,7 @@ func pipelineList(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// template for pipeline list information
|
||||
var tmplPipelineList = "\x1b[33mBuild #{{ .Number }} \x1b[0m" + `
|
||||
var tmplPipelineList = "\x1b[33mPipeline #{{ .Number }} \x1b[0m" + `
|
||||
Status: {{ .Status }}
|
||||
Event: {{ .Event }}
|
||||
Commit: {{ .Commit }}
|
||||
|
|
|
@ -27,14 +27,18 @@ import (
|
|||
var pipelineLogsCmd = &cli.Command{
|
||||
Name: "logs",
|
||||
Usage: "show pipeline logs",
|
||||
ArgsUsage: "<repo/name> [pipeline] [stepID]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline] [stepID]",
|
||||
Action: pipelineLogs,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func pipelineLogs(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -49,12 +53,7 @@ func pipelineLogs(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logs, err := client.StepLogEntries(owner, name, number, step)
|
||||
logs, err := client.StepLogEntries(repoID, number, step)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
var pipelinePsCmd = &cli.Command{
|
||||
Name: "ps",
|
||||
Usage: "show pipeline steps",
|
||||
ArgsUsage: "<repo/name> [pipeline]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline]",
|
||||
Action: pipelinePs,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplPipelinePs),
|
||||
|
@ -36,14 +36,12 @@ var pipelinePsCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelinePs(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -53,7 +51,7 @@ func pipelinePs(c *cli.Context) error {
|
|||
|
||||
if pipelineArg == "last" || len(pipelineArg) == 0 {
|
||||
// Fetch the pipeline number from the last pipeline
|
||||
pipeline, err := client.PipelineLast(owner, name, "")
|
||||
pipeline, err := client.PipelineLast(repoID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -66,7 +64,7 @@ func pipelinePs(c *cli.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
pipeline, err := client.Pipeline(owner, name, number)
|
||||
pipeline, err := client.Pipeline(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
var pipelineStartCmd = &cli.Command{
|
||||
Name: "start",
|
||||
Usage: "start a pipeline",
|
||||
ArgsUsage: "<repo/name> [pipeline]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline]",
|
||||
Action: pipelineStart,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.StringSliceFlag{
|
||||
|
@ -40,13 +40,12 @@ var pipelineStartCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func pipelineStart(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -55,7 +54,7 @@ func pipelineStart(c *cli.Context) (err error) {
|
|||
var number int
|
||||
if pipelineArg == "last" {
|
||||
// Fetch the pipeline number from the last pipeline
|
||||
pipeline, err := client.PipelineLast(owner, name, "")
|
||||
pipeline, err := client.PipelineLast(repoID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -72,11 +71,11 @@ func pipelineStart(c *cli.Context) (err error) {
|
|||
|
||||
params := internal.ParseKeyPair(c.StringSlice("param"))
|
||||
|
||||
pipeline, err := client.PipelineStart(owner, name, number, params)
|
||||
pipeline, err := client.PipelineStart(repoID, number, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Starting pipeline %s/%s#%d\n", owner, name, pipeline.Number)
|
||||
fmt.Printf("Starting pipeline %s#%d\n", repoIDOrFullName, pipeline.Number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,14 +27,18 @@ import (
|
|||
var pipelineStopCmd = &cli.Command{
|
||||
Name: "stop",
|
||||
Usage: "stop a pipeline",
|
||||
ArgsUsage: "<repo/name> [pipeline]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline]",
|
||||
Flags: common.GlobalFlags,
|
||||
Action: pipelineStop,
|
||||
}
|
||||
|
||||
func pipelineStop(c *cli.Context) (err error) {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -43,16 +47,11 @@ func pipelineStop(c *cli.Context) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
err = client.PipelineStop(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.PipelineStop(owner, name, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Stopping pipeline %s/%s#%d\n", owner, name, number)
|
||||
fmt.Printf("Stopping pipeline %s#%d\n", repoIDOrFullName, number)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var registryCreateCmd = &cli.Command{
|
||||
Name: "add",
|
||||
Usage: "adds a registry",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: registryCreate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -36,19 +36,19 @@ var registryCreateCmd = &cli.Command{
|
|||
|
||||
func registryCreate(c *cli.Context) error {
|
||||
var (
|
||||
hostname = c.String("hostname")
|
||||
username = c.String("username")
|
||||
password = c.String("password")
|
||||
reponame = c.String("repository")
|
||||
hostname = c.String("hostname")
|
||||
username = c.String("username")
|
||||
password = c.String("password")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func registryCreate(c *cli.Context) error {
|
|||
}
|
||||
registry.Password = string(out)
|
||||
}
|
||||
_, err = client.RegistryCreate(owner, name, registry)
|
||||
_, err = client.RegistryCreate(repoID, registry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
var registryInfoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "display registry info",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: registryInfo,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -28,22 +28,22 @@ var registryInfoCmd = &cli.Command{
|
|||
|
||||
func registryInfo(c *cli.Context) error {
|
||||
var (
|
||||
hostname = c.String("hostname")
|
||||
reponame = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
hostname = c.String("hostname")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registry, err := client.Registry(owner, name, hostname)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registry, err := client.Registry(repoID, hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
var registryListCmd = &cli.Command{
|
||||
Name: "ls",
|
||||
Usage: "list registries",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: registryList,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -37,21 +37,21 @@ var registryListCmd = &cli.Command{
|
|||
|
||||
func registryList(c *cli.Context) error {
|
||||
var (
|
||||
format = c.String("format") + "\n"
|
||||
reponame = c.String("repository")
|
||||
format = c.String("format") + "\n"
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list, err := client.RegistryList(owner, name)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
list, err := client.RegistryList(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
var registryDeleteCmd = &cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "remove a registry",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: registryDelete,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -24,19 +24,19 @@ var registryDeleteCmd = &cli.Command{
|
|||
|
||||
func registryDelete(c *cli.Context) error {
|
||||
var (
|
||||
hostname = c.String("hostname")
|
||||
reponame = c.String("repository")
|
||||
hostname = c.String("hostname")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
if err != nil {
|
||||
return err
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.RegistryDelete(owner, name, hostname)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.RegistryDelete(repoID, hostname)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var registryUpdateCmd = &cli.Command{
|
||||
Name: "update",
|
||||
Usage: "update a registry",
|
||||
ArgsUsage: "[repo/name]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: registryUpdate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.RepoFlag,
|
||||
|
@ -36,19 +36,19 @@ var registryUpdateCmd = &cli.Command{
|
|||
|
||||
func registryUpdate(c *cli.Context) error {
|
||||
var (
|
||||
hostname = c.String("hostname")
|
||||
username = c.String("username")
|
||||
password = c.String("password")
|
||||
reponame = c.String("repository")
|
||||
hostname = c.String("hostname")
|
||||
username = c.String("username")
|
||||
password = c.String("password")
|
||||
repoIDOrFullName = c.String("repository")
|
||||
)
|
||||
if reponame == "" {
|
||||
reponame = c.Args().First()
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
owner, name, err := internal.ParseRepo(reponame)
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -65,9 +65,6 @@ func registryUpdate(c *cli.Context) error {
|
|||
}
|
||||
registry.Password = string(out)
|
||||
}
|
||||
_, err = client.RegistryUpdate(owner, name, registry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
_, err = client.RegistryUpdate(repoID, registry)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package repo
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
|
@ -12,16 +13,16 @@ import (
|
|||
var repoAddCmd = &cli.Command{
|
||||
Name: "add",
|
||||
Usage: "add a repository",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<forge-remote-id>",
|
||||
Action: repoAdd,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func repoAdd(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
_forgeRemoteID := c.Args().First()
|
||||
forgeRemoteID, err := strconv.Atoi(_forgeRemoteID)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid forge remote id: %s", _forgeRemoteID)
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
|
@ -29,9 +30,11 @@ func repoAdd(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if _, err := client.RepoPost(owner, name); err != nil {
|
||||
repo, err := client.RepoPost(int64(forgeRemoteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully activated repository %s/%s\n", owner, name)
|
||||
|
||||
fmt.Printf("Successfully activated repository with forge remote %s\n", repo.FullName)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,26 +12,27 @@ import (
|
|||
var repoChownCmd = &cli.Command{
|
||||
Name: "chown",
|
||||
Usage: "assume ownership of a repository",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: repoChown,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func repoChown(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := client.RepoChown(owner, name); err != nil {
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully assumed ownership of repository %s/%s\n", owner, name)
|
||||
|
||||
repo, err := client.RepoChown(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully assumed ownership of repository %s\n", repo.FullName)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
var repoInfoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "show repository details",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: repoInfo,
|
||||
Flags: append(common.GlobalFlags,
|
||||
common.FormatFlag(tmplRepoInfo),
|
||||
|
@ -21,18 +21,17 @@ var repoInfoCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func repoInfo(c *cli.Context) error {
|
||||
arg := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repo, err := client.Repo(owner, name)
|
||||
repo, err := client.Repo(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -47,11 +46,12 @@ func repoInfo(c *cli.Context) error {
|
|||
// template for repo information
|
||||
var tmplRepoInfo = `Owner: {{ .Owner }}
|
||||
Repo: {{ .Name }}
|
||||
Type: {{ .Kind }}
|
||||
Config: {{ .Config }}
|
||||
Link: {{ .Link }}
|
||||
Config path: {{ .Config }}
|
||||
Visibility: {{ .Visibility }}
|
||||
Private: {{ .IsSCMPrivate }}
|
||||
Trusted: {{ .IsTrusted }}
|
||||
Gated: {{ .IsGated }}
|
||||
Forge: {{ .Clone }}
|
||||
Clone url: {{ .Clone }}
|
||||
Allow pull-requests: {{ .AllowPullRequests }}
|
||||
`
|
||||
|
|
|
@ -53,4 +53,4 @@ func repoList(c *cli.Context) error {
|
|||
}
|
||||
|
||||
// template for repository list items
|
||||
var tmplRepoList = `{{ .FullName }}`
|
||||
var tmplRepoList = "\x1b[33m{{ .FullName }}\x1b[0m (id: {{ .ID }})"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/cli/common"
|
||||
|
@ -10,20 +12,26 @@ import (
|
|||
var repoRepairCmd = &cli.Command{
|
||||
Name: "repair",
|
||||
Usage: "repair repository webhooks",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: repoRepair,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func repoRepair(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.RepoRepair(owner, name)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := client.RepoRepair(repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully removed repository %s\n", repoIDOrFullName)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,26 +12,25 @@ import (
|
|||
var repoRemoveCmd = &cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "remove a repository",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: repoRemove,
|
||||
Flags: common.GlobalFlags,
|
||||
}
|
||||
|
||||
func repoRemove(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := client.RepoDel(owner, name); err != nil {
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully removed repository %s/%s\n", owner, name)
|
||||
|
||||
if err := client.RepoDel(repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully removed repository %s\n", repoIDOrFullName)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ var repoSyncCmd = &cli.Command{
|
|||
),
|
||||
}
|
||||
|
||||
// TODO: remove this and add an option to the list cmd as we do not store the remote repo list anymore
|
||||
func repoSync(c *cli.Context) error {
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
var repoUpdateCmd = &cli.Command{
|
||||
Name: "update",
|
||||
Usage: "update a repository",
|
||||
ArgsUsage: "<repo/name>",
|
||||
ArgsUsage: "<repo-id|repo-full-name>",
|
||||
Action: repoUpdate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -63,13 +63,12 @@ var repoUpdateCmd = &cli.Command{
|
|||
}
|
||||
|
||||
func repoUpdate(c *cli.Context) error {
|
||||
repo := c.Args().First()
|
||||
owner, name, err := internal.ParseRepo(repo)
|
||||
repoIDOrFullName := c.Args().First()
|
||||
client, err := internal.NewClient(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := internal.NewClient(c)
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -111,9 +110,11 @@ func repoUpdate(c *cli.Context) error {
|
|||
patch.PipelineCounter = &pipelineCounter
|
||||
}
|
||||
|
||||
if _, err := client.RepoPatch(owner, name, patch); err != nil {
|
||||
repo, err := client.RepoPatch(repoID, patch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Successfully updated repository %s/%s\n", owner, name)
|
||||
|
||||
fmt.Printf("Successfully updated repository %s\n", repo.FullName)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/woodpecker-ci/woodpecker/cli/common"
|
||||
"github.com/woodpecker-ci/woodpecker/cli/internal"
|
||||
"github.com/woodpecker-ci/woodpecker/woodpecker-go/woodpecker"
|
||||
)
|
||||
|
||||
// Command exports the secret command.
|
||||
|
@ -23,24 +24,29 @@ var Command = &cli.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func parseTargetArgs(c *cli.Context) (global bool, owner, name string, err error) {
|
||||
func parseTargetArgs(client woodpecker.Client, c *cli.Context) (global bool, owner string, repoID int64, err error) {
|
||||
if c.Bool("global") {
|
||||
return true, "", "", nil
|
||||
return true, "", -1, nil
|
||||
}
|
||||
|
||||
repoIDOrFullName := c.String("repository")
|
||||
if repoIDOrFullName == "" {
|
||||
repoIDOrFullName = c.Args().First()
|
||||
}
|
||||
|
||||
orgName := c.String("organization")
|
||||
repoName := c.String("repository")
|
||||
if orgName == "" && repoName == "" {
|
||||
repoName = c.Args().First()
|
||||
if orgName != "" && repoIDOrFullName == "" {
|
||||
return false, orgName, -1, err
|
||||
}
|
||||
if orgName == "" && !strings.Contains(repoName, "/") {
|
||||
orgName = repoName
|
||||
|
||||
if orgName != "" && !strings.Contains(repoIDOrFullName, "/") {
|
||||
repoIDOrFullName = orgName + "/" + repoIDOrFullName
|
||||
}
|
||||
if orgName != "" {
|
||||
return false, orgName, "", err
|
||||
}
|
||||
owner, name, err = internal.ParseRepo(repoName)
|
||||
|
||||
repoID, err = internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return false, "", "", err
|
||||
return false, "", -1, err
|
||||
}
|
||||
return false, owner, name, nil
|
||||
|
||||
return false, "", repoID, nil
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var secretCreateCmd = &cli.Command{
|
||||
Name: "add",
|
||||
Usage: "adds a secret",
|
||||
ArgsUsage: "[org/repo|org]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: secretCreate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -74,7 +74,7 @@ func secretCreate(c *cli.Context) error {
|
|||
secret.Value = string(out)
|
||||
}
|
||||
|
||||
global, owner, repo, err := parseTargetArgs(c)
|
||||
global, owner, repoID, err := parseTargetArgs(client, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -83,11 +83,11 @@ func secretCreate(c *cli.Context) error {
|
|||
_, err = client.GlobalSecretCreate(secret)
|
||||
return err
|
||||
}
|
||||
if repo == "" {
|
||||
if owner != "" {
|
||||
_, err = client.OrgSecretCreate(owner, secret)
|
||||
return err
|
||||
}
|
||||
_, err = client.SecretCreate(owner, repo, secret)
|
||||
_, err = client.SecretCreate(repoID, secret)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var secretInfoCmd = &cli.Command{
|
||||
Name: "info",
|
||||
Usage: "display secret info",
|
||||
ArgsUsage: "[org/repo|org]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: secretInfo,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -44,7 +44,7 @@ func secretInfo(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
global, owner, repo, err := parseTargetArgs(c)
|
||||
global, owner, repoID, err := parseTargetArgs(client, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -55,13 +55,13 @@ func secretInfo(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if repo == "" {
|
||||
} else if owner != "" {
|
||||
secret, err = client.OrgSecret(owner, secretName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
secret, err = client.Secret(owner, repo, secretName)
|
||||
secret, err = client.Secret(repoID, secretName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
var secretListCmd = &cli.Command{
|
||||
Name: "ls",
|
||||
Usage: "list secrets",
|
||||
ArgsUsage: "[org/name|org]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: secretList,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -39,7 +39,7 @@ func secretList(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
global, owner, repo, err := parseTargetArgs(c)
|
||||
global, owner, repoID, err := parseTargetArgs(client, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -50,13 +50,13 @@ func secretList(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if repo == "" {
|
||||
} else if owner != "" {
|
||||
list, err = client.OrgSecretList(owner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
list, err = client.SecretList(owner, repo)
|
||||
list, err = client.SecretList(repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
var secretDeleteCmd = &cli.Command{
|
||||
Name: "rm",
|
||||
Usage: "remove a secret",
|
||||
ArgsUsage: "[org/repo|org]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: secretDelete,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -37,7 +37,7 @@ func secretDelete(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
global, owner, repo, err := parseTargetArgs(c)
|
||||
global, owner, repoID, err := parseTargetArgs(client, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -45,8 +45,8 @@ func secretDelete(c *cli.Context) error {
|
|||
if global {
|
||||
return client.GlobalSecretDelete(secretName)
|
||||
}
|
||||
if repo == "" {
|
||||
if owner != "" {
|
||||
return client.OrgSecretDelete(owner, secretName)
|
||||
}
|
||||
return client.SecretDelete(owner, repo, secretName)
|
||||
return client.SecretDelete(repoID, secretName)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
var secretUpdateCmd = &cli.Command{
|
||||
Name: "update",
|
||||
Usage: "update a secret",
|
||||
ArgsUsage: "[org/repo|org]",
|
||||
ArgsUsage: "[repo-id|repo-full-name]",
|
||||
Action: secretUpdate,
|
||||
Flags: append(common.GlobalFlags,
|
||||
&cli.BoolFlag{
|
||||
|
@ -71,7 +71,7 @@ func secretUpdate(c *cli.Context) error {
|
|||
secret.Value = string(out)
|
||||
}
|
||||
|
||||
global, owner, repo, err := parseTargetArgs(c)
|
||||
global, owner, repoID, err := parseTargetArgs(client, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -80,10 +80,10 @@ func secretUpdate(c *cli.Context) error {
|
|||
_, err = client.GlobalSecretUpdate(secret)
|
||||
return err
|
||||
}
|
||||
if repo == "" {
|
||||
if owner != "" {
|
||||
_, err = client.OrgSecretUpdate(owner, secret)
|
||||
return err
|
||||
}
|
||||
_, err = client.SecretUpdate(owner, repo, secret)
|
||||
_, err = client.SecretUpdate(repoID, secret)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -250,7 +250,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/badges/{owner}/{name}/cc.xml": {
|
||||
"/badges/{repo_id}/cc.xml": {
|
||||
"get": {
|
||||
"description": "CCMenu displays the pipeline status of projects on a CI server as an item in the Mac's menu bar.\nMore details on how to install, you can find at http://ccmenu.org/\nThe response format adheres to CCTray v1 Specification, https://cctray.org/v1/",
|
||||
"produces": [
|
||||
|
@ -283,7 +283,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/badges/{owner}/{name}/status.svg": {
|
||||
"/badges/{repo_id}/status.svg": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"image/svg+xml"
|
||||
|
@ -294,16 +294,9 @@ const docTemplate = `{
|
|||
"summary": "Get status badge, SVG format",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -751,7 +744,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/logs/{owner}/{name}/{pipeline}/{stepID}": {
|
||||
"/logs/{repo_id}/{pipeline}/{stepID}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"text/plain"
|
||||
|
@ -762,16 +755,9 @@ const docTemplate = `{
|
|||
"summary": "Log stream",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1206,7 +1192,43 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}": {
|
||||
"/repos/lookup/{repo_full_name}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Repositories"
|
||||
],
|
||||
"summary": "Get repository by full-name",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"default": "Bearer \u003cpersonal access token\u003e",
|
||||
"description": "Insert your personal access token",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository full-name / slug",
|
||||
"name": "repo_full_name",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Repo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{repo_id}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1225,16 +1247,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -1266,16 +1281,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -1307,16 +1315,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -1348,16 +1349,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1381,7 +1375,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/branches": {
|
||||
"/repos/{repo_id}/branches": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1400,16 +1394,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1441,7 +1428,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/chown": {
|
||||
"/repos/{repo_id}/chown": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1460,16 +1447,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -1484,7 +1464,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/cron": {
|
||||
"/repos/{repo_id}/cron": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1503,16 +1483,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1561,16 +1534,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1594,7 +1560,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/cron/{cron}": {
|
||||
"/repos/{repo_id}/cron/{cron}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1613,16 +1579,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1661,16 +1620,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1709,16 +1661,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1754,16 +1699,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1794,7 +1732,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/logs/{number}": {
|
||||
"/repos/{repo_id}/logs/{number}": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"text/plain"
|
||||
|
@ -1813,16 +1751,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1841,7 +1772,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/logs/{number}/{stepID}": {
|
||||
"/repos/{repo_id}/logs/{number}/{stepID}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -1860,16 +1791,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1901,7 +1825,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/move": {
|
||||
"/repos/{repo_id}/move": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"text/plain"
|
||||
|
@ -1920,16 +1844,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -1948,7 +1865,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/permissions": {
|
||||
"/repos/{repo_id}/permissions": {
|
||||
"get": {
|
||||
"description": "The repository permission, according to the used access token.",
|
||||
"produces": [
|
||||
|
@ -1992,7 +1909,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines": {
|
||||
"/repos/{repo_id}/pipelines": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2011,16 +1928,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2069,16 +1979,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2102,7 +2005,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines/{number}": {
|
||||
"/repos/{repo_id}/pipelines/{number}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2121,16 +2024,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2213,7 +2109,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines/{number}/approve": {
|
||||
"/repos/{repo_id}/pipelines/{number}/approve": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2232,16 +2128,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2263,7 +2152,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines/{number}/cancel": {
|
||||
"/repos/{repo_id}/pipelines/{number}/cancel": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"text/plain"
|
||||
|
@ -2282,16 +2171,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2310,7 +2192,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines/{number}/config": {
|
||||
"/repos/{repo_id}/pipelines/{number}/config": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2329,16 +2211,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2363,7 +2238,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pipelines/{number}/decline": {
|
||||
"/repos/{repo_id}/pipelines/{number}/decline": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2382,16 +2257,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2413,7 +2281,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/pull_requests": {
|
||||
"/repos/{repo_id}/pull_requests": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2432,16 +2300,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2473,7 +2334,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/registry": {
|
||||
"/repos/{repo_id}/registry": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2492,16 +2353,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2550,16 +2404,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2583,7 +2430,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/registry/{registry}": {
|
||||
"/repos/{repo_id}/registry/{registry}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2602,16 +2449,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2650,16 +2490,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2695,16 +2528,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2735,7 +2561,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/repair": {
|
||||
"/repos/{repo_id}/repair": {
|
||||
"post": {
|
||||
"produces": [
|
||||
"text/plain"
|
||||
|
@ -2754,16 +2580,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
|
@ -2775,7 +2594,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/secrets": {
|
||||
"/repos/{repo_id}/secrets": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2794,16 +2613,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2852,16 +2664,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2885,7 +2690,7 @@ const docTemplate = `{
|
|||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{name}/secrets/{secretName}": {
|
||||
"/repos/{repo_id}/secrets/{secretName}": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
|
@ -2904,16 +2709,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2952,16 +2750,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -2997,16 +2788,9 @@ const docTemplate = `{
|
|||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository owner's name",
|
||||
"name": "owner",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "the repository name",
|
||||
"name": "name",
|
||||
"type": "integer",
|
||||
"description": "the repository id",
|
||||
"name": "repo_id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
|
@ -3753,24 +3537,15 @@ const docTemplate = `{
|
|||
"finished_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "integer"
|
||||
},
|
||||
"owner": {
|
||||
"type": "string"
|
||||
},
|
||||
"ref": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -3780,6 +3555,9 @@ const docTemplate = `{
|
|||
"remote": {
|
||||
"type": "string"
|
||||
},
|
||||
"repo_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"started_at": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -4037,6 +3815,10 @@ const docTemplate = `{
|
|||
"default_branch": {
|
||||
"type": "string"
|
||||
},
|
||||
"forge_remote_id": {
|
||||
"description": "ForgeRemoteID is the unique identifier for the repository on the forge.",
|
||||
"type": "string"
|
||||
},
|
||||
"full_name": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
@ -5,14 +5,14 @@ Woodpecker has integrated support for repository status badges. These badges can
|
|||
## Badge endpoint
|
||||
|
||||
```text
|
||||
<scheme>://<hostname>/api/badges/<owner>/<repo>/status.svg
|
||||
<scheme>://<hostname>/api/badges/<repo-id>/status.svg
|
||||
```
|
||||
|
||||
The status badge displays the status for the latest build to your default branch (e.g. master). You can customize the branch by adding the `branch` query parameter.
|
||||
|
||||
```diff
|
||||
-<scheme>://<hostname>/api/badges/<owner>/<repo>/status.svg
|
||||
+<scheme>://<hostname>/api/badges/<owner>/<repo>/status.svg?branch=<branch>
|
||||
-<scheme>://<hostname>/api/badges/<repo-id>/status.svg
|
||||
+<scheme>://<hostname>/api/badges/<repo-id>/status.svg?branch=<branch>
|
||||
```
|
||||
|
||||
Please note status badges do not include pull request results, since the status of a pull request does not provide an accurate representation of your repository state.
|
||||
|
|
|
@ -19,7 +19,13 @@ Some versions need some changes to the server configuration or the pipeline conf
|
|||
- Dropped support for [Coding](https://coding.net/) and [Gogs](https://gogs.io).
|
||||
- `/api/queue/resume` & `/api/queue/pause` endpoint methods were changed from `GET` to `POST`
|
||||
- rename `pipeline:` key in your workflow config to `steps:`
|
||||
- If you want to migrate old logs to the new format, watch the error messages on start. If there are none we are good to go, else you have to plan a migration that can take hours. Set `WOODPECKER_ALLOW_LONG_MIGRATION` to true and let it run.
|
||||
- If you want to migrate old logs to the new format, watch the error messages on start. If there are none we are good to go, else you have to plan a migration that can take hours. Set `WOODPECKER_MIGRATIONS_ALLOW_LONG` to true and let it run.
|
||||
- Using `repo-id` in favor of `owner/repo` combination
|
||||
- :warning: The api endpoints `/api/repos/{owner}/{repo}/...` were replaced by new endpoints using the repos id `/api/repos/{repo-id}`
|
||||
- To find the id of a repo use the `/api/repos/lookup/{repo-full-name-with-slashes}` endpoint.
|
||||
- The existing badge endpoint `/api/badges/{owner}/{repo}` will still work, but whenever possible try to use the new endpoint using the `repo-id`: `/api/badges/{repo-id}`.
|
||||
- The UI urls for a repository changed from `/repos/{owner}/{repo}/...` to `/repos/{repo-id}/...`. You will be redirected automatically when using the old url.
|
||||
- The woodpecker-go api-client is now using the `repo-id` instead of `owner/repo` for all functions
|
||||
|
||||
## 0.15.0
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -37,15 +38,29 @@ import (
|
|||
// GetBadge
|
||||
//
|
||||
// @Summary Get status badge, SVG format
|
||||
// @Router /badges/{owner}/{name}/status.svg [get]
|
||||
// @Router /badges/{repo_id}/status.svg [get]
|
||||
// @Produce image/svg+xml
|
||||
// @Success 200
|
||||
// @Tags Badges
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func GetBadge(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
repo, err := _store.GetRepoName(c.Param("owner") + "/" + c.Param("name"))
|
||||
|
||||
var repo *model.Repo
|
||||
var err error
|
||||
|
||||
if c.Param("repo_name") != "" {
|
||||
repo, err = _store.GetRepoName(c.Param("repo_id_or_owner") + "/" + c.Param("repo_name"))
|
||||
} else {
|
||||
var repoID int64
|
||||
repoID, err = strconv.ParseInt(c.Param("repo_id_or_owner"), 10, 64)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
repo, err = _store.GetRepo(repoID)
|
||||
}
|
||||
|
||||
if err != nil || !repo.IsActive {
|
||||
if err == nil || errors.Is(err, types.RecordNotExist) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
|
@ -80,7 +95,7 @@ func GetBadge(c *gin.Context) {
|
|||
// @Description CCMenu displays the pipeline status of projects on a CI server as an item in the Mac's menu bar.
|
||||
// @Description More details on how to install, you can find at http://ccmenu.org/
|
||||
// @Description The response format adheres to CCTray v1 Specification, https://cctray.org/v1/
|
||||
// @Router /badges/{owner}/{name}/cc.xml [get]
|
||||
// @Router /badges/{repo_id}/cc.xml [get]
|
||||
// @Produce xml
|
||||
// @Success 200
|
||||
// @Tags Badges
|
||||
|
|
|
@ -31,13 +31,12 @@ import (
|
|||
// GetCron
|
||||
//
|
||||
// @Summary Get a cron job by id
|
||||
// @Router /repos/{owner}/{name}/cron/{cron} [get]
|
||||
// @Router /repos/{repo_id}/cron/{cron} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Cron
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param cron path string true "the cron job id"
|
||||
func GetCron(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
@ -58,13 +57,12 @@ func GetCron(c *gin.Context) {
|
|||
// RunCron
|
||||
//
|
||||
// @Summary Start a cron job now
|
||||
// @Router /repos/{owner}/{name}/cron/{cron} [post]
|
||||
// @Router /repos/{repo_id}/cron/{cron} [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param cron path string true "the cron job id"
|
||||
func RunCron(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
@ -99,13 +97,12 @@ func RunCron(c *gin.Context) {
|
|||
// PostCron
|
||||
//
|
||||
// @Summary Persist/creat a cron job
|
||||
// @Router /repos/{owner}/{name}/cron [post]
|
||||
// @Router /repos/{repo_id}/cron [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Cron
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param cronJob body Cron true "the new cron job"
|
||||
func PostCron(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
@ -156,13 +153,12 @@ func PostCron(c *gin.Context) {
|
|||
// PatchCron
|
||||
//
|
||||
// @Summary Update a cron job
|
||||
// @Router /repos/{owner}/{name}/cron/{cron} [patch]
|
||||
// @Router /repos/{repo_id}/cron/{cron} [patch]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Cron
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param cron path string true "the cron job id"
|
||||
// @Param cronJob body Cron true "the cron job data"
|
||||
func PatchCron(c *gin.Context) {
|
||||
|
@ -226,13 +222,12 @@ func PatchCron(c *gin.Context) {
|
|||
// GetCronList
|
||||
//
|
||||
// @Summary Get the cron job list
|
||||
// @Router /repos/{owner}/{name}/cron [get]
|
||||
// @Router /repos/{repo_id}/cron [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} Cron
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetCronList(c *gin.Context) {
|
||||
|
@ -248,13 +243,12 @@ func GetCronList(c *gin.Context) {
|
|||
// DeleteCron
|
||||
//
|
||||
// @Summary Delete a cron job by id
|
||||
// @Router /repos/{owner}/{name}/cron/{cron} [delete]
|
||||
// @Router /repos/{repo_id}/cron/{cron} [delete]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Repository cron jobs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param cron path string true "the cron job id"
|
||||
func DeleteCron(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
|
|
@ -39,13 +39,12 @@ import (
|
|||
// CreatePipeline
|
||||
//
|
||||
// @Summary Run/trigger a pipelines
|
||||
// @Router /repos/{owner}/{name}/pipelines [post]
|
||||
// @Router /repos/{repo_id}/pipelines [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Pipelines
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param options body PipelineOptions true "the options for the pipeline to run"
|
||||
func CreatePipeline(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
@ -97,15 +96,14 @@ func createTmpPipeline(event model.WebhookEvent, commitSHA string, repo *model.R
|
|||
// GetPipelines
|
||||
//
|
||||
// @Summary Get pipelines, current running and past ones
|
||||
// @Router /repos/{owner}/{name}/pipelines [get]
|
||||
// @Router /repos/{repo_id}/pipelines [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} Pipeline
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetPipelines(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
||||
|
@ -124,14 +122,13 @@ func GetPipelines(c *gin.Context) {
|
|||
// GetPipeline
|
||||
//
|
||||
// @Summary Pipeline information by number
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number} [get]
|
||||
// @Router /repos/{repo_id}/pipelines/{number} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param number path int true "the number of the pipeline, OR 'latest'"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline, OR 'latest'"
|
||||
func GetPipeline(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
if c.Param("number") == "latest" {
|
||||
|
@ -190,13 +187,12 @@ func GetPipelineLast(c *gin.Context) {
|
|||
// GetStepLogs
|
||||
//
|
||||
// @Summary Log information
|
||||
// @Router /repos/{owner}/{name}/logs/{number}/{stepID} [get]
|
||||
// @Router /repos/{repo_id}/logs/{number}/{stepID} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} LogEntry
|
||||
// @Tags Pipeline logs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
// @Param stepID path int true "the step id"
|
||||
func GetStepLogs(c *gin.Context) {
|
||||
|
@ -247,13 +243,12 @@ func GetStepLogs(c *gin.Context) {
|
|||
// GetPipelineConfig
|
||||
//
|
||||
// @Summary Pipeline configuration
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number}/config [get]
|
||||
// @Router /repos/{repo_id}/pipelines/{number}/config [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} Config
|
||||
// @Tags Pipelines
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
func GetPipelineConfig(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
@ -282,13 +277,12 @@ func GetPipelineConfig(c *gin.Context) {
|
|||
// CancelPipeline
|
||||
//
|
||||
// @Summary Cancels a pipeline
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number}/cancel [post]
|
||||
// @Router /repos/{repo_id}/pipelines/{number}/cancel [post]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
func CancelPipeline(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
@ -312,13 +306,12 @@ func CancelPipeline(c *gin.Context) {
|
|||
// PostApproval
|
||||
//
|
||||
// @Summary Start pipelines in gated repos
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number}/approve [post]
|
||||
// @Router /repos/{repo_id}/pipelines/{number}/approve [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
func PostApproval(c *gin.Context) {
|
||||
var (
|
||||
|
@ -345,13 +338,12 @@ func PostApproval(c *gin.Context) {
|
|||
// PostDecline
|
||||
//
|
||||
// @Summary Decline pipelines in gated repos
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number}/decline [post]
|
||||
// @Router /repos/{repo_id}/pipelines/{number}/decline [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Pipelines
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
func PostDecline(c *gin.Context) {
|
||||
var (
|
||||
|
@ -396,7 +388,7 @@ func GetPipelineQueue(c *gin.Context) {
|
|||
//
|
||||
// @Summary Restart a pipeline
|
||||
// @Description Restarts a pipeline optional with altered event, deploy or environment
|
||||
// @Router /repos/{owner}/{name}/pipelines/{number} [post]
|
||||
// @Router /repos/{repo_id}/pipelines/{number} [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Pipeline
|
||||
// @Tags Pipelines
|
||||
|
@ -478,13 +470,12 @@ func PostPipeline(c *gin.Context) {
|
|||
// DeletePipelineLogs
|
||||
//
|
||||
// @Summary Deletes log
|
||||
// @Router /repos/{owner}/{name}/logs/{number} [post]
|
||||
// @Router /repos/{repo_id}/logs/{number} [post]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Pipeline logs
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param number path int true "the number of the pipeline"
|
||||
func DeletePipelineLogs(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
|
|
@ -27,13 +27,12 @@ import (
|
|||
// GetRegistry
|
||||
//
|
||||
// @Summary Get a named registry
|
||||
// @Router /repos/{owner}/{name}/registry/{registry} [get]
|
||||
// @Router /repos/{repo_id}/registry/{registry} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Registry
|
||||
// @Tags Repository registries
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param registry path string true "the registry name"
|
||||
func GetRegistry(c *gin.Context) {
|
||||
var (
|
||||
|
@ -51,13 +50,12 @@ func GetRegistry(c *gin.Context) {
|
|||
// PostRegistry
|
||||
//
|
||||
// @Summary Persist/create a registry
|
||||
// @Router /repos/{owner}/{name}/registry [post]
|
||||
// @Router /repos/{repo_id}/registry [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Registry
|
||||
// @Tags Repository registries
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param registry body Registry true "the new registry data"
|
||||
func PostRegistry(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
@ -89,13 +87,12 @@ func PostRegistry(c *gin.Context) {
|
|||
// PatchRegistry
|
||||
//
|
||||
// @Summary Update a named registry
|
||||
// @Router /repos/{owner}/{name}/registry/{registry} [patch]
|
||||
// @Router /repos/{repo_id}/registry/{registry} [patch]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Registry
|
||||
// @Tags Repository registries
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param registry path string true "the registry name"
|
||||
// @Param registryData body Registry true "the attributes for the registry"
|
||||
func PatchRegistry(c *gin.Context) {
|
||||
|
@ -143,13 +140,12 @@ func PatchRegistry(c *gin.Context) {
|
|||
// GetRegistryList
|
||||
//
|
||||
// @Summary Get the registry list
|
||||
// @Router /repos/{owner}/{name}/registry [get]
|
||||
// @Router /repos/{repo_id}/registry [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} Registry
|
||||
// @Tags Repository registries
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetRegistryList(c *gin.Context) {
|
||||
|
@ -170,13 +166,12 @@ func GetRegistryList(c *gin.Context) {
|
|||
// DeleteRegistry
|
||||
//
|
||||
// @Summary Delete a named registry
|
||||
// @Router /repos/{owner}/{name}/registry/{registry} [delete]
|
||||
// @Router /repos/{repo_id}/registry/{registry} [delete]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Repository registries
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param registry path string true "the registry name"
|
||||
func DeleteRegistry(c *gin.Context) {
|
||||
var (
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -38,21 +39,19 @@ import (
|
|||
// PostRepo
|
||||
//
|
||||
// @Summary Activate a repository
|
||||
// @Router /repos/{owner}/{name} [post]
|
||||
// @Router /repos/{repo_id} [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func PostRepo(c *gin.Context) {
|
||||
forge := server.Config.Services.Forge
|
||||
_store := store.FromContext(c)
|
||||
user := session.User(c)
|
||||
|
||||
owner := c.Param("owner")
|
||||
name := c.Param("name")
|
||||
repo, err := _store.GetRepoName(owner + "/" + name)
|
||||
forgeRemoteID := model.ForgeRemoteID(c.Query("forge_remote_id"))
|
||||
repo, err := _store.GetRepoForgeID(forgeRemoteID)
|
||||
enabledOnce := err == nil // if there's no error, the repo was found and enabled once already
|
||||
if enabledOnce && repo.IsActive {
|
||||
c.String(http.StatusConflict, "Repository is already active.")
|
||||
|
@ -62,7 +61,7 @@ func PostRepo(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
from, err := forge.Repo(c, user, "0", owner, name)
|
||||
from, err := forge.Repo(c, user, forgeRemoteID, "", "")
|
||||
if err != nil {
|
||||
c.String(http.StatusInternalServerError, "Could not fetch repository from forge.")
|
||||
return
|
||||
|
@ -147,13 +146,12 @@ func PostRepo(c *gin.Context) {
|
|||
// PatchRepo
|
||||
//
|
||||
// @Summary Change a repository
|
||||
// @Router /repos/{owner}/{name} [patch]
|
||||
// @Router /repos/{repo_id} [patch]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param repo body RepoPatch true "the repository's information"
|
||||
func PatchRepo(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
|
@ -218,13 +216,12 @@ func PatchRepo(c *gin.Context) {
|
|||
// ChownRepo
|
||||
//
|
||||
// @Summary Change a repository's owner, to the one holding the access token
|
||||
// @Router /repos/{owner}/{name}/chown [post]
|
||||
// @Router /repos/{repo_id}/chown [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func ChownRepo(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
repo := session.Repo(c)
|
||||
|
@ -239,16 +236,42 @@ func ChownRepo(c *gin.Context) {
|
|||
c.JSON(http.StatusOK, repo)
|
||||
}
|
||||
|
||||
// GetRepo
|
||||
// LookupRepo
|
||||
//
|
||||
// @Summary Get repository information
|
||||
// @Router /repos/{owner}/{name} [get]
|
||||
// @Summary Get repository by full-name
|
||||
// @Router /repos/lookup/{repo_full_name} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_full_name path string true "the repository full-name / slug"
|
||||
func LookupRepo(c *gin.Context) {
|
||||
_store := store.FromContext(c)
|
||||
repoFullName := strings.TrimLeft(c.Param("repo_full_name"), "/")
|
||||
|
||||
repo, err := _store.GetRepoName(repoFullName)
|
||||
if err != nil {
|
||||
if errors.Is(err, types.RecordNotExist) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, repo)
|
||||
}
|
||||
|
||||
// GetRepo
|
||||
//
|
||||
// @Summary Get repository information
|
||||
// @Router /repos/{repo_id} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func GetRepo(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, session.Repo(c))
|
||||
}
|
||||
|
@ -257,7 +280,7 @@ func GetRepo(c *gin.Context) {
|
|||
//
|
||||
// @Summary Repository permission information
|
||||
// @Description The repository permission, according to the used access token.
|
||||
// @Router /repos/{owner}/{name}/permissions [get]
|
||||
// @Router /repos/{repo_id}/permissions [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Perm
|
||||
// @Tags Repositories
|
||||
|
@ -272,13 +295,12 @@ func GetRepoPermissions(c *gin.Context) {
|
|||
// GetRepoBranches
|
||||
//
|
||||
// @Summary Get repository branches
|
||||
// @Router /repos/{owner}/{name}/branches [get]
|
||||
// @Router /repos/{repo_id}/branches [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} string
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetRepoBranches(c *gin.Context) {
|
||||
|
@ -298,13 +320,12 @@ func GetRepoBranches(c *gin.Context) {
|
|||
// GetRepoPullRequests
|
||||
//
|
||||
// @Summary List active pull requests
|
||||
// @Router /repos/{owner}/{name}/pull_requests [get]
|
||||
// @Router /repos/{repo_id}/pull_requests [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} PullRequest
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetRepoPullRequests(c *gin.Context) {
|
||||
|
@ -324,13 +345,12 @@ func GetRepoPullRequests(c *gin.Context) {
|
|||
// DeleteRepo
|
||||
//
|
||||
// @Summary Delete a repository
|
||||
// @Router /repos/{owner}/{name} [delete]
|
||||
// @Router /repos/{repo_id} [delete]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Repo
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func DeleteRepo(c *gin.Context) {
|
||||
remove, _ := strconv.ParseBool(c.Query("remove"))
|
||||
_store := store.FromContext(c)
|
||||
|
@ -363,13 +383,12 @@ func DeleteRepo(c *gin.Context) {
|
|||
// RepairRepo
|
||||
//
|
||||
// @Summary Repair a repository
|
||||
// @Router /repos/{owner}/{name}/repair [post]
|
||||
// @Router /repos/{repo_id}/repair [post]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
func RepairRepo(c *gin.Context) {
|
||||
forge := server.Config.Services.Forge
|
||||
_store := store.FromContext(c)
|
||||
|
@ -435,13 +454,12 @@ func RepairRepo(c *gin.Context) {
|
|||
// MoveRepo
|
||||
//
|
||||
// @Summary Move a repository to a new owner
|
||||
// @Router /repos/{owner}/{name}/move [post]
|
||||
// @Router /repos/{repo_id}/move [post]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Repositories
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param to query string true "the username to move the repository to"
|
||||
func MoveRepo(c *gin.Context) {
|
||||
forge := server.Config.Services.Forge
|
||||
|
|
|
@ -28,13 +28,12 @@ import (
|
|||
// GetSecret
|
||||
//
|
||||
// @Summary Get a named secret
|
||||
// @Router /repos/{owner}/{name}/secrets/{secretName} [get]
|
||||
// @Router /repos/{repo_id}/secrets/{secretName} [get]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Secret
|
||||
// @Tags Repository secrets
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param secretName path string true "the secret name"
|
||||
func GetSecret(c *gin.Context) {
|
||||
var (
|
||||
|
@ -52,13 +51,12 @@ func GetSecret(c *gin.Context) {
|
|||
// PostSecret
|
||||
//
|
||||
// @Summary Persist/create a secret
|
||||
// @Router /repos/{owner}/{name}/secrets [post]
|
||||
// @Router /repos/{repo_id}/secrets [post]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Secret
|
||||
// @Tags Repository secrets
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param secret body Secret true "the new secret"
|
||||
func PostSecret(c *gin.Context) {
|
||||
repo := session.Repo(c)
|
||||
|
@ -90,13 +88,12 @@ func PostSecret(c *gin.Context) {
|
|||
// PatchSecret
|
||||
//
|
||||
// @Summary Update a named secret
|
||||
// @Router /repos/{owner}/{name}/secrets/{secretName} [patch]
|
||||
// @Router /repos/{repo_id}/secrets/{secretName} [patch]
|
||||
// @Produce json
|
||||
// @Success 200 {object} Secret
|
||||
// @Tags Repository secrets
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param secretName path string true "the secret name"
|
||||
// @Param secret body Secret true "the secret itself"
|
||||
func PatchSecret(c *gin.Context) {
|
||||
|
@ -142,13 +139,12 @@ func PatchSecret(c *gin.Context) {
|
|||
// GetSecretList
|
||||
//
|
||||
// @Summary Get the secret list
|
||||
// @Router /repos/{owner}/{name}/secrets [get]
|
||||
// @Router /repos/{repo_id}/secrets [get]
|
||||
// @Produce json
|
||||
// @Success 200 {array} Secret
|
||||
// @Tags Repository secrets
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param page query int false "for response pagination, page offset number" default(1)
|
||||
// @Param perPage query int false "for response pagination, max items per page" default(50)
|
||||
func GetSecretList(c *gin.Context) {
|
||||
|
@ -169,13 +165,12 @@ func GetSecretList(c *gin.Context) {
|
|||
// DeleteSecret
|
||||
//
|
||||
// @Summary Delete a named secret
|
||||
// @Router /repos/{owner}/{name}/secrets/{secretName} [delete]
|
||||
// @Router /repos/{repo_id}/secrets/{secretName} [delete]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Repository secrets
|
||||
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param secretName path string true "the secret name"
|
||||
func DeleteSecret(c *gin.Context) {
|
||||
var (
|
||||
|
|
|
@ -124,12 +124,11 @@ func EventStreamSSE(c *gin.Context) {
|
|||
// LogStream
|
||||
//
|
||||
// @Summary Log stream
|
||||
// @Router /logs/{owner}/{name}/{pipeline}/{stepID} [get]
|
||||
// @Router /logs/{repo_id}/{pipeline}/{stepID} [get]
|
||||
// @Produce plain
|
||||
// @Success 200
|
||||
// @Tags Pipeline logs
|
||||
// @Param owner path string true "the repository owner's name"
|
||||
// @Param name path string true "the repository name"
|
||||
// @Param repo_id path int true "the repository id"
|
||||
// @Param pipeline path int true "the number of the pipeline"
|
||||
// @Param stepID path int true "the step id"
|
||||
func LogStreamSSE(c *gin.Context) {
|
||||
|
|
|
@ -96,9 +96,9 @@ func GetRepos(c *gin.Context) {
|
|||
}
|
||||
|
||||
if all {
|
||||
active := map[string]bool{}
|
||||
active := map[model.ForgeRemoteID]*model.Repo{}
|
||||
for _, r := range activeRepos {
|
||||
active[r.FullName] = r.IsActive
|
||||
active[r.ForgeRemoteID] = r
|
||||
}
|
||||
|
||||
_repos, err := _forge.Repos(c, user)
|
||||
|
@ -106,13 +106,18 @@ func GetRepos(c *gin.Context) {
|
|||
c.String(http.StatusInternalServerError, "Error fetching repository list. %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
var repos []*model.Repo
|
||||
for _, r := range _repos {
|
||||
if r.Perm.Push {
|
||||
if active[r.FullName] {
|
||||
r.IsActive = true
|
||||
if active[r.ForgeRemoteID] != nil && active[r.ForgeRemoteID].IsActive {
|
||||
existingRepo := active[r.ForgeRemoteID]
|
||||
existingRepo.Update(r)
|
||||
existingRepo.IsActive = true
|
||||
repos = append(repos, existingRepo)
|
||||
} else {
|
||||
repos = append(repos, r)
|
||||
}
|
||||
repos = append(repos, r)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ func GetPipelineStatusDescription(status model.StatusValue) string {
|
|||
|
||||
func GetPipelineStatusLink(repo *model.Repo, pipeline *model.Pipeline, step *model.Step) string {
|
||||
if step == nil {
|
||||
return fmt.Sprintf("%s/%s/pipeline/%d", server.Config.Server.Host, repo.FullName, pipeline.Number)
|
||||
return fmt.Sprintf("%s/repos/%d/pipeline/%d", server.Config.Server.Host, repo.ID, pipeline.Number)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/pipeline/%d/%d", server.Config.Server.Host, repo.FullName, pipeline.Number, step.PID)
|
||||
return fmt.Sprintf("%s/repos/%d/pipeline/%d/%d", server.Config.Server.Host, repo.ID, pipeline.Number, step.PID)
|
||||
}
|
||||
|
|
|
@ -290,12 +290,6 @@ func (g *GitLab) Repos(ctx context.Context, user *model.User) ([]*model.Repo, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// TODO(648) remove when woodpecker understands nested repos
|
||||
if strings.Count(repo.FullName, "/") > 1 {
|
||||
log.Debug().Msgf("Skipping nested repository %s for user %s, because they are not supported, yet (see #648).", repo.FullName, user.Login)
|
||||
continue
|
||||
}
|
||||
|
||||
repos = append(repos, repo)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,7 @@ package model
|
|||
|
||||
// Feed represents an item in the user's feed or timeline.
|
||||
type Feed struct {
|
||||
Owner string `json:"owner" xorm:"feed_repo_owner"`
|
||||
Name string `json:"name" xorm:"feed_repo_name"`
|
||||
FullName string `json:"full_name" xorm:"feed_repo_full_name"`
|
||||
|
||||
RepoID int64 `json:"repo_id" xorm:"feed_repo_id"`
|
||||
ID int64 `json:"id,omitempty" xorm:"feed_pipeline_id"`
|
||||
Number int64 `json:"number,omitempty" xorm:"feed_pipeline_number"`
|
||||
Event string `json:"event,omitempty" xorm:"feed_pipeline_event"`
|
||||
|
|
|
@ -25,7 +25,7 @@ type Repo struct {
|
|||
ID int64 `json:"id,omitempty" xorm:"pk autoincr 'repo_id'"`
|
||||
UserID int64 `json:"-" xorm:"repo_user_id"`
|
||||
// ForgeRemoteID is the unique identifier for the repository on the forge.
|
||||
ForgeRemoteID ForgeRemoteID `json:"-" xorm:"forge_remote_id"`
|
||||
ForgeRemoteID ForgeRemoteID `json:"forge_remote_id" xorm:"forge_remote_id"`
|
||||
Owner string `json:"owner" xorm:"UNIQUE(name) 'repo_owner'"`
|
||||
Name string `json:"name" xorm:"UNIQUE(name) 'repo_name'"`
|
||||
FullName string `json:"full_name" xorm:"UNIQUE 'repo_full_name'"`
|
||||
|
|
|
@ -61,8 +61,9 @@ func apiRoutes(e *gin.Engine) {
|
|||
}
|
||||
}
|
||||
|
||||
apiBase.POST("/repos/:owner/:name", session.MustUser(), api.PostRepo)
|
||||
repoBase := apiBase.Group("/repos/:owner/:name")
|
||||
apiBase.GET("/repos/lookup/*repo_full_name", api.LookupRepo) // TODO: check if this public route is a security issue
|
||||
apiBase.POST("/repos", session.MustUser(), api.PostRepo)
|
||||
repoBase := apiBase.Group("/repos/:repo_id")
|
||||
{
|
||||
repoBase.Use(session.SetRepo())
|
||||
repoBase.Use(session.SetPerm())
|
||||
|
@ -125,12 +126,18 @@ func apiRoutes(e *gin.Engine) {
|
|||
}
|
||||
}
|
||||
|
||||
badges := apiBase.Group("/badges/:owner/:name")
|
||||
badges := apiBase.Group("/badges/:repo_id_or_owner")
|
||||
{
|
||||
badges.GET("/status.svg", api.GetBadge)
|
||||
badges.GET("/cc.xml", api.GetCC)
|
||||
}
|
||||
|
||||
_badges := apiBase.Group("/badges/:repo_id_or_owner/:repo_name")
|
||||
{
|
||||
_badges.GET("/status.svg", api.GetBadge)
|
||||
_badges.GET("/cc.xml", api.GetCC)
|
||||
}
|
||||
|
||||
pipelines := apiBase.Group("/pipelines")
|
||||
{
|
||||
pipelines.Use(session.MustAdmin())
|
||||
|
|
|
@ -17,6 +17,7 @@ package session
|
|||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -44,14 +45,28 @@ func Repo(c *gin.Context) *model.Repo {
|
|||
func SetRepo() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var (
|
||||
_store = store.FromContext(c)
|
||||
owner = c.Param("owner")
|
||||
name = c.Param("name")
|
||||
user = User(c)
|
||||
_store = store.FromContext(c)
|
||||
owner = c.Param("owner")
|
||||
name = c.Param("name")
|
||||
_repoID = c.Param("repo_id")
|
||||
user = User(c)
|
||||
)
|
||||
|
||||
repo, err := _store.GetRepoName(owner + "/" + name)
|
||||
if err == nil {
|
||||
var repo *model.Repo
|
||||
var err error
|
||||
if _repoID != "" {
|
||||
var repoID int64
|
||||
repoID, err = strconv.ParseInt(_repoID, 10, 64)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
repo, err = _store.GetRepo(repoID)
|
||||
} else {
|
||||
repo, err = _store.GetRepoName(owner + "/" + name)
|
||||
}
|
||||
|
||||
if repo != nil {
|
||||
c.Set("repo", repo)
|
||||
c.Next()
|
||||
return
|
||||
|
@ -64,15 +79,17 @@ func SetRepo() gin.HandlerFunc {
|
|||
err.Error(),
|
||||
)
|
||||
|
||||
if user != nil {
|
||||
if errors.Is(err, types.RecordNotExist) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
} else {
|
||||
if user == nil {
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
if errors.Is(err, types.RecordNotExist) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
_ = c.AbortWithError(http.StatusInternalServerError, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,7 @@ import (
|
|||
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||
)
|
||||
|
||||
var feedItemSelect = `repos.repo_owner as feed_repo_owner,
|
||||
repos.repo_name as feed_repo_name,
|
||||
repos.repo_full_name as feed_repo_full_name,
|
||||
var feedItemSelect = `repos.repo_id as feed_repo_id,
|
||||
pipelines.pipeline_id as feed_pipeline_id,
|
||||
pipelines.pipeline_number as feed_pipeline_number,
|
||||
pipelines.pipeline_event as feed_pipeline_event,
|
||||
|
|
|
@ -126,6 +126,7 @@ func TestRepoListLatest(t *testing.T) {
|
|||
assert.NoError(t, store.CreateUser(user))
|
||||
|
||||
repo1 := &model.Repo{
|
||||
ID: 1,
|
||||
Owner: "bradrydzewski",
|
||||
Name: "test",
|
||||
FullName: "bradrydzewski/test",
|
||||
|
@ -133,6 +134,7 @@ func TestRepoListLatest(t *testing.T) {
|
|||
IsActive: true,
|
||||
}
|
||||
repo2 := &model.Repo{
|
||||
ID: 2,
|
||||
Owner: "test",
|
||||
Name: "test",
|
||||
FullName: "test/test",
|
||||
|
@ -140,6 +142,7 @@ func TestRepoListLatest(t *testing.T) {
|
|||
IsActive: true,
|
||||
}
|
||||
repo3 := &model.Repo{
|
||||
ID: 3,
|
||||
Owner: "octocat",
|
||||
Name: "hello-world",
|
||||
FullName: "octocat/hello-world",
|
||||
|
@ -189,13 +192,13 @@ func TestRepoListLatest(t *testing.T) {
|
|||
if got, want := pipelines[0].Status, string(model.StatusRunning); want != got {
|
||||
t.Errorf("Want repository status %s, got %s", want, got)
|
||||
}
|
||||
if got, want := pipelines[0].FullName, repo1.FullName; want != got {
|
||||
t.Errorf("Want repository name %s, got %s", want, got)
|
||||
if got, want := pipelines[0].RepoID, repo1.ID; want != got {
|
||||
t.Errorf("Want repository id %d, got %d", want, got)
|
||||
}
|
||||
if got, want := pipelines[1].Status, string(model.StatusKilled); want != got {
|
||||
t.Errorf("Want repository status %s, got %s", want, got)
|
||||
}
|
||||
if got, want := pipelines[1].FullName, repo2.FullName; want != got {
|
||||
t.Errorf("Want repository name %s, got %s", want, got)
|
||||
if got, want := pipelines[1].RepoID, repo2.ID; want != got {
|
||||
t.Errorf("Want repository id %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ func (s storage) GetPipelineLastBefore(repo *model.Repo, branch string, num int6
|
|||
}
|
||||
|
||||
func (s storage) GetPipelineList(repo *model.Repo, p *model.ListOptions) ([]*model.Pipeline, error) {
|
||||
var pipelines []*model.Pipeline
|
||||
pipelines := make([]*model.Pipeline, 0, 16)
|
||||
return pipelines, s.paginate(p).Where("pipeline_repo_id = ?", repo.ID).
|
||||
Desc("pipeline_number").
|
||||
Find(&pipelines)
|
||||
|
|
|
@ -245,9 +245,9 @@ func TestUsers(t *testing.T) {
|
|||
pipelines, err := store.UserFeed(user)
|
||||
g.Assert(err).IsNil()
|
||||
g.Assert(len(pipelines)).Equal(3)
|
||||
g.Assert(pipelines[0].FullName).Equal(repo2.FullName)
|
||||
g.Assert(pipelines[1].FullName).Equal(repo1.FullName)
|
||||
g.Assert(pipelines[2].FullName).Equal(repo1.FullName)
|
||||
g.Assert(pipelines[0].RepoID).Equal(repo2.ID)
|
||||
g.Assert(pipelines[1].RepoID).Equal(repo1.ID)
|
||||
g.Assert(pipelines[2].RepoID).Equal(repo1.ID)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -99,12 +99,7 @@ function deleteVar(key: string) {
|
|||
const pipelineNumber = toRef(props, 'pipelineNumber');
|
||||
async function triggerDeployPipeline() {
|
||||
loading.value = true;
|
||||
const newPipeline = await apiClient.deployPipeline(
|
||||
repo.value.owner,
|
||||
repo.value.name,
|
||||
pipelineNumber.value,
|
||||
payload.value,
|
||||
);
|
||||
const newPipeline = await apiClient.deployPipeline(repo.value.id, pipelineNumber.value, payload.value);
|
||||
|
||||
emit('close');
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ const newPipelineVariable = ref<{ name: string; value: string }>({ name: '', val
|
|||
|
||||
const loading = ref(true);
|
||||
onMounted(async () => {
|
||||
const data = await usePaginate((page) => apiClient.getRepoBranches(repo.value.owner, repo.value.name, page));
|
||||
const data = await usePaginate((page) => apiClient.getRepoBranches(repo.value.id, page));
|
||||
branches.value = data.map((e) => ({
|
||||
text: e,
|
||||
value: e,
|
||||
|
@ -103,7 +103,7 @@ function deleteVar(key: string) {
|
|||
|
||||
async function triggerManualPipeline() {
|
||||
loading.value = true;
|
||||
const pipeline = await apiClient.createPipeline(repo.value.owner, repo.value.name, payload.value);
|
||||
const pipeline = await apiClient.createPipeline(repo.value.id, payload.value);
|
||||
|
||||
emit('close');
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div v-if="pipeline" class="flex text-color w-full">
|
||||
<PipelineStatusIcon :status="pipeline.status" class="flex items-center" />
|
||||
<div class="flex flex-col ml-4 min-w-0">
|
||||
<span class="underline">{{ pipeline.owner }} / {{ pipeline.name }}</span>
|
||||
<span class="underline">{{ repo?.owner }} / {{ repo?.name }}</span>
|
||||
<span class="whitespace-nowrap overflow-hidden overflow-ellipsis">{{ message }}</span>
|
||||
<div class="flex flex-col mt-2">
|
||||
<div class="flex space-x-2 items-center">
|
||||
|
@ -23,32 +23,24 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script lang="ts" setup>
|
||||
import { Tooltip } from 'floating-vue';
|
||||
import { defineComponent, PropType, toRef } from 'vue';
|
||||
import { computed, toRef } from 'vue';
|
||||
|
||||
import Icon from '~/components/atomic/Icon.vue';
|
||||
import PipelineStatusIcon from '~/components/repo/pipeline/PipelineStatusIcon.vue';
|
||||
import usePipeline from '~/compositions/usePipeline';
|
||||
import { PipelineFeed } from '~/lib/api/types';
|
||||
import { useRepoStore } from '~/store/repos';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PipelineFeedItem',
|
||||
const props = defineProps<{
|
||||
pipeline: PipelineFeed;
|
||||
}>();
|
||||
|
||||
components: { PipelineStatusIcon, Icon, Tooltip },
|
||||
const repoStore = useRepoStore();
|
||||
|
||||
props: {
|
||||
pipeline: {
|
||||
type: Object as PropType<PipelineFeed>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
const pipeline = toRef(props, 'pipeline');
|
||||
const repo = repoStore.getRepo(computed(() => pipeline.value.repo_id));
|
||||
|
||||
setup(props) {
|
||||
const pipeline = toRef(props, 'pipeline');
|
||||
const { since, duration, message, created } = usePipeline(pipeline);
|
||||
|
||||
return { since, duration, message, created };
|
||||
},
|
||||
});
|
||||
const { since, duration, message, created } = usePipeline(pipeline);
|
||||
</script>
|
||||
|
|
|
@ -1,43 +1,29 @@
|
|||
<template>
|
||||
<aside
|
||||
v-if="isPipelineFeedOpen"
|
||||
v-if="isOpen"
|
||||
class="flex flex-col z-50 overflow-y-auto items-center bg-white dark:bg-dark-gray-800 dark:border-dark-500"
|
||||
:aria-label="$t('pipeline_feed')"
|
||||
>
|
||||
<router-link
|
||||
v-for="pipeline in sortedPipelineFeed"
|
||||
v-for="pipeline in sortedPipelines"
|
||||
:key="pipeline.id"
|
||||
:to="{
|
||||
name: 'repo-pipeline',
|
||||
params: { repoOwner: pipeline.owner, repoName: pipeline.name, pipelineId: pipeline.number },
|
||||
params: { repoId: pipeline.repo_id, pipelineId: pipeline.number },
|
||||
}"
|
||||
class="flex border-b py-4 px-2 w-full hover:bg-light-300 dark:hover:bg-dark-gray-900 dark:border-dark-gray-600 hover:shadow-sm"
|
||||
>
|
||||
<PipelineFeedItem :pipeline="pipeline" />
|
||||
</router-link>
|
||||
|
||||
<span v-if="sortedPipelineFeed.length === 0" class="text-color m-4">{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
<span v-if="sortedPipelines.length === 0" class="text-color m-4">{{ $t('repo.pipeline.no_pipelines') }}</span>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
<script lang="ts" setup>
|
||||
import PipelineFeedItem from '~/components/pipeline-feed/PipelineFeedItem.vue';
|
||||
import usePipelineFeed from '~/compositions/usePipelineFeed';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PipelineFeedSidebar',
|
||||
|
||||
components: { PipelineFeedItem },
|
||||
|
||||
setup() {
|
||||
const pipelineFeed = usePipelineFeed();
|
||||
|
||||
return {
|
||||
isPipelineFeedOpen: pipelineFeed.isOpen,
|
||||
sortedPipelineFeed: pipelineFeed.sortedPipelines,
|
||||
};
|
||||
},
|
||||
});
|
||||
const pipelineFeed = usePipelineFeed();
|
||||
const { isOpen, sortedPipelines } = pipelineFeed;
|
||||
</script>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
:key="pipeline.id"
|
||||
:to="{
|
||||
name: 'repo-pipeline',
|
||||
params: { repoOwner: repo.owner, repoName: repo.name, pipelineId: pipeline.number },
|
||||
params: { pipelineId: pipeline.number },
|
||||
}"
|
||||
:pipeline="pipeline"
|
||||
/>
|
||||
|
@ -15,28 +15,12 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from 'vue';
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Panel from '~/components/layout/Panel.vue';
|
||||
import PipelineItem from '~/components/repo/pipeline/PipelineItem.vue';
|
||||
import { Pipeline, Repo } from '~/lib/api/types';
|
||||
import { Pipeline } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PipelineList',
|
||||
|
||||
components: { Panel, PipelineItem },
|
||||
|
||||
props: {
|
||||
repo: {
|
||||
type: Object as PropType<Repo>,
|
||||
required: true,
|
||||
},
|
||||
|
||||
pipelines: {
|
||||
type: Object as PropType<Pipeline[] | undefined>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
defineProps<{
|
||||
pipelines: Pipeline[] | undefined;
|
||||
}>();
|
||||
</script>
|
||||
|
|
|
@ -190,7 +190,7 @@ async function download() {
|
|||
let logs;
|
||||
try {
|
||||
downloadInProgress.value = true;
|
||||
logs = await apiClient.getLogs(repo.value.owner, repo.value.name, pipeline.value.number, step.value.id);
|
||||
logs = await apiClient.getLogs(repo.value.id, pipeline.value.number, step.value.id);
|
||||
} catch (e) {
|
||||
notifications.notifyError(e, i18n.t('repo.pipeline.log_download_error'));
|
||||
return;
|
||||
|
@ -239,22 +239,16 @@ async function loadLogs() {
|
|||
}
|
||||
|
||||
if (isStepFinished(step.value)) {
|
||||
const logs = await apiClient.getLogs(repo.value.owner, repo.value.name, pipeline.value.number, step.value.id);
|
||||
const logs = await apiClient.getLogs(repo.value.id, pipeline.value.number, step.value.id);
|
||||
logs?.forEach((line) => writeLog({ index: line.line, text: atob(line.data), time: line.time }));
|
||||
flushLogs(false);
|
||||
}
|
||||
|
||||
if (isStepRunning(step.value)) {
|
||||
stream.value = apiClient.streamLogs(
|
||||
repo.value.owner,
|
||||
repo.value.name,
|
||||
pipeline.value.number,
|
||||
step.value.id,
|
||||
(line) => {
|
||||
writeLog({ index: line.line, text: atob(line.data), time: line.time });
|
||||
flushLogs(true);
|
||||
},
|
||||
);
|
||||
stream.value = apiClient.streamLogs(repo.value.id, pipeline.value.number, step.value.id, (line) => {
|
||||
writeLog({ index: line.line, text: atob(line.data), time: line.time });
|
||||
flushLogs(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
</Panel>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject, Ref } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, Ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
@ -57,74 +57,56 @@ import { useAsyncAction } from '~/compositions/useAsyncAction';
|
|||
import useNotifications from '~/compositions/useNotifications';
|
||||
import { Repo } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ActionsTab',
|
||||
const apiClient = useApiClient();
|
||||
const router = useRouter();
|
||||
const notifications = useNotifications();
|
||||
const i18n = useI18n();
|
||||
|
||||
components: { Button, Panel },
|
||||
const repo = inject<Ref<Repo>>('repo');
|
||||
|
||||
setup() {
|
||||
const apiClient = useApiClient();
|
||||
const router = useRouter();
|
||||
const notifications = useNotifications();
|
||||
const i18n = useI18n();
|
||||
const { doSubmit: repairRepo, isLoading: isRepairingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
const repo = inject<Ref<Repo>>('repo');
|
||||
|
||||
const { doSubmit: repairRepo, isLoading: isRepairingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await apiClient.repairRepo(repo.value.owner, repo.value.name);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.repair.success'), type: 'success' });
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRepo, isLoading: isDeletingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
// TODO use proper dialog
|
||||
// eslint-disable-next-line no-alert, no-restricted-globals
|
||||
if (!confirm(i18n.t('repo.settings.actions.delete.confirm'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
await apiClient.deleteRepo(repo.value.owner, repo.value.name);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.delete.success'), type: 'success' });
|
||||
await router.replace({ name: 'repos' });
|
||||
});
|
||||
|
||||
const { doSubmit: activateRepo, isLoading: isActivatingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await apiClient.activateRepo(repo.value.owner, repo.value.name);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.enable.success'), type: 'success' });
|
||||
});
|
||||
|
||||
const { doSubmit: deactivateRepo, isLoading: isDeactivatingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await apiClient.deleteRepo(repo.value.owner, repo.value.name, false);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.disable.success'), type: 'success' });
|
||||
await router.replace({ name: 'repos' });
|
||||
});
|
||||
|
||||
return {
|
||||
isActive: repo?.value.active,
|
||||
isRepairingRepo,
|
||||
isDeletingRepo,
|
||||
isDeactivatingRepo,
|
||||
isActivatingRepo,
|
||||
deleteRepo,
|
||||
repairRepo,
|
||||
deactivateRepo,
|
||||
activateRepo,
|
||||
};
|
||||
},
|
||||
await apiClient.repairRepo(repo.value.id);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.repair.success'), type: 'success' });
|
||||
});
|
||||
|
||||
const { doSubmit: deleteRepo, isLoading: isDeletingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
// TODO use proper dialog
|
||||
// eslint-disable-next-line no-alert, no-restricted-globals
|
||||
if (!confirm(i18n.t('repo.settings.actions.delete.confirm'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
await apiClient.deleteRepo(repo.value.id);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.delete.success'), type: 'success' });
|
||||
await router.replace({ name: 'repos' });
|
||||
});
|
||||
|
||||
const { doSubmit: activateRepo, isLoading: isActivatingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await apiClient.activateRepo(repo.value.forge_remote_id);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.enable.success'), type: 'success' });
|
||||
});
|
||||
|
||||
const { doSubmit: deactivateRepo, isLoading: isDeactivatingRepo } = useAsyncAction(async () => {
|
||||
if (!repo) {
|
||||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await apiClient.deleteRepo(repo.value.id, false);
|
||||
notifications.notify({ title: i18n.t('repo.settings.actions.disable.success'), type: 'success' });
|
||||
await router.replace({ name: 'repos' });
|
||||
});
|
||||
|
||||
const isActive = computed(() => repo?.value.active);
|
||||
</script>
|
||||
|
|
|
@ -75,7 +75,7 @@ export default defineComponent({
|
|||
throw new Error('Unexpected: "repo" should be provided at this place');
|
||||
}
|
||||
|
||||
branches.value = (await usePaginate((page) => apiClient.getRepoBranches(repo.value.owner, repo.value.name, page)))
|
||||
branches.value = (await usePaginate((page) => apiClient.getRepoBranches(repo.value.id, page)))
|
||||
.map((b) => ({
|
||||
value: b,
|
||||
text: b,
|
||||
|
@ -91,14 +91,9 @@ export default defineComponent({
|
|||
window.location.port ? `:${window.location.port}` : ''
|
||||
}`;
|
||||
const badgeUrl = computed(
|
||||
() =>
|
||||
`/api/badges/${repo.value.owner}/${repo.value.name}/status.svg${
|
||||
branch.value !== '' ? `?branch=${branch.value}` : ''
|
||||
}`,
|
||||
);
|
||||
const repoUrl = computed(
|
||||
() => `/${repo.value.owner}/${repo.value.name}${branch.value !== '' ? `/branches/${branch.value}` : ''}`,
|
||||
() => `/api/badges/${repo.value.id}/status.svg${branch.value !== '' ? `?branch=${branch.value}` : ''}`,
|
||||
);
|
||||
const repoUrl = computed(() => `/${repo.value.id}${branch.value !== '' ? `/branches/${branch.value}` : ''}`);
|
||||
|
||||
const badgeContent = computed(() => {
|
||||
if (!repo) {
|
||||
|
|
|
@ -121,7 +121,7 @@ async function loadCrons(page: number): Promise<Cron[] | null> {
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
return apiClient.getCronList(repo.value.owner, repo.value.name, page);
|
||||
return apiClient.getCronList(repo.value.id, page);
|
||||
}
|
||||
|
||||
const { resetPage, data: crons } = usePagination(loadCrons, () => !selectedCron.value);
|
||||
|
@ -136,9 +136,9 @@ const { doSubmit: createCron, isLoading: isSaving } = useAsyncAction(async () =>
|
|||
}
|
||||
|
||||
if (isEditingCron.value) {
|
||||
await apiClient.updateCron(repo.value.owner, repo.value.name, selectedCron.value);
|
||||
await apiClient.updateCron(repo.value.id, selectedCron.value);
|
||||
} else {
|
||||
await apiClient.createCron(repo.value.owner, repo.value.name, selectedCron.value);
|
||||
await apiClient.createCron(repo.value.id, selectedCron.value);
|
||||
}
|
||||
notifications.notify({
|
||||
title: i18n.t(isEditingCron.value ? 'repo.settings.crons.saved' : i18n.t('repo.settings.crons.created')),
|
||||
|
@ -153,7 +153,7 @@ const { doSubmit: deleteCron, isLoading: isDeleting } = useAsyncAction(async (_c
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
await apiClient.deleteCron(repo.value.owner, repo.value.name, _cron.id);
|
||||
await apiClient.deleteCron(repo.value.id, _cron.id);
|
||||
notifications.notify({ title: i18n.t('repo.settings.crons.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
});
|
||||
|
@ -163,12 +163,10 @@ const { doSubmit: runCron } = useAsyncAction(async (_cron: Cron) => {
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
const pipeline = await apiClient.runCron(repo.value.owner, repo.value.name, _cron.id);
|
||||
const pipeline = await apiClient.runCron(repo.value.id, _cron.id);
|
||||
await router.push({
|
||||
name: 'repo-pipeline',
|
||||
params: {
|
||||
repoOwner: repo.value.owner,
|
||||
repoName: repo.value.name,
|
||||
pipelineId: pipeline.number,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -148,7 +148,7 @@ export default defineComponent({
|
|||
throw new Error('Unexpected: Repo should be set');
|
||||
}
|
||||
|
||||
await repoStore.loadRepo(repo.value.owner, repo.value.name);
|
||||
await repoStore.loadRepo(repo.value.id);
|
||||
loadRepoSettings();
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ export default defineComponent({
|
|||
throw new Error('Unexpected: Repo-Settings should be set');
|
||||
}
|
||||
|
||||
await apiClient.updateRepo(repo.value.owner, repo.value.name, repoSettings.value);
|
||||
await apiClient.updateRepo(repo.value.id, repoSettings.value);
|
||||
await loadRepo();
|
||||
notifications.notify({ title: i18n.t('repo.settings.general.success'), type: 'success' });
|
||||
});
|
||||
|
|
|
@ -124,7 +124,7 @@ export default defineComponent({
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
return apiClient.getRegistryList(repo.value.owner, repo.value.name, page);
|
||||
return apiClient.getRegistryList(repo.value.id, page);
|
||||
}
|
||||
|
||||
const { resetPage, data: registries } = usePagination(loadRegistries, () => !selectedRegistry.value);
|
||||
|
@ -139,9 +139,9 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
if (isEditingRegistry.value) {
|
||||
await apiClient.updateRegistry(repo.value.owner, repo.value.name, selectedRegistry.value);
|
||||
await apiClient.updateRegistry(repo.value.id, selectedRegistry.value);
|
||||
} else {
|
||||
await apiClient.createRegistry(repo.value.owner, repo.value.name, selectedRegistry.value);
|
||||
await apiClient.createRegistry(repo.value.id, selectedRegistry.value);
|
||||
}
|
||||
notifications.notify({
|
||||
title: i18n.t(
|
||||
|
@ -159,7 +159,7 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
const registryAddress = encodeURIComponent(_registry.address);
|
||||
await apiClient.deleteRegistry(repo.value.owner, repo.value.name, registryAddress);
|
||||
await apiClient.deleteRegistry(repo.value.id, registryAddress);
|
||||
notifications.notify({ title: i18n.t('repo.settings.registries.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
});
|
||||
|
|
|
@ -86,7 +86,7 @@ export default defineComponent({
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
return apiClient.getSecretList(repo.value.owner, repo.value.name, page);
|
||||
return apiClient.getSecretList(repo.value.id, page);
|
||||
}
|
||||
|
||||
const { resetPage, data: secrets } = usePagination(loadSecrets, () => !selectedSecret.value);
|
||||
|
@ -101,9 +101,9 @@ export default defineComponent({
|
|||
}
|
||||
|
||||
if (isEditingSecret.value) {
|
||||
await apiClient.updateSecret(repo.value.owner, repo.value.name, selectedSecret.value);
|
||||
await apiClient.updateSecret(repo.value.id, selectedSecret.value);
|
||||
} else {
|
||||
await apiClient.createSecret(repo.value.owner, repo.value.name, selectedSecret.value);
|
||||
await apiClient.createSecret(repo.value.id, selectedSecret.value);
|
||||
}
|
||||
notifications.notify({
|
||||
title: i18n.t(isEditingSecret.value ? 'repo.settings.secrets.saved' : 'repo.settings.secrets.created'),
|
||||
|
@ -118,7 +118,7 @@ export default defineComponent({
|
|||
throw new Error("Unexpected: Can't load repo");
|
||||
}
|
||||
|
||||
await apiClient.deleteSecret(repo.value.owner, repo.value.name, _secret.name);
|
||||
await apiClient.deleteSecret(repo.value.id, _secret.name);
|
||||
notifications.notify({ title: i18n.t('repo.settings.secrets.deleted'), type: 'success' });
|
||||
resetPage();
|
||||
});
|
||||
|
|
|
@ -28,13 +28,13 @@ export default () => {
|
|||
return;
|
||||
}
|
||||
const { pipeline } = data;
|
||||
pipelineStore.setPipeline(repo.owner, repo.name, pipeline);
|
||||
pipelineStore.setPipeline(repo.id, pipeline);
|
||||
|
||||
// contains step update
|
||||
if (!data.step) {
|
||||
return;
|
||||
}
|
||||
const { step } = data;
|
||||
pipelineStore.setStep(repo.owner, repo.name, pipeline.number, step);
|
||||
pipelineStore.setStep(repo.id, pipeline.number, step);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,12 +3,11 @@ import { RouteLocationRaw, useRouter } from 'vue-router';
|
|||
export function useRouteBackOrDefault(to: RouteLocationRaw) {
|
||||
const router = useRouter();
|
||||
|
||||
return () => {
|
||||
// TODO: use history navigation once we have found a solution for filtering external history entries
|
||||
// if (window.history.length > 2) {
|
||||
// router.back();
|
||||
// } else {
|
||||
router.replace(to);
|
||||
// }
|
||||
return async () => {
|
||||
if ((window.history.state as { back: string }).back === null) {
|
||||
await router.replace(to);
|
||||
return;
|
||||
}
|
||||
router.back();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,66 +40,70 @@ export default class WoodpeckerClient extends ApiClient {
|
|||
return this._get(`/api/user/repos?${query}`) as Promise<Repo[]>;
|
||||
}
|
||||
|
||||
getRepo(owner: string, repo: string): Promise<Repo> {
|
||||
return this._get(`/api/repos/${owner}/${repo}`) as Promise<Repo>;
|
||||
lookupRepo(owner: string, name: string): Promise<Repo | undefined> {
|
||||
return this._get(`/api/repos/lookup/${owner}/${name}`) as Promise<Repo | undefined>;
|
||||
}
|
||||
|
||||
getRepoPermissions(owner: string, repo: string): Promise<RepoPermissions> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/permissions`) as Promise<RepoPermissions>;
|
||||
getRepo(repoId: number): Promise<Repo> {
|
||||
return this._get(`/api/repos/${repoId}`) as Promise<Repo>;
|
||||
}
|
||||
|
||||
getRepoBranches(owner: string, repo: string, page: number): Promise<string[]> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/branches?page=${page}`) as Promise<string[]>;
|
||||
getRepoPermissions(repoId: number): Promise<RepoPermissions> {
|
||||
return this._get(`/api/repos/${repoId}/permissions`) as Promise<RepoPermissions>;
|
||||
}
|
||||
|
||||
getRepoPullRequests(owner: string, repo: string, page: number): Promise<PullRequest[]> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/pull_requests?page=${page}`) as Promise<PullRequest[]>;
|
||||
getRepoBranches(repoId: number, page: number): Promise<string[]> {
|
||||
return this._get(`/api/repos/${repoId}/branches?page=${page}`) as Promise<string[]>;
|
||||
}
|
||||
|
||||
activateRepo(owner: string, repo: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}`);
|
||||
getRepoPullRequests(repoId: number, page: number): Promise<PullRequest[]> {
|
||||
return this._get(`/api/repos/${repoId}/pull_requests?page=${page}`) as Promise<PullRequest[]>;
|
||||
}
|
||||
|
||||
updateRepo(owner: string, repo: string, repoSettings: RepoSettings): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${owner}/${repo}`, repoSettings);
|
||||
activateRepo(forgeRemoteId: string): Promise<Repo> {
|
||||
return this._post(`/api/repos?forge_remote_id=${forgeRemoteId}`) as Promise<Repo>;
|
||||
}
|
||||
|
||||
deleteRepo(owner: string, repo: string, remove = true): Promise<unknown> {
|
||||
updateRepo(repoId: number, repoSettings: RepoSettings): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${repoId}`, repoSettings);
|
||||
}
|
||||
|
||||
deleteRepo(repoId: number, remove = true): Promise<unknown> {
|
||||
const query = encodeQueryString({ remove });
|
||||
return this._delete(`/api/repos/${owner}/${repo}?${query}`);
|
||||
return this._delete(`/api/repos/${repoId}?${query}`);
|
||||
}
|
||||
|
||||
repairRepo(owner: string, repo: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/repair`);
|
||||
repairRepo(repoId: number): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/repair`);
|
||||
}
|
||||
|
||||
createPipeline(owner: string, repo: string, options: PipelineOptions): Promise<Pipeline> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines`, options) as Promise<Pipeline>;
|
||||
createPipeline(repoId: number, options: PipelineOptions): Promise<Pipeline> {
|
||||
return this._post(`/api/repos/${repoId}/pipelines`, options) as Promise<Pipeline>;
|
||||
}
|
||||
|
||||
// Deploy triggers a deployment for an existing pipeline using the
|
||||
// specified target environment.
|
||||
deployPipeline(owner: string, repo: string, pipelineNumber: string, options: DeploymentOptions): Promise<Pipeline> {
|
||||
deployPipeline(repoId: number, pipelineNumber: string, options: DeploymentOptions): Promise<Pipeline> {
|
||||
const vars = {
|
||||
...options.variables,
|
||||
event: 'deployment',
|
||||
deploy_to: options.environment,
|
||||
};
|
||||
const query = encodeQueryString(vars);
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}?${query}`) as Promise<Pipeline>;
|
||||
return this._post(`/api/repos/${repoId}/pipelines/${pipelineNumber}?${query}`) as Promise<Pipeline>;
|
||||
}
|
||||
|
||||
getPipelineList(owner: string, repo: string, opts?: Record<string, string | number | boolean>): Promise<Pipeline[]> {
|
||||
getPipelineList(repoId: number, opts?: Record<string, string | number | boolean>): Promise<Pipeline[]> {
|
||||
const query = encodeQueryString(opts);
|
||||
return this._get(`/api/repos/${owner}/${repo}/pipelines?${query}`) as Promise<Pipeline[]>;
|
||||
return this._get(`/api/repos/${repoId}/pipelines?${query}`) as Promise<Pipeline[]>;
|
||||
}
|
||||
|
||||
getPipeline(owner: string, repo: string, pipelineNumber: number | 'latest'): Promise<Pipeline> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}`) as Promise<Pipeline>;
|
||||
getPipeline(repoId: number, pipelineNumber: number | 'latest'): Promise<Pipeline> {
|
||||
return this._get(`/api/repos/${repoId}/pipelines/${pipelineNumber}`) as Promise<Pipeline>;
|
||||
}
|
||||
|
||||
getPipelineConfig(owner: string, repo: string, pipelineNumber: number): Promise<PipelineConfig[]> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}/config`) as Promise<PipelineConfig[]>;
|
||||
getPipelineConfig(repoId: number, pipelineNumber: number): Promise<PipelineConfig[]> {
|
||||
return this._get(`/api/repos/${repoId}/pipelines/${pipelineNumber}/config`) as Promise<PipelineConfig[]>;
|
||||
}
|
||||
|
||||
getPipelineFeed(opts?: Record<string, string | number | boolean>): Promise<PipelineFeed[]> {
|
||||
|
@ -107,82 +111,81 @@ export default class WoodpeckerClient extends ApiClient {
|
|||
return this._get(`/api/user/feed?${query}`) as Promise<PipelineFeed[]>;
|
||||
}
|
||||
|
||||
cancelPipeline(owner: string, repo: string, pipelineNumber: number): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}/cancel`);
|
||||
cancelPipeline(repoId: number, pipelineNumber: number): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/pipelines/${pipelineNumber}/cancel`);
|
||||
}
|
||||
|
||||
approvePipeline(owner: string, repo: string, pipelineNumber: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}/approve`);
|
||||
approvePipeline(repoId: number, pipelineNumber: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/pipelines/${pipelineNumber}/approve`);
|
||||
}
|
||||
|
||||
declinePipeline(owner: string, repo: string, pipelineNumber: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines/${pipelineNumber}/decline`);
|
||||
declinePipeline(repoId: number, pipelineNumber: string): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/pipelines/${pipelineNumber}/decline`);
|
||||
}
|
||||
|
||||
restartPipeline(
|
||||
owner: string,
|
||||
repo: string,
|
||||
repoId: number,
|
||||
pipeline: string,
|
||||
opts?: Record<string, string | number | boolean>,
|
||||
): Promise<Pipeline> {
|
||||
const query = encodeQueryString(opts);
|
||||
return this._post(`/api/repos/${owner}/${repo}/pipelines/${pipeline}?${query}`) as Promise<Pipeline>;
|
||||
return this._post(`/api/repos/${repoId}/pipelines/${pipeline}?${query}`) as Promise<Pipeline>;
|
||||
}
|
||||
|
||||
getLogs(owner: string, repo: string, pipeline: number, stepId: number): Promise<PipelineLog[]> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/logs/${pipeline}/${stepId}`) as Promise<PipelineLog[]>;
|
||||
getLogs(repoId: number, pipeline: number, step: number): Promise<PipelineLog[]> {
|
||||
return this._get(`/api/repos/${repoId}/logs/${pipeline}/${step}`) as Promise<PipelineLog[]>;
|
||||
}
|
||||
|
||||
getSecretList(owner: string, repo: string, page: number): Promise<Secret[] | null> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/secrets?page=${page}`) as Promise<Secret[] | null>;
|
||||
getSecretList(repoId: number, page: number): Promise<Secret[] | null> {
|
||||
return this._get(`/api/repos/${repoId}/secrets?page=${page}`) as Promise<Secret[] | null>;
|
||||
}
|
||||
|
||||
createSecret(owner: string, repo: string, secret: Partial<Secret>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/secrets`, secret);
|
||||
createSecret(repoId: number, secret: Partial<Secret>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/secrets`, secret);
|
||||
}
|
||||
|
||||
updateSecret(owner: string, repo: string, secret: Partial<Secret>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${owner}/${repo}/secrets/${secret.name}`, secret);
|
||||
updateSecret(repoId: number, secret: Partial<Secret>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${repoId}/secrets/${secret.name}`, secret);
|
||||
}
|
||||
|
||||
deleteSecret(owner: string, repo: string, secretName: string): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${owner}/${repo}/secrets/${secretName}`);
|
||||
deleteSecret(repoId: number, secretName: string): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${repoId}/secrets/${secretName}`);
|
||||
}
|
||||
|
||||
getRegistryList(owner: string, repo: string, page: number): Promise<Registry[] | null> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/registry?page=${page}`) as Promise<Registry[] | null>;
|
||||
getRegistryList(repoId: number, page: number): Promise<Registry[] | null> {
|
||||
return this._get(`/api/repos/${repoId}/registry?page=${page}`) as Promise<Registry[] | null>;
|
||||
}
|
||||
|
||||
createRegistry(owner: string, repo: string, registry: Partial<Registry>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/registry`, registry);
|
||||
createRegistry(repoId: number, registry: Partial<Registry>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/registry`, registry);
|
||||
}
|
||||
|
||||
updateRegistry(owner: string, repo: string, registry: Partial<Registry>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${owner}/${repo}/registry/${registry.address}`, registry);
|
||||
updateRegistry(repoId: number, registry: Partial<Registry>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${repoId}/registry/${registry.address}`, registry);
|
||||
}
|
||||
|
||||
deleteRegistry(owner: string, repo: string, registryAddress: string): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${owner}/${repo}/registry/${registryAddress}`);
|
||||
deleteRegistry(repoId: number, registryAddress: string): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${repoId}/registry/${registryAddress}`);
|
||||
}
|
||||
|
||||
getCronList(owner: string, repo: string, page: number): Promise<Cron[] | null> {
|
||||
return this._get(`/api/repos/${owner}/${repo}/cron?page=${page}`) as Promise<Cron[] | null>;
|
||||
getCronList(repoId: number, page: number): Promise<Cron[] | null> {
|
||||
return this._get(`/api/repos/${repoId}/cron?page=${page}`) as Promise<Cron[] | null>;
|
||||
}
|
||||
|
||||
createCron(owner: string, repo: string, cron: Partial<Cron>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/cron`, cron);
|
||||
createCron(repoId: number, cron: Partial<Cron>): Promise<unknown> {
|
||||
return this._post(`/api/repos/${repoId}/cron`, cron);
|
||||
}
|
||||
|
||||
updateCron(owner: string, repo: string, cron: Partial<Cron>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${owner}/${repo}/cron/${cron.id}`, cron);
|
||||
updateCron(repoId: number, cron: Partial<Cron>): Promise<unknown> {
|
||||
return this._patch(`/api/repos/${repoId}/cron/${cron.id}`, cron);
|
||||
}
|
||||
|
||||
deleteCron(owner: string, repo: string, cronId: number): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${owner}/${repo}/cron/${cronId}`);
|
||||
deleteCron(repoId: number, cronId: number): Promise<unknown> {
|
||||
return this._delete(`/api/repos/${repoId}/cron/${cronId}`);
|
||||
}
|
||||
|
||||
runCron(owner: string, repo: string, cronId: number): Promise<Pipeline> {
|
||||
return this._post(`/api/repos/${owner}/${repo}/cron/${cronId}`) as Promise<Pipeline>;
|
||||
runCron(repoId: number, cronId: number): Promise<Pipeline> {
|
||||
return this._post(`/api/repos/${repoId}/cron/${cronId}`) as Promise<Pipeline>;
|
||||
}
|
||||
|
||||
getOrgPermissions(owner: string): Promise<OrgPermissions> {
|
||||
|
@ -293,14 +296,13 @@ export default class WoodpeckerClient extends ApiClient {
|
|||
}
|
||||
|
||||
streamLogs(
|
||||
owner: string,
|
||||
repo: string,
|
||||
repoId: number,
|
||||
pipeline: number,
|
||||
step: number,
|
||||
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
||||
callback: (data: PipelineLog) => void,
|
||||
): EventSource {
|
||||
return this._subscribe(`/api/stream/logs/${owner}/${repo}/${pipeline}/${step}`, callback, {
|
||||
return this._subscribe(`/api/stream/logs/${repoId}/${pipeline}/${step}`, callback, {
|
||||
reconnect: true,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -127,7 +127,5 @@ export type PipelineLog = {
|
|||
};
|
||||
|
||||
export type PipelineFeed = Pipeline & {
|
||||
owner: string;
|
||||
name: string;
|
||||
full_name: string;
|
||||
repo_id: number;
|
||||
};
|
||||
|
|
|
@ -6,6 +6,9 @@ export type Repo = {
|
|||
// The unique identifier for the repository.
|
||||
id: number;
|
||||
|
||||
// The id of the repository on the source control management system.
|
||||
forge_remote_id: string;
|
||||
|
||||
// The source control management being used.
|
||||
// Currently this is either 'git' or 'hg' (Mercurial).
|
||||
scm: string;
|
||||
|
@ -57,6 +60,7 @@ export type Repo = {
|
|||
|
||||
// Events that will cancel running pipelines before starting a new one
|
||||
cancel_previous_pipeline_events: string[];
|
||||
|
||||
netrc_only_trusted: boolean;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,31 +12,108 @@ const routes: RouteRecordRaw[] = [
|
|||
},
|
||||
{
|
||||
path: '/repos',
|
||||
name: 'repos',
|
||||
component: (): Component => import('~/views/Repos.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
component: (): Component => import('~/views/RouterView.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'repos',
|
||||
component: (): Component => import('~/views/Repos.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
name: 'repo-add',
|
||||
component: (): Component => import('~/views/RepoAdd.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
},
|
||||
{
|
||||
path: ':repoId',
|
||||
name: 'repo-wrapper',
|
||||
component: (): Component => import('~/views/repo/RepoWrapper.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'repo',
|
||||
component: (): Component => import('~/views/repo/RepoPipelines.vue'),
|
||||
meta: { repoHeader: true },
|
||||
},
|
||||
{
|
||||
path: 'branches',
|
||||
name: 'repo-branches',
|
||||
component: (): Component => import('~/views/repo/RepoBranches.vue'),
|
||||
meta: { repoHeader: true },
|
||||
},
|
||||
{
|
||||
path: 'branches/:branch',
|
||||
name: 'repo-branch',
|
||||
component: (): Component => import('~/views/repo/RepoBranch.vue'),
|
||||
meta: { repoHeader: true },
|
||||
props: (route) => ({ branch: route.params.branch }),
|
||||
},
|
||||
{
|
||||
path: 'pull-requests',
|
||||
name: 'repo-pull-requests',
|
||||
component: (): Component => import('~/views/repo/RepoPullRequests.vue'),
|
||||
meta: { repoHeader: true },
|
||||
},
|
||||
{
|
||||
path: 'pull-requests/:pullRequest',
|
||||
name: 'repo-pull-request',
|
||||
component: (): Component => import('~/views/repo/RepoPullRequest.vue'),
|
||||
meta: { repoHeader: true },
|
||||
props: (route) => ({ pullRequest: route.params.pullRequest }),
|
||||
},
|
||||
{
|
||||
path: 'pipeline/:pipelineId',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineWrapper.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
path: ':stepId?',
|
||||
name: 'repo-pipeline',
|
||||
component: (): Component => import('~/views/repo/pipeline/Pipeline.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'changed-files',
|
||||
name: 'repo-pipeline-changed-files',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineChangedFiles.vue'),
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
name: 'repo-pipeline-config',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineConfig.vue'),
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
name: 'repo-settings',
|
||||
component: (): Component => import('~/views/repo/RepoSettings.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: ':repoOwner/:repoName/:pathMatch(.*)*',
|
||||
component: () => import('~/views/repo/RepoDeprecatedRedirect.vue'),
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/repo/add',
|
||||
name: 'repo-add',
|
||||
component: (): Component => import('~/views/RepoAdd.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
},
|
||||
{
|
||||
path: '/:repoOwner',
|
||||
name: 'repos-owner',
|
||||
component: (): Component => import('~/views/ReposOwner.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/org/:repoOwner',
|
||||
path: '/org/:orgName',
|
||||
component: (): Component => import('~/views/org/OrgWrapper.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'org',
|
||||
redirect: (route) => ({ name: 'repos-owner', params: route.params }),
|
||||
component: (): Component => import('~/views/org/OrgRepos.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
|
@ -48,114 +125,25 @@ const routes: RouteRecordRaw[] = [
|
|||
],
|
||||
},
|
||||
{
|
||||
path: '/:repoOwner/:repoName',
|
||||
name: 'repo-wrapper',
|
||||
component: (): Component => import('~/views/repo/RepoWrapper.vue'),
|
||||
props: true,
|
||||
path: '/admin',
|
||||
component: (): Component => import('~/views/RouterView.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'repo',
|
||||
component: (): Component => import('~/views/repo/RepoPipelines.vue'),
|
||||
meta: { repoHeader: true },
|
||||
},
|
||||
{
|
||||
path: 'branches',
|
||||
name: 'repo-branches',
|
||||
component: (): Component => import('~/views/repo/RepoBranches.vue'),
|
||||
meta: { repoHeader: true },
|
||||
props: (route) => ({ branch: route.params.branch }),
|
||||
},
|
||||
{
|
||||
path: 'branches/:branch',
|
||||
name: 'repo-branch',
|
||||
component: (): Component => import('~/views/repo/RepoBranch.vue'),
|
||||
meta: { repoHeader: true },
|
||||
props: (route) => ({ branch: route.params.branch }),
|
||||
},
|
||||
{
|
||||
path: 'pull-requests',
|
||||
name: 'repo-pull-requests',
|
||||
component: (): Component => import('~/views/repo/RepoPullRequests.vue'),
|
||||
meta: { repoHeader: true },
|
||||
},
|
||||
{
|
||||
path: 'pull-requests/:pullRequest',
|
||||
name: 'repo-pull-request',
|
||||
component: (): Component => import('~/views/repo/RepoPullRequest.vue'),
|
||||
meta: { repoHeader: true },
|
||||
props: (route) => ({ pullRequest: route.params.pullRequest }),
|
||||
},
|
||||
{
|
||||
path: 'pipeline/:pipelineId',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineWrapper.vue'),
|
||||
name: 'admin',
|
||||
component: (): Component => import('~/views/admin/Admin.vue'),
|
||||
props: true,
|
||||
children: [
|
||||
{
|
||||
path: ':stepId?',
|
||||
name: 'repo-pipeline',
|
||||
component: (): Component => import('~/views/repo/pipeline/Pipeline.vue'),
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: 'changed-files',
|
||||
name: 'repo-pipeline-changed-files',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineChangedFiles.vue'),
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
name: 'repo-pipeline-config',
|
||||
component: (): Component => import('~/views/repo/pipeline/PipelineConfig.vue'),
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'settings',
|
||||
name: 'repo-settings',
|
||||
component: (): Component => import('~/views/repo/RepoSettings.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
name: 'admin-settings',
|
||||
component: (): Component => import('~/views/admin/AdminSettings.vue'),
|
||||
props: true,
|
||||
},
|
||||
// TODO: redirect to support backwards compatibility => remove after some time
|
||||
{
|
||||
path: ':pipelineId',
|
||||
redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
},
|
||||
{
|
||||
path: 'build/:pipelineId',
|
||||
redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
children: [
|
||||
{
|
||||
path: ':procId?',
|
||||
redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
},
|
||||
{
|
||||
path: 'changed-files',
|
||||
redirect: (route) => ({ name: 'repo-pipeline-changed-files', params: route.params }),
|
||||
},
|
||||
{
|
||||
path: 'config',
|
||||
redirect: (route) => ({ name: 'repo-pipeline-config', params: route.params }),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/admin',
|
||||
name: 'admin',
|
||||
component: (): Component => import('~/views/admin/Admin.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/admin/settings',
|
||||
name: 'admin-settings',
|
||||
component: (): Component => import('~/views/admin/AdminSettings.vue'),
|
||||
meta: { authentication: 'required' },
|
||||
props: true,
|
||||
},
|
||||
|
||||
{
|
||||
path: '/user',
|
||||
name: 'user',
|
||||
|
@ -177,6 +165,19 @@ const routes: RouteRecordRaw[] = [
|
|||
meta: { blank: true },
|
||||
props: true,
|
||||
},
|
||||
|
||||
// TODO: deprecated routes => remove after some time
|
||||
{
|
||||
path: '/:ownerOrOrgId',
|
||||
redirect: (route) => ({ name: 'org', params: route.params }),
|
||||
},
|
||||
{
|
||||
path: '/:repoOwner/:repoName/:pathMatch(.*)*',
|
||||
component: () => import('~/views/repo/RepoDeprecatedRedirect.vue'),
|
||||
props: true,
|
||||
},
|
||||
|
||||
// not found handler
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'not-found',
|
||||
|
@ -198,7 +199,8 @@ router.beforeEach(async (to, _, next) => {
|
|||
}
|
||||
|
||||
const authentication = useAuthentication();
|
||||
if (to.meta.authentication === 'required' && !authentication.isAuthenticated) {
|
||||
const authenticationRequired = to.matched.some((record) => record.meta.authentication === 'required');
|
||||
if (authenticationRequired && !authentication.isAuthenticated) {
|
||||
next({ name: 'login', query: { url: to.fullPath } });
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -4,41 +4,36 @@ import { computed, reactive, Ref, ref } from 'vue';
|
|||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { Pipeline, PipelineFeed, PipelineStep } from '~/lib/api/types';
|
||||
import { useRepoStore } from '~/store/repos';
|
||||
import { comparePipelines, isPipelineActive, repoSlug } from '~/utils/helpers';
|
||||
import { comparePipelines, isPipelineActive } from '~/utils/helpers';
|
||||
|
||||
export const usePipelineStore = defineStore('pipelines', () => {
|
||||
const apiClient = useApiClient();
|
||||
const repoStore = useRepoStore();
|
||||
|
||||
const pipelines: Map<string, Map<number, Pipeline>> = reactive(new Map());
|
||||
const pipelines: Map<number, Map<number, Pipeline>> = reactive(new Map());
|
||||
|
||||
function setPipeline(owner: string, repo: string, pipeline: Pipeline) {
|
||||
const _repoSlug = repoSlug(owner, repo);
|
||||
const repoPipelines = pipelines.get(_repoSlug) || new Map();
|
||||
function setPipeline(repoId: number, pipeline: Pipeline) {
|
||||
const repoPipelines = pipelines.get(repoId) || new Map();
|
||||
repoPipelines.set(pipeline.number, {
|
||||
...(repoPipelines.get(pipeline.number) || {}),
|
||||
...pipeline,
|
||||
});
|
||||
pipelines.set(_repoSlug, repoPipelines);
|
||||
pipelines.set(repoId, repoPipelines);
|
||||
}
|
||||
|
||||
function getRepoPipelines(owner: Ref<string>, repo: Ref<string>) {
|
||||
return computed(() => {
|
||||
const slug = repoSlug(owner.value, repo.value);
|
||||
return Array.from(pipelines.get(slug)?.values() || []).sort(comparePipelines);
|
||||
});
|
||||
function getRepoPipelines(repoId: Ref<number>) {
|
||||
return computed(() => Array.from(pipelines.get(repoId.value)?.values() || []).sort(comparePipelines));
|
||||
}
|
||||
|
||||
function getPipeline(owner: Ref<string>, repo: Ref<string>, _pipelineNumber: Ref<string>) {
|
||||
function getPipeline(repoId: Ref<number>, _pipelineNumber: Ref<string>) {
|
||||
return computed(() => {
|
||||
const slug = repoSlug(owner.value, repo.value);
|
||||
const pipelineNumber = parseInt(_pipelineNumber.value, 10);
|
||||
return pipelines.get(slug)?.get(pipelineNumber);
|
||||
return pipelines.get(repoId.value)?.get(pipelineNumber);
|
||||
});
|
||||
}
|
||||
|
||||
function setStep(owner: string, repo: string, pipelineNumber: number, step: PipelineStep) {
|
||||
const pipeline = getPipeline(ref(owner), ref(repo), ref(pipelineNumber.toString())).value;
|
||||
function setStep(repoId: number, pipelineNumber: number, step: PipelineStep) {
|
||||
const pipeline = getPipeline(ref(repoId), ref(pipelineNumber.toString())).value;
|
||||
if (!pipeline) {
|
||||
throw new Error("Can't find pipeline");
|
||||
}
|
||||
|
@ -48,38 +43,36 @@ export const usePipelineStore = defineStore('pipelines', () => {
|
|||
}
|
||||
|
||||
pipeline.steps = [...pipeline.steps.filter((p) => p.pid !== step.pid), step];
|
||||
setPipeline(owner, repo, pipeline);
|
||||
setPipeline(repoId, pipeline);
|
||||
}
|
||||
|
||||
async function loadRepoPipelines(owner: string, repo: string) {
|
||||
const _pipelines = await apiClient.getPipelineList(owner, repo);
|
||||
async function loadRepoPipelines(repoId: number) {
|
||||
const _pipelines = await apiClient.getPipelineList(repoId);
|
||||
_pipelines.forEach((pipeline) => {
|
||||
setPipeline(owner, repo, pipeline);
|
||||
setPipeline(repoId, pipeline);
|
||||
});
|
||||
}
|
||||
|
||||
async function loadPipeline(owner: string, repo: string, pipelinesNumber: number) {
|
||||
const pipeline = await apiClient.getPipeline(owner, repo, pipelinesNumber);
|
||||
setPipeline(owner, repo, pipeline);
|
||||
async function loadPipeline(repoId: number, pipelinesNumber: number) {
|
||||
const pipeline = await apiClient.getPipeline(repoId, pipelinesNumber);
|
||||
setPipeline(repoId, pipeline);
|
||||
}
|
||||
|
||||
const pipelineFeed = computed(() =>
|
||||
Array.from(pipelines.entries())
|
||||
.reduce<PipelineFeed[]>((acc, [_repoSlug, repoPipelines]) => {
|
||||
.reduce<PipelineFeed[]>((acc, [_repoId, repoPipelines]) => {
|
||||
const repoPipelinesArray = Array.from(repoPipelines.entries()).map(
|
||||
([_pipelineNumber, pipeline]) =>
|
||||
<PipelineFeed>{
|
||||
...pipeline,
|
||||
full_name: _repoSlug,
|
||||
owner: _repoSlug.split('/')[0],
|
||||
name: _repoSlug.split('/')[1],
|
||||
repo_id: _repoId,
|
||||
number: _pipelineNumber,
|
||||
},
|
||||
);
|
||||
return [...acc, ...repoPipelinesArray];
|
||||
}, [])
|
||||
.sort(comparePipelines)
|
||||
.filter((pipeline) => repoStore.ownedRepoSlugs.includes(pipeline.full_name)),
|
||||
.filter((pipeline) => repoStore.ownedRepoIds.includes(pipeline.repo_id)),
|
||||
);
|
||||
|
||||
const activePipelines = computed(() => pipelineFeed.value.filter(isPipelineActive));
|
||||
|
@ -89,7 +82,7 @@ export const usePipelineStore = defineStore('pipelines', () => {
|
|||
|
||||
const _pipelines = await apiClient.getPipelineFeed();
|
||||
_pipelines.forEach((pipeline) => {
|
||||
setPipeline(pipeline.owner, pipeline.name, pipeline);
|
||||
setPipeline(pipeline.repo_id, pipeline);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,49 +3,45 @@ import { computed, reactive, Ref, ref } from 'vue';
|
|||
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { Repo } from '~/lib/api/types';
|
||||
import { repoSlug } from '~/utils/helpers';
|
||||
|
||||
export const useRepoStore = defineStore('repos', () => {
|
||||
const apiClient = useApiClient();
|
||||
|
||||
const repos: Map<string, Repo> = reactive(new Map());
|
||||
const ownedRepoSlugs = ref<string[]>([]);
|
||||
const repos: Map<number, Repo> = reactive(new Map());
|
||||
const ownedRepoIds = ref<number[]>([]);
|
||||
|
||||
const ownedRepos = computed(() =>
|
||||
Array.from(repos.entries())
|
||||
.filter(([slug]) => ownedRepoSlugs.value.includes(slug))
|
||||
.filter(([repoId]) => ownedRepoIds.value.includes(repoId))
|
||||
.map(([, repo]) => repo),
|
||||
);
|
||||
|
||||
function getRepo(owner: Ref<string>, name: Ref<string>) {
|
||||
return computed(() => {
|
||||
const slug = repoSlug(owner.value, name.value);
|
||||
return repos.get(slug);
|
||||
});
|
||||
function getRepo(repoId: Ref<number>) {
|
||||
return computed(() => repos.get(repoId.value));
|
||||
}
|
||||
|
||||
function setRepo(repo: Repo) {
|
||||
repos.set(repoSlug(repo), repo);
|
||||
repos.set(repo.id, repo);
|
||||
}
|
||||
|
||||
async function loadRepo(owner: string, name: string) {
|
||||
const repo = await apiClient.getRepo(owner, name);
|
||||
repos.set(repoSlug(repo), repo);
|
||||
async function loadRepo(repoId: number) {
|
||||
const repo = await apiClient.getRepo(repoId);
|
||||
repos.set(repo.id, repo);
|
||||
return repo;
|
||||
}
|
||||
|
||||
async function loadRepos() {
|
||||
const _ownedRepos = await apiClient.getRepoList();
|
||||
_ownedRepos.forEach((repo) => {
|
||||
repos.set(repoSlug(repo), repo);
|
||||
repos.set(repo.id, repo);
|
||||
});
|
||||
ownedRepoSlugs.value = _ownedRepos.map((repo) => repoSlug(repo));
|
||||
ownedRepoIds.value = _ownedRepos.map((repo) => repo.id);
|
||||
}
|
||||
|
||||
return {
|
||||
repos,
|
||||
ownedRepos,
|
||||
ownedRepoSlugs,
|
||||
ownedRepoIds,
|
||||
getRepo,
|
||||
setRepo,
|
||||
loadRepo,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
v-for="repo in searchedRepos"
|
||||
:key="repo.id"
|
||||
class="items-center"
|
||||
:to="repo.active ? { name: 'repo', params: { repoOwner: repo.owner, repoName: repo.name } } : undefined"
|
||||
:to="repo.active ? { name: 'repo', params: { repoId: repo.id } } : undefined"
|
||||
>
|
||||
<span class="text-color">{{ repo.full_name }}</span>
|
||||
<span v-if="repo.active" class="ml-auto text-color-alt">{{ $t('repo.enable.enabled') }}</span>
|
||||
|
@ -25,8 +25,8 @@
|
|||
</Scaffold>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
@ -40,48 +40,27 @@ import { useRepoSearch } from '~/compositions/useRepoSearch';
|
|||
import { useRouteBackOrDefault } from '~/compositions/useRouteBackOrDefault';
|
||||
import { Repo } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RepoAdd',
|
||||
const router = useRouter();
|
||||
const apiClient = useApiClient();
|
||||
const notifications = useNotifications();
|
||||
const repos = ref<Repo[]>();
|
||||
const repoToActivate = ref<Repo>();
|
||||
const search = ref('');
|
||||
const i18n = useI18n();
|
||||
|
||||
components: {
|
||||
Button,
|
||||
ListItem,
|
||||
Scaffold,
|
||||
},
|
||||
const { searchedRepos } = useRepoSearch(repos, search);
|
||||
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const apiClient = useApiClient();
|
||||
const notifications = useNotifications();
|
||||
const repos = ref<Repo[]>();
|
||||
const repoToActivate = ref<Repo>();
|
||||
const search = ref('');
|
||||
const i18n = useI18n();
|
||||
|
||||
const { searchedRepos } = useRepoSearch(repos, search);
|
||||
|
||||
onMounted(async () => {
|
||||
repos.value = await apiClient.getRepoList({ all: true });
|
||||
});
|
||||
|
||||
const { doSubmit: activateRepo, isLoading: isActivatingRepo } = useAsyncAction(async (repo: Repo) => {
|
||||
repoToActivate.value = repo;
|
||||
await apiClient.activateRepo(repo.owner, repo.name);
|
||||
notifications.notify({ title: i18n.t('repo.enable.success'), type: 'success' });
|
||||
repoToActivate.value = undefined;
|
||||
await router.push({ name: 'repo', params: { repoName: repo.name, repoOwner: repo.owner } });
|
||||
});
|
||||
|
||||
const goBack = useRouteBackOrDefault({ name: 'repos' });
|
||||
|
||||
return {
|
||||
isActivatingRepo,
|
||||
repoToActivate,
|
||||
goBack,
|
||||
activateRepo,
|
||||
searchedRepos,
|
||||
search,
|
||||
};
|
||||
},
|
||||
onMounted(async () => {
|
||||
repos.value = await apiClient.getRepoList({ all: true });
|
||||
});
|
||||
|
||||
const { doSubmit: activateRepo, isLoading: isActivatingRepo } = useAsyncAction(async (repo: Repo) => {
|
||||
repoToActivate.value = repo;
|
||||
const _repo = await apiClient.activateRepo(repo.forge_remote_id);
|
||||
notifications.notify({ title: i18n.t('repo.enable.success'), type: 'success' });
|
||||
repoToActivate.value = undefined;
|
||||
await router.push({ name: 'repo', params: { repoId: _repo.id } });
|
||||
});
|
||||
|
||||
const goBack = useRouteBackOrDefault({ name: 'repos' });
|
||||
</script>
|
||||
|
|
|
@ -9,11 +9,7 @@
|
|||
</template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<ListItem
|
||||
v-for="repo in searchedRepos"
|
||||
:key="repo.id"
|
||||
:to="{ name: 'repo', params: { repoName: repo.name, repoOwner: repo.owner } }"
|
||||
>
|
||||
<ListItem v-for="repo in searchedRepos" :key="repo.id" :to="{ name: 'repo', params: { repoId: repo.id } }">
|
||||
<span class="text-color">{{ `${repo.owner} / ${repo.name}` }}</span>
|
||||
</ListItem>
|
||||
</div>
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
<template>
|
||||
<Scaffold v-model:search="search">
|
||||
<template #title>
|
||||
{{ repoOwner }}
|
||||
</template>
|
||||
|
||||
<template #titleActions>
|
||||
<IconButton
|
||||
v-if="orgPermissions.admin"
|
||||
icon="settings"
|
||||
:to="{ name: 'org-settings' }"
|
||||
:title="$t('org.settings.settings')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<ListItem
|
||||
v-for="repo in searchedRepos"
|
||||
:key="repo.id"
|
||||
:to="{ name: 'repo', params: { repoName: repo.name, repoOwner: repo.owner } }"
|
||||
>
|
||||
<span class="text-color">{{ `${repo.name}` }}</span>
|
||||
</ListItem>
|
||||
</div>
|
||||
<div v-if="(searchedRepos || []).length <= 0" class="text-center">
|
||||
<span class="text-color m-auto">{{ $t('repo.user_none') }}</span>
|
||||
</div>
|
||||
</Scaffold>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onMounted, ref } from 'vue';
|
||||
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import Scaffold from '~/components/layout/scaffold/Scaffold.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { useRepoSearch } from '~/compositions/useRepoSearch';
|
||||
import { OrgPermissions } from '~/lib/api/types';
|
||||
import { useRepoStore } from '~/store/repos';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ReposOwner',
|
||||
|
||||
components: {
|
||||
ListItem,
|
||||
IconButton,
|
||||
Scaffold,
|
||||
},
|
||||
|
||||
props: {
|
||||
repoOwner: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const apiClient = useApiClient();
|
||||
const repoStore = useRepoStore();
|
||||
// TODO: filter server side
|
||||
const repos = computed(() => Array.from(repoStore.repos.values()).filter((repo) => repo.owner === props.repoOwner));
|
||||
const search = ref('');
|
||||
const orgPermissions = ref<OrgPermissions>({ member: false, admin: false });
|
||||
|
||||
const { searchedRepos } = useRepoSearch(repos, search);
|
||||
|
||||
onMounted(async () => {
|
||||
await repoStore.loadRepos();
|
||||
orgPermissions.value = await apiClient.getOrgPermissions(props.repoOwner);
|
||||
});
|
||||
|
||||
return { searchedRepos, search, orgPermissions };
|
||||
},
|
||||
});
|
||||
</script>
|
3
web/src/views/RouterView.vue
Normal file
3
web/src/views/RouterView.vue
Normal file
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<router-view />
|
||||
</template>
|
57
web/src/views/org/OrgRepos.vue
Normal file
57
web/src/views/org/OrgRepos.vue
Normal file
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<Scaffold v-model:search="search">
|
||||
<template #title>
|
||||
{{ orgName }}
|
||||
</template>
|
||||
|
||||
<template #titleActions>
|
||||
<IconButton
|
||||
v-if="orgPermissions.admin"
|
||||
icon="settings"
|
||||
:to="{ name: 'org-settings' }"
|
||||
:title="$t('org.settings.settings')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div class="space-y-4">
|
||||
<ListItem v-for="repo in searchedRepos" :key="repo.id" :to="{ name: 'repo', params: { repoId: repo.id } }">
|
||||
<span class="text-color">{{ `${repo.owner} / ${repo.name}` }}</span>
|
||||
</ListItem>
|
||||
</div>
|
||||
<div v-if="(searchedRepos || []).length <= 0" class="text-center">
|
||||
<span class="text-color m-auto">{{ $t('repo.user_none') }}</span>
|
||||
</div>
|
||||
</Scaffold>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref, toRef } from 'vue';
|
||||
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import ListItem from '~/components/atomic/ListItem.vue';
|
||||
import Scaffold from '~/components/layout/scaffold/Scaffold.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { useRepoSearch } from '~/compositions/useRepoSearch';
|
||||
import { OrgPermissions } from '~/lib/api/types';
|
||||
import { useRepoStore } from '~/store/repos';
|
||||
|
||||
const props = defineProps<{
|
||||
orgName: string;
|
||||
}>();
|
||||
|
||||
const apiClient = useApiClient();
|
||||
const repoStore = useRepoStore();
|
||||
|
||||
// TODO: filter server side
|
||||
const orgName = toRef(props, 'orgName');
|
||||
const repos = computed(() => Array.from(repoStore.repos.values()).filter((repo) => repo.owner === orgName.value));
|
||||
const search = ref('');
|
||||
const orgPermissions = ref<OrgPermissions>({ member: false, admin: false });
|
||||
|
||||
const { searchedRepos } = useRepoSearch(repos, search);
|
||||
|
||||
onMounted(async () => {
|
||||
await repoStore.loadRepos();
|
||||
orgPermissions.value = await apiClient.getOrgPermissions(orgName.value);
|
||||
});
|
||||
</script>
|
|
@ -2,7 +2,7 @@
|
|||
<Scaffold enable-tabs :go-back="goBack">
|
||||
<template #title>
|
||||
<span>
|
||||
<router-link :to="{ name: 'repos-owner', params: { repoOwner: org.name } }" class="hover:underline">
|
||||
<router-link :to="{ name: 'org', params: { orgName: org.name } }" class="hover:underline">
|
||||
{{ org.name }}
|
||||
</router-link>
|
||||
/
|
||||
|
@ -16,8 +16,8 @@
|
|||
</Scaffold>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject, onMounted, Ref } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { inject, onMounted, Ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
|
@ -27,40 +27,26 @@ import useNotifications from '~/compositions/useNotifications';
|
|||
import { useRouteBackOrDefault } from '~/compositions/useRouteBackOrDefault';
|
||||
import { Org, OrgPermissions } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrgSettings',
|
||||
const notifications = useNotifications();
|
||||
const router = useRouter();
|
||||
const i18n = useI18n();
|
||||
|
||||
components: {
|
||||
Tab,
|
||||
OrgSecretsTab,
|
||||
},
|
||||
const orgPermissions = inject<Ref<OrgPermissions>>('org-permissions');
|
||||
if (!orgPermissions) {
|
||||
throw new Error('Unexpected: "orgPermissions" should be provided at this place');
|
||||
}
|
||||
|
||||
setup() {
|
||||
const notifications = useNotifications();
|
||||
const router = useRouter();
|
||||
const i18n = useI18n();
|
||||
const org = inject<Ref<Org>>('org');
|
||||
if (!org) {
|
||||
throw new Error('Unexpected: "org" should be provided at this place');
|
||||
}
|
||||
|
||||
const orgPermissions = inject<Ref<OrgPermissions>>('org-permissions');
|
||||
if (!orgPermissions) {
|
||||
throw new Error('Unexpected: "orgPermissions" should be provided at this place');
|
||||
}
|
||||
|
||||
const org = inject<Ref<Org>>('org');
|
||||
if (!org) {
|
||||
throw new Error('Unexpected: "org" should be provided at this place');
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (!orgPermissions.value.admin) {
|
||||
notifications.notify({ type: 'error', title: i18n.t('org.settings.not_allowed') });
|
||||
await router.replace({ name: 'home' });
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
org,
|
||||
goBack: useRouteBackOrDefault({ name: 'repos-owner' }),
|
||||
};
|
||||
},
|
||||
onMounted(async () => {
|
||||
if (!orgPermissions.value.admin) {
|
||||
notifications.notify({ type: 'error', title: i18n.t('org.settings.not_allowed') });
|
||||
await router.replace({ name: 'home' });
|
||||
}
|
||||
});
|
||||
|
||||
const goBack = useRouteBackOrDefault({ name: 'repos-owner' });
|
||||
</script>
|
||||
|
|
|
@ -18,48 +18,35 @@
|
|||
<router-view v-else-if="org && orgPermissions" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onMounted, provide, ref, toRef, watch } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, provide, ref, toRef, watch } from 'vue';
|
||||
|
||||
import IconButton from '~/components/atomic/IconButton.vue';
|
||||
import Scaffold from '~/components/layout/scaffold/Scaffold.vue';
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
import { Org, OrgPermissions } from '~/lib/api/types';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'OrgWrapper',
|
||||
const props = defineProps<{
|
||||
orgName: string;
|
||||
}>();
|
||||
|
||||
components: { IconButton, Scaffold },
|
||||
const orgName = toRef(props, 'orgName');
|
||||
const apiClient = useApiClient();
|
||||
|
||||
props: {
|
||||
repoOwner: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
const org = computed<Org>(() => ({ name: orgName.value }));
|
||||
const orgPermissions = ref<OrgPermissions>();
|
||||
provide('org', org);
|
||||
provide('org-permissions', orgPermissions);
|
||||
|
||||
setup(props) {
|
||||
const repoOwner = toRef(props, 'repoOwner');
|
||||
const apiClient = useApiClient();
|
||||
const org = computed<Org>(() => ({ name: repoOwner.value }));
|
||||
async function load() {
|
||||
orgPermissions.value = await apiClient.getOrgPermissions(orgName.value);
|
||||
}
|
||||
|
||||
const orgPermissions = ref<OrgPermissions>();
|
||||
provide('org', org);
|
||||
provide('org-permissions', orgPermissions);
|
||||
onMounted(() => {
|
||||
load();
|
||||
});
|
||||
|
||||
async function load() {
|
||||
orgPermissions.value = await apiClient.getOrgPermissions(repoOwner.value);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
load();
|
||||
});
|
||||
|
||||
watch([repoOwner], () => {
|
||||
load();
|
||||
});
|
||||
|
||||
return { org, orgPermissions };
|
||||
},
|
||||
watch([orgName], () => {
|
||||
load();
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -31,7 +31,7 @@ async function loadBranches(page: number): Promise<string[]> {
|
|||
throw new Error('Unexpected: "repo" should be provided at this place');
|
||||
}
|
||||
|
||||
return apiClient.getRepoBranches(repo.value.owner, repo.value.name, page);
|
||||
return apiClient.getRepoBranches(repo.value.id, page);
|
||||
}
|
||||
|
||||
const { resetPage, data: branches } = usePagination(loadBranches);
|
||||
|
|
54
web/src/views/repo/RepoDeprecatedRedirect.vue
Normal file
54
web/src/views/repo/RepoDeprecatedRedirect.vue
Normal file
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import useApiClient from '~/compositions/useApiClient';
|
||||
|
||||
const apiClient = useApiClient();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps<{
|
||||
repoOwner: string;
|
||||
repoName: string;
|
||||
}>();
|
||||
|
||||
onMounted(async () => {
|
||||
const repo = await apiClient.lookupRepo(props.repoOwner, props.repoName);
|
||||
|
||||
// {
|
||||
// path: ':pipelineId',
|
||||
// redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
// },
|
||||
// {
|
||||
// path: 'build/:pipelineId',
|
||||
// redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
// children: [
|
||||
// {
|
||||
// path: ':procId?',
|
||||
// redirect: (route) => ({ name: 'repo-pipeline', params: route.params }),
|
||||
// },
|
||||
// {
|
||||
// path: 'changed-files',
|
||||
// redirect: (route) => ({ name: 'repo-pipeline-changed-files', params: route.params }),
|
||||
// },
|
||||
// {
|
||||
// path: 'config',
|
||||
// redirect: (route) => ({ name: 'repo-pipeline-config', params: route.params }),
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
|
||||
// TODO: support pipeline and build routes
|
||||
|
||||
const path = route.path
|
||||
.replace(`/repos/${props.repoOwner}/${props.repoName}`, `/repos/${repo?.id}`)
|
||||
.replace(`/${props.repoOwner}/${props.repoName}`, `/repos/${repo?.id}`);
|
||||
|
||||
await router.replace({ path });
|
||||
});
|
||||
</script>
|
|
@ -35,7 +35,7 @@ async function loadPullRequests(page: number): Promise<PullRequest[]> {
|
|||
throw new Error('Unexpected: "repo" should be provided at this place');
|
||||
}
|
||||
|
||||
return apiClient.getRepoPullRequests(repo.value.owner, repo.value.name, page);
|
||||
return apiClient.getRepoPullRequests(repo.value.id, page);
|
||||
}
|
||||
|
||||
const { resetPage, data: pullRequests } = usePagination(loadPullRequests);
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
<Scaffold enable-tabs :go-back="goBack">
|
||||
<template #title>
|
||||
<span>
|
||||
<router-link :to="{ name: 'repos-owner', params: { repoOwner: repo.owner } }" class="hover:underline">
|
||||
<router-link :to="{ name: 'org', params: { orgName: repo.owner } }" class="hover:underline">
|
||||
{{ repo.owner }}
|
||||
</router-link>
|
||||
/
|
||||
<router-link
|
||||
:to="{ name: 'repo', params: { repoOwner: repo.owner, repoName: repo.name } }"
|
||||
class="hover:underline"
|
||||
>
|
||||
<router-link :to="{ name: 'repo' }" class="hover:underline">
|
||||
{{ repo.name }}
|
||||
</router-link>
|
||||
/
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
>
|
||||
<template #title>
|
||||
<span class="flex">
|
||||
<router-link :to="{ name: 'repos-owner', params: { repoOwner } }" class="hover:underline">{{
|
||||
repoOwner
|
||||
<router-link :to="{ name: 'org', params: { orgName: repo?.owner } }" class="hover:underline">{{
|
||||
repo.owner
|
||||
}}</router-link>
|
||||
{{ ` / ${repo.name}` }}
|
||||
</span>
|
||||
|
@ -72,20 +72,12 @@ import { RepoPermissions } from '~/lib/api/types';
|
|||
import { usePipelineStore } from '~/store/pipelines';
|
||||
import { useRepoStore } from '~/store/repos';
|
||||
|
||||
const props = defineProps({
|
||||
repoOwner: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
const props = defineProps<{
|
||||
repoId: string;
|
||||
}>();
|
||||
|
||||
repoName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const repoOwner = toRef(props, 'repoOwner');
|
||||
const repoName = toRef(props, 'repoName');
|
||||
const _repoId = toRef(props, 'repoId');
|
||||
const repoId = computed(() => parseInt(_repoId.value, 10));
|
||||
const repoStore = useRepoStore();
|
||||
const pipelineStore = usePipelineStore();
|
||||
const apiClient = useApiClient();
|
||||
|
@ -97,9 +89,9 @@ const i18n = useI18n();
|
|||
const config = useConfig();
|
||||
|
||||
const { forge } = useConfig();
|
||||
const repo = repoStore.getRepo(repoOwner, repoName);
|
||||
const repo = repoStore.getRepo(repoId);
|
||||
const repoPermissions = ref<RepoPermissions>();
|
||||
const pipelines = pipelineStore.getRepoPipelines(repoOwner, repoName);
|
||||
const pipelines = pipelineStore.getRepoPipelines(repoId);
|
||||
provide('repo', repo);
|
||||
provide('repo-permissions', repoPermissions);
|
||||
provide('pipelines', pipelines);
|
||||
|
@ -107,7 +99,7 @@ provide('pipelines', pipelines);
|
|||
const showManualPipelinePopup = ref(false);
|
||||
|
||||
async function loadRepo() {
|
||||
repoPermissions.value = await apiClient.getRepoPermissions(repoOwner.value, repoName.value);
|
||||
repoPermissions.value = await apiClient.getRepoPermissions(repoId.value);
|
||||
if (!repoPermissions.value.pull) {
|
||||
notifications.notify({ type: 'error', title: i18n.t('repo.not_allowed') });
|
||||
// no access and not authenticated, redirect to login
|
||||
|
@ -119,26 +111,19 @@ async function loadRepo() {
|
|||
return;
|
||||
}
|
||||
|
||||
const apiRepo = await repoStore.loadRepo(repoOwner.value, repoName.value);
|
||||
if (apiRepo.full_name !== `${repoOwner.value}/${repoName.value}`) {
|
||||
await router.replace({
|
||||
name: route.name ? route.name : 'repo',
|
||||
params: { repoOwner: apiRepo.owner, repoName: apiRepo.name },
|
||||
});
|
||||
return;
|
||||
}
|
||||
await pipelineStore.loadRepoPipelines(repoOwner.value, repoName.value);
|
||||
await repoStore.loadRepo(repoId.value);
|
||||
await pipelineStore.loadRepoPipelines(repoId.value);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadRepo();
|
||||
});
|
||||
|
||||
watch([repoOwner, repoName], () => {
|
||||
watch([repoId], () => {
|
||||
loadRepo();
|
||||
});
|
||||
|
||||
const badgeUrl = computed(() => repo.value && `/api/badges/${repo.value.owner}/${repo.value.name}/status.svg`);
|
||||
const badgeUrl = computed(() => repo.value && `/api/badges/${repo.value.id}/status.svg`);
|
||||
|
||||
const activeTab = computed({
|
||||
get() {
|
||||
|
|
|
@ -133,7 +133,7 @@ const { doSubmit: approvePipeline, isLoading: isApprovingPipeline } = useAsyncAc
|
|||
throw new Error('Unexpected: Repo is undefined');
|
||||
}
|
||||
|
||||
await apiClient.approvePipeline(repo.value.owner, repo.value.name, `${pipeline.value.number}`);
|
||||
await apiClient.approvePipeline(repo.value.id, `${pipeline.value.number}`);
|
||||
notifications.notify({ title: i18n.t('repo.pipeline.protected.approve_success'), type: 'success' });
|
||||
});
|
||||
|
||||
|
@ -142,7 +142,7 @@ const { doSubmit: declinePipeline, isLoading: isDecliningPipeline } = useAsyncAc
|
|||
throw new Error('Unexpected: Repo is undefined');
|
||||
}
|
||||
|
||||
await apiClient.declinePipeline(repo.value.owner, repo.value.name, `${pipeline.value.number}`);
|
||||
await apiClient.declinePipeline(repo.value.id, `${pipeline.value.number}`);
|
||||
notifications.notify({ title: i18n.t('repo.pipeline.protected.decline_success'), type: 'success' });
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -41,9 +41,7 @@ export default defineComponent({
|
|||
throw new Error('Unexpected: "repo" & "pipeline" should be provided at this place');
|
||||
}
|
||||
|
||||
pipelineConfigs.value = (
|
||||
await apiClient.getPipelineConfig(repo.value.owner, repo.value.name, pipeline.value.number)
|
||||
).map((i) => ({
|
||||
pipelineConfigs.value = (await apiClient.getPipelineConfig(repo.value.id, pipeline.value.number)).map((i) => ({
|
||||
...i,
|
||||
data: atob(i.data),
|
||||
}));
|
||||
|
|
|
@ -96,8 +96,7 @@ import { Repo, RepoPermissions } from '~/lib/api/types';
|
|||
import { usePipelineStore } from '~/store/pipelines';
|
||||
|
||||
const props = defineProps<{
|
||||
repoOwner: string;
|
||||
repoName: string;
|
||||
repoId: string;
|
||||
pipelineId: string;
|
||||
}>();
|
||||
|
||||
|
@ -110,15 +109,15 @@ const i18n = useI18n();
|
|||
|
||||
const pipelineStore = usePipelineStore();
|
||||
const pipelineId = toRef(props, 'pipelineId');
|
||||
const repoOwner = toRef(props, 'repoOwner');
|
||||
const repoName = toRef(props, 'repoName');
|
||||
const _repoId = toRef(props, 'repoId');
|
||||
const repoId = computed(() => parseInt(_repoId.value, 10));
|
||||
const repo = inject<Ref<Repo>>('repo');
|
||||
const repoPermissions = inject<Ref<RepoPermissions>>('repo-permissions');
|
||||
if (!repo || !repoPermissions) {
|
||||
throw new Error('Unexpected: "repo" & "repoPermissions" should be provided at this place');
|
||||
}
|
||||
|
||||
const pipeline = pipelineStore.getPipeline(repoOwner, repoName, pipelineId);
|
||||
const pipeline = pipelineStore.getPipeline(repoId, pipelineId);
|
||||
const { since, duration, created } = usePipeline(pipeline);
|
||||
provide('pipeline', pipeline);
|
||||
|
||||
|
@ -131,7 +130,7 @@ async function loadPipeline(): Promise<void> {
|
|||
throw new Error('Unexpected: Repo is undefined');
|
||||
}
|
||||
|
||||
await pipelineStore.loadPipeline(repo.value.owner, repo.value.name, parseInt(pipelineId.value, 10));
|
||||
await pipelineStore.loadPipeline(repo.value.id, parseInt(pipelineId.value, 10));
|
||||
|
||||
favicon.updateStatus(pipeline.value?.status);
|
||||
}
|
||||
|
@ -152,7 +151,7 @@ const { doSubmit: cancelPipeline, isLoading: isCancelingPipeline } = useAsyncAct
|
|||
// throw new Error('Unexpected: Step not found');
|
||||
// }
|
||||
|
||||
await apiClient.cancelPipeline(repo.value.owner, repo.value.name, parseInt(pipelineId.value, 10));
|
||||
await apiClient.cancelPipeline(repo.value.id, parseInt(pipelineId.value, 10));
|
||||
notifications.notify({ title: i18n.t('repo.pipeline.actions.cancel_success'), type: 'success' });
|
||||
});
|
||||
|
||||
|
@ -161,7 +160,7 @@ const { doSubmit: restartPipeline, isLoading: isRestartingPipeline } = useAsyncA
|
|||
throw new Error('Unexpected: Repo is undefined');
|
||||
}
|
||||
|
||||
const newPipeline = await apiClient.restartPipeline(repo.value.owner, repo.value.name, pipelineId.value, {
|
||||
const newPipeline = await apiClient.restartPipeline(repo.value.id, pipelineId.value, {
|
||||
fork: true,
|
||||
});
|
||||
notifications.notify({ title: i18n.t('repo.pipeline.actions.restart_success'), type: 'success' });
|
||||
|
@ -172,7 +171,7 @@ const { doSubmit: restartPipeline, isLoading: isRestartingPipeline } = useAsyncA
|
|||
});
|
||||
|
||||
onMounted(loadPipeline);
|
||||
watch([repoName, repoOwner, pipelineId], loadPipeline);
|
||||
watch([repoId, pipelineId], loadPipeline);
|
||||
onBeforeUnmount(() => {
|
||||
favicon.updateStatus('default');
|
||||
});
|
||||
|
|
|
@ -28,23 +28,24 @@ import (
|
|||
const (
|
||||
pathSelf = "%s/api/user"
|
||||
pathRepos = "%s/api/user/repos"
|
||||
pathRepo = "%s/api/repos/%s/%s"
|
||||
pathRepoMove = "%s/api/repos/%s/%s/move?to=%s"
|
||||
pathChown = "%s/api/repos/%s/%s/chown"
|
||||
pathRepair = "%s/api/repos/%s/%s/repair"
|
||||
pathPipelines = "%s/api/repos/%s/%s/pipelines"
|
||||
pathPipeline = "%s/api/repos/%s/%s/pipelines/%v"
|
||||
pathLogs = "%s/api/repos/%s/%s/logs/%d/%d"
|
||||
pathApprove = "%s/api/repos/%s/%s/pipelines/%d/approve"
|
||||
pathDecline = "%s/api/repos/%s/%s/pipelines/%d/decline"
|
||||
pathStop = "%s/api/repos/%s/%s/pipelines/%d/cancel"
|
||||
pathLogPurge = "%s/api/repos/%s/%s/logs/%d"
|
||||
pathRepoSecrets = "%s/api/repos/%s/%s/secrets"
|
||||
pathRepoSecret = "%s/api/repos/%s/%s/secrets/%s"
|
||||
pathRepoRegistries = "%s/api/repos/%s/%s/registry"
|
||||
pathRepoRegistry = "%s/api/repos/%s/%s/registry/%s"
|
||||
pathRepoCrons = "%s/api/repos/%s/%s/cron"
|
||||
pathRepoCron = "%s/api/repos/%s/%s/cron/%d"
|
||||
pathRepo = "%s/api/repos/%d"
|
||||
pathRepoLookup = "%s/api/repos/lookup/%s"
|
||||
pathRepoMove = "%s/api/repos/%d/move?to=%s"
|
||||
pathChown = "%s/api/repos/%d/chown"
|
||||
pathRepair = "%s/api/repos/%d/repair"
|
||||
pathPipelines = "%s/api/repos/%d/pipelines"
|
||||
pathPipeline = "%s/api/repos/%d/pipelines/%v"
|
||||
pathLogs = "%s/api/repos/%d/logs/%d/%d"
|
||||
pathApprove = "%s/api/repos/%d/pipelines/%d/approve"
|
||||
pathDecline = "%s/api/repos/%d/pipelines/%d/decline"
|
||||
pathStop = "%s/api/repos/%d/pipelines/%d/cancel"
|
||||
pathLogPurge = "%s/api/repos/%d/logs/%d"
|
||||
pathRepoSecrets = "%s/api/repos/%d/secrets"
|
||||
pathRepoSecret = "%s/api/repos/%d/secrets/%s"
|
||||
pathRepoRegistries = "%s/api/repos/%d/registry"
|
||||
pathRepoRegistry = "%s/api/repos/%d/registry/%s"
|
||||
pathRepoCrons = "%s/api/repos/%d/cron"
|
||||
pathRepoCron = "%s/api/repos/%d/cron/%d"
|
||||
pathOrgSecrets = "%s/api/orgs/%s/secrets"
|
||||
pathOrgSecret = "%s/api/orgs/%s/secrets/%s"
|
||||
pathGlobalSecrets = "%s/api/secrets"
|
||||
|
@ -134,10 +135,18 @@ func (c *client) UserDel(login string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Repo returns a repository by name.
|
||||
func (c *client) Repo(owner, name string) (*Repo, error) {
|
||||
// Repo returns a repository by id.
|
||||
func (c *client) Repo(repoID int64) (*Repo, error) {
|
||||
out := new(Repo)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, repoID)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RepoLookup returns a repository by name.
|
||||
func (c *client) RepoLookup(fullName string) (*Repo, error) {
|
||||
out := new(Repo)
|
||||
uri := fmt.Sprintf(pathRepoLookup, c.addr, fullName)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
@ -161,60 +170,60 @@ func (c *client) RepoListOpts(sync, all bool) ([]*Repo, error) {
|
|||
}
|
||||
|
||||
// RepoPost activates a repository.
|
||||
func (c *client) RepoPost(owner, name string) (*Repo, error) {
|
||||
func (c *client) RepoPost(forgeRemoteID int64) (*Repo, error) {
|
||||
out := new(Repo)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, forgeRemoteID)
|
||||
err := c.post(uri, nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RepoChown updates a repository owner.
|
||||
func (c *client) RepoChown(owner, name string) (*Repo, error) {
|
||||
func (c *client) RepoChown(repoID int64) (*Repo, error) {
|
||||
out := new(Repo)
|
||||
uri := fmt.Sprintf(pathChown, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathChown, c.addr, repoID)
|
||||
err := c.post(uri, nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RepoRepair repairs the repository hooks.
|
||||
func (c *client) RepoRepair(owner, name string) error {
|
||||
uri := fmt.Sprintf(pathRepair, c.addr, owner, name)
|
||||
func (c *client) RepoRepair(repoID int64) error {
|
||||
uri := fmt.Sprintf(pathRepair, c.addr, repoID)
|
||||
return c.post(uri, nil, nil)
|
||||
}
|
||||
|
||||
// RepoPatch updates a repository.
|
||||
func (c *client) RepoPatch(owner, name string, in *RepoPatch) (*Repo, error) {
|
||||
func (c *client) RepoPatch(repoID int64, in *RepoPatch) (*Repo, error) {
|
||||
out := new(Repo)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, repoID)
|
||||
err := c.patch(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RepoDel deletes a repository.
|
||||
func (c *client) RepoDel(owner, name string) error {
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, owner, name)
|
||||
func (c *client) RepoDel(repoID int64) error {
|
||||
uri := fmt.Sprintf(pathRepo, c.addr, repoID)
|
||||
err := c.delete(uri)
|
||||
return err
|
||||
}
|
||||
|
||||
// RepoMove moves a repository
|
||||
func (c *client) RepoMove(owner, name, newFullName string) error {
|
||||
uri := fmt.Sprintf(pathRepoMove, c.addr, owner, name, newFullName)
|
||||
func (c *client) RepoMove(repoID int64, newFullName string) error {
|
||||
uri := fmt.Sprintf(pathRepoMove, c.addr, repoID, newFullName)
|
||||
return c.post(uri, nil, nil)
|
||||
}
|
||||
|
||||
// Pipeline returns a repository pipeline by number.
|
||||
func (c *client) Pipeline(owner, name string, num int) (*Pipeline, error) {
|
||||
// Pipeline returns a repository pipeline by pipeline-id.
|
||||
func (c *client) Pipeline(repoID int64, pipeline int) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, owner, name, num)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Pipeline returns the latest repository pipeline by branch.
|
||||
func (c *client) PipelineLast(owner, name, branch string) (*Pipeline, error) {
|
||||
func (c *client) PipelineLast(repoID int64, branch string) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, owner, name, "latest")
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, "latest")
|
||||
if len(branch) != 0 {
|
||||
uri += "?branch=" + branch
|
||||
}
|
||||
|
@ -224,16 +233,16 @@ func (c *client) PipelineLast(owner, name, branch string) (*Pipeline, error) {
|
|||
|
||||
// PipelineList returns a list of recent pipelines for the
|
||||
// the specified repository.
|
||||
func (c *client) PipelineList(owner, name string) ([]*Pipeline, error) {
|
||||
func (c *client) PipelineList(repoID int64) ([]*Pipeline, error) {
|
||||
var out []*Pipeline
|
||||
uri := fmt.Sprintf(pathPipelines, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathPipelines, c.addr, repoID)
|
||||
err := c.get(uri, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (c *client) PipelineCreate(owner, name string, options *PipelineOptions) (*Pipeline, error) {
|
||||
func (c *client) PipelineCreate(repoID int64, options *PipelineOptions) (*Pipeline, error) {
|
||||
var out *Pipeline
|
||||
uri := fmt.Sprintf(pathPipelines, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathPipelines, c.addr, repoID)
|
||||
err := c.post(uri, options, &out)
|
||||
return out, err
|
||||
}
|
||||
|
@ -247,47 +256,47 @@ func (c *client) PipelineQueue() ([]*Activity, error) {
|
|||
}
|
||||
|
||||
// PipelineStart re-starts a stopped pipeline.
|
||||
func (c *client) PipelineStart(owner, name string, num int, params map[string]string) (*Pipeline, error) {
|
||||
func (c *client) PipelineStart(repoID int64, pipeline int, params map[string]string) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
val := mapValues(params)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, owner, name, num)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
|
||||
err := c.post(uri+"?"+val.Encode(), nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// PipelineStop cancels the running step.
|
||||
func (c *client) PipelineStop(owner, name string, pipeline int) error {
|
||||
uri := fmt.Sprintf(pathStop, c.addr, owner, name, pipeline)
|
||||
func (c *client) PipelineStop(repoID int64, pipeline int) error {
|
||||
uri := fmt.Sprintf(pathStop, c.addr, repoID, pipeline)
|
||||
err := c.post(uri, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// PipelineApprove approves a blocked pipeline.
|
||||
func (c *client) PipelineApprove(owner, name string, num int) (*Pipeline, error) {
|
||||
func (c *client) PipelineApprove(repoID int64, pipeline int) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
uri := fmt.Sprintf(pathApprove, c.addr, owner, name, num)
|
||||
uri := fmt.Sprintf(pathApprove, c.addr, repoID, pipeline)
|
||||
err := c.post(uri, nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// PipelineDecline declines a blocked pipeline.
|
||||
func (c *client) PipelineDecline(owner, name string, num int) (*Pipeline, error) {
|
||||
func (c *client) PipelineDecline(repoID int64, pipeline int) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
uri := fmt.Sprintf(pathDecline, c.addr, owner, name, num)
|
||||
uri := fmt.Sprintf(pathDecline, c.addr, repoID, pipeline)
|
||||
err := c.post(uri, nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// PipelineKill force kills the running pipeline.
|
||||
func (c *client) PipelineKill(owner, name string, num int) error {
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, owner, name, num)
|
||||
func (c *client) PipelineKill(repoID int64, pipeline int) error {
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
|
||||
err := c.delete(uri)
|
||||
return err
|
||||
}
|
||||
|
||||
// PipelineLogs returns the pipeline logs for the specified step.
|
||||
func (c *client) StepLogEntries(owner, name string, num, step int) ([]*LogEntry, error) {
|
||||
uri := fmt.Sprintf(pathLogs, c.addr, owner, name, num, step)
|
||||
func (c *client) StepLogEntries(repoID int64, num, step int) ([]*LogEntry, error) {
|
||||
uri := fmt.Sprintf(pathLogs, c.addr, repoID, num, step)
|
||||
var out []*LogEntry
|
||||
err := c.get(uri, &out)
|
||||
return out, err
|
||||
|
@ -295,96 +304,96 @@ func (c *client) StepLogEntries(owner, name string, num, step int) ([]*LogEntry,
|
|||
|
||||
// Deploy triggers a deployment for an existing pipeline using the
|
||||
// specified target environment.
|
||||
func (c *client) Deploy(owner, name string, num int, env string, params map[string]string) (*Pipeline, error) {
|
||||
func (c *client) Deploy(repoID int64, pipeline int, env string, params map[string]string) (*Pipeline, error) {
|
||||
out := new(Pipeline)
|
||||
val := mapValues(params)
|
||||
val.Set("event", EventDeploy)
|
||||
val.Set("deploy_to", env)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, owner, name, num)
|
||||
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
|
||||
err := c.post(uri+"?"+val.Encode(), nil, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// LogsPurge purges the pipeline logs for the specified pipeline.
|
||||
func (c *client) LogsPurge(owner, name string, num int) error {
|
||||
uri := fmt.Sprintf(pathLogPurge, c.addr, owner, name, num)
|
||||
func (c *client) LogsPurge(repoID int64, pipeline int) error {
|
||||
uri := fmt.Sprintf(pathLogPurge, c.addr, repoID, pipeline)
|
||||
err := c.delete(uri)
|
||||
return err
|
||||
}
|
||||
|
||||
// Registry returns a registry by hostname.
|
||||
func (c *client) Registry(owner, name, hostname string) (*Registry, error) {
|
||||
func (c *client) Registry(repoID int64, hostname string) (*Registry, error) {
|
||||
out := new(Registry)
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, owner, name, hostname)
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, repoID, hostname)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RegistryList returns a list of all repository registries.
|
||||
func (c *client) RegistryList(owner, name string) ([]*Registry, error) {
|
||||
func (c *client) RegistryList(repoID int64) ([]*Registry, error) {
|
||||
var out []*Registry
|
||||
uri := fmt.Sprintf(pathRepoRegistries, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepoRegistries, c.addr, repoID)
|
||||
err := c.get(uri, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RegistryCreate creates a registry.
|
||||
func (c *client) RegistryCreate(owner, name string, in *Registry) (*Registry, error) {
|
||||
func (c *client) RegistryCreate(repoID int64, in *Registry) (*Registry, error) {
|
||||
out := new(Registry)
|
||||
uri := fmt.Sprintf(pathRepoRegistries, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepoRegistries, c.addr, repoID)
|
||||
err := c.post(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RegistryUpdate updates a registry.
|
||||
func (c *client) RegistryUpdate(owner, name string, in *Registry) (*Registry, error) {
|
||||
func (c *client) RegistryUpdate(repoID int64, in *Registry) (*Registry, error) {
|
||||
out := new(Registry)
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, owner, name, in.Address)
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, repoID, in.Address)
|
||||
err := c.patch(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// RegistryDelete deletes a registry.
|
||||
func (c *client) RegistryDelete(owner, name, hostname string) error {
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, owner, name, hostname)
|
||||
func (c *client) RegistryDelete(repoID int64, hostname string) error {
|
||||
uri := fmt.Sprintf(pathRepoRegistry, c.addr, repoID, hostname)
|
||||
return c.delete(uri)
|
||||
}
|
||||
|
||||
// Secret returns a secret by name.
|
||||
func (c *client) Secret(owner, name, secret string) (*Secret, error) {
|
||||
func (c *client) Secret(repoID int64, secret string) (*Secret, error) {
|
||||
out := new(Secret)
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, secret)
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, repoID, secret)
|
||||
err := c.get(uri, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SecretList returns a list of all repository secrets.
|
||||
func (c *client) SecretList(owner, name string) ([]*Secret, error) {
|
||||
func (c *client) SecretList(repoID int64) ([]*Secret, error) {
|
||||
var out []*Secret
|
||||
uri := fmt.Sprintf(pathRepoSecrets, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepoSecrets, c.addr, repoID)
|
||||
err := c.get(uri, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SecretCreate creates a secret.
|
||||
func (c *client) SecretCreate(owner, name string, in *Secret) (*Secret, error) {
|
||||
func (c *client) SecretCreate(repoID int64, in *Secret) (*Secret, error) {
|
||||
out := new(Secret)
|
||||
uri := fmt.Sprintf(pathRepoSecrets, c.addr, owner, name)
|
||||
uri := fmt.Sprintf(pathRepoSecrets, c.addr, repoID)
|
||||
err := c.post(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SecretUpdate updates a secret.
|
||||
func (c *client) SecretUpdate(owner, name string, in *Secret) (*Secret, error) {
|
||||
func (c *client) SecretUpdate(repoID int64, in *Secret) (*Secret, error) {
|
||||
out := new(Secret)
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, in.Name)
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, repoID, in.Name)
|
||||
err := c.patch(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// SecretDelete deletes a secret.
|
||||
func (c *client) SecretDelete(owner, name, secret string) error {
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, owner, name, secret)
|
||||
func (c *client) SecretDelete(repoID int64, secret string) error {
|
||||
uri := fmt.Sprintf(pathRepoSecret, c.addr, repoID, secret)
|
||||
return c.delete(uri)
|
||||
}
|
||||
|
||||
|
@ -488,33 +497,33 @@ func (c *client) SetLogLevel(in *LogLevel) (*LogLevel, error) {
|
|||
return out, err
|
||||
}
|
||||
|
||||
func (c *client) CronList(owner, repo string) ([]*Cron, error) {
|
||||
func (c *client) CronList(repoID int64) ([]*Cron, error) {
|
||||
out := make([]*Cron, 0, 5)
|
||||
uri := fmt.Sprintf(pathRepoCrons, c.addr, owner, repo)
|
||||
uri := fmt.Sprintf(pathRepoCrons, c.addr, repoID)
|
||||
return out, c.get(uri, &out)
|
||||
}
|
||||
|
||||
func (c *client) CronCreate(owner, repo string, in *Cron) (*Cron, error) {
|
||||
func (c *client) CronCreate(repoID int64, in *Cron) (*Cron, error) {
|
||||
out := new(Cron)
|
||||
uri := fmt.Sprintf(pathRepoCrons, c.addr, owner, repo)
|
||||
uri := fmt.Sprintf(pathRepoCrons, c.addr, repoID)
|
||||
return out, c.post(uri, in, out)
|
||||
}
|
||||
|
||||
func (c *client) CronUpdate(owner, repo string, in *Cron) (*Cron, error) {
|
||||
func (c *client) CronUpdate(repoID int64, in *Cron) (*Cron, error) {
|
||||
out := new(Cron)
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, owner, repo, in.ID)
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, repoID, in.ID)
|
||||
err := c.patch(uri, in, out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
func (c *client) CronDelete(owner, repo string, cronID int64) error {
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, owner, repo, cronID)
|
||||
func (c *client) CronDelete(repoID, cronID int64) error {
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, repoID, cronID)
|
||||
return c.delete(uri)
|
||||
}
|
||||
|
||||
func (c *client) CronGet(owner, repo string, cronID int64) (*Cron, error) {
|
||||
func (c *client) CronGet(repoID, cronID int64) (*Cron, error) {
|
||||
out := new(Cron)
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, owner, repo, cronID)
|
||||
uri := fmt.Sprintf(pathRepoCron, c.addr, repoID, cronID)
|
||||
return out, c.get(uri, out)
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,10 @@ type Client interface {
|
|||
UserDel(string) error
|
||||
|
||||
// Repo returns a repository by name.
|
||||
Repo(string, string) (*Repo, error)
|
||||
Repo(repoID int64) (*Repo, error)
|
||||
|
||||
// RepoLookup returns a repository id by the owner and name.
|
||||
RepoLookup(repoFullName string) (*Repo, error)
|
||||
|
||||
// RepoList returns a list of all repositories to which the user has explicit
|
||||
// access in the host system.
|
||||
|
@ -56,94 +59,94 @@ type Client interface {
|
|||
RepoListOpts(bool, bool) ([]*Repo, error)
|
||||
|
||||
// RepoPost activates a repository.
|
||||
RepoPost(string, string) (*Repo, error)
|
||||
RepoPost(forgeRemoteID int64) (*Repo, error)
|
||||
|
||||
// RepoPatch updates a repository.
|
||||
RepoPatch(string, string, *RepoPatch) (*Repo, error)
|
||||
RepoPatch(repoID int64, repo *RepoPatch) (*Repo, error)
|
||||
|
||||
// RepoMove moves the repository
|
||||
RepoMove(string, string, string) error
|
||||
RepoMove(repoID int64, dst string) error
|
||||
|
||||
// RepoChown updates a repository owner.
|
||||
RepoChown(string, string) (*Repo, error)
|
||||
RepoChown(repoID int64) (*Repo, error)
|
||||
|
||||
// RepoRepair repairs the repository hooks.
|
||||
RepoRepair(string, string) error
|
||||
RepoRepair(repoID int64) error
|
||||
|
||||
// RepoDel deletes a repository.
|
||||
RepoDel(string, string) error
|
||||
RepoDel(repoID int64) error
|
||||
|
||||
// Pipeline returns a repository pipeline by number.
|
||||
Pipeline(string, string, int) (*Pipeline, error)
|
||||
Pipeline(repoID int64, pipeline int) (*Pipeline, error)
|
||||
|
||||
// PipelineLast returns the latest repository pipeline by branch. An empty branch
|
||||
// will result in the default branch.
|
||||
PipelineLast(string, string, string) (*Pipeline, error)
|
||||
PipelineLast(repoID int64, branch string) (*Pipeline, error)
|
||||
|
||||
// PipelineList returns a list of recent pipelines for the
|
||||
// the specified repository.
|
||||
PipelineList(string, string) ([]*Pipeline, error)
|
||||
PipelineList(repoID int64) ([]*Pipeline, error)
|
||||
|
||||
// PipelineQueue returns a list of enqueued pipelines.
|
||||
PipelineQueue() ([]*Activity, error)
|
||||
|
||||
// PipelineCreate returns creates a pipeline on specified branch.
|
||||
PipelineCreate(string, string, *PipelineOptions) (*Pipeline, error)
|
||||
PipelineCreate(repoID int64, opts *PipelineOptions) (*Pipeline, error)
|
||||
|
||||
// PipelineStart re-starts a stopped pipeline.
|
||||
PipelineStart(string, string, int, map[string]string) (*Pipeline, error)
|
||||
PipelineStart(repoID int64, num int, params map[string]string) (*Pipeline, error)
|
||||
|
||||
// PipelineStop stops the given pipeline.
|
||||
PipelineStop(string, string, int) error
|
||||
PipelineStop(repoID int64, pipeline int) error
|
||||
|
||||
// PipelineApprove approves a blocked pipeline.
|
||||
PipelineApprove(string, string, int) (*Pipeline, error)
|
||||
PipelineApprove(repoID int64, pipeline int) (*Pipeline, error)
|
||||
|
||||
// PipelineDecline declines a blocked pipeline.
|
||||
PipelineDecline(string, string, int) (*Pipeline, error)
|
||||
PipelineDecline(repoID int64, pipeline int) (*Pipeline, error)
|
||||
|
||||
// PipelineKill force kills the running pipeline.
|
||||
PipelineKill(string, string, int) error
|
||||
PipelineKill(repoID int64, pipeline int) error
|
||||
|
||||
// StepLogEntries returns the LogEntries for the given pipeline step
|
||||
StepLogEntries(string, string, int, int) ([]*LogEntry, error)
|
||||
StepLogEntries(repoID int64, pipeline, stepID int) ([]*LogEntry, error)
|
||||
|
||||
// Deploy triggers a deployment for an existing pipeline using the specified
|
||||
// target environment.
|
||||
Deploy(string, string, int, string, map[string]string) (*Pipeline, error)
|
||||
Deploy(repoID int64, pipeline int, env string, params map[string]string) (*Pipeline, error)
|
||||
|
||||
// LogsPurge purges the pipeline logs for the specified pipeline.
|
||||
LogsPurge(string, string, int) error
|
||||
LogsPurge(repoID int64, pipeline int) error
|
||||
|
||||
// Registry returns a registry by hostname.
|
||||
Registry(owner, name, hostname string) (*Registry, error)
|
||||
Registry(repoID int64, hostname string) (*Registry, error)
|
||||
|
||||
// RegistryList returns a list of all repository registries.
|
||||
RegistryList(owner, name string) ([]*Registry, error)
|
||||
RegistryList(repoID int64) ([]*Registry, error)
|
||||
|
||||
// RegistryCreate creates a registry.
|
||||
RegistryCreate(owner, name string, registry *Registry) (*Registry, error)
|
||||
RegistryCreate(repoID int64, registry *Registry) (*Registry, error)
|
||||
|
||||
// RegistryUpdate updates a registry.
|
||||
RegistryUpdate(owner, name string, registry *Registry) (*Registry, error)
|
||||
RegistryUpdate(repoID int64, registry *Registry) (*Registry, error)
|
||||
|
||||
// RegistryDelete deletes a registry.
|
||||
RegistryDelete(owner, name, hostname string) error
|
||||
RegistryDelete(repoID int64, hostname string) error
|
||||
|
||||
// Secret returns a secret by name.
|
||||
Secret(owner, name, secret string) (*Secret, error)
|
||||
Secret(repoID int64, secret string) (*Secret, error)
|
||||
|
||||
// SecretList returns a list of all repository secrets.
|
||||
SecretList(owner, name string) ([]*Secret, error)
|
||||
SecretList(repoID int64) ([]*Secret, error)
|
||||
|
||||
// SecretCreate creates a secret.
|
||||
SecretCreate(owner, name string, secret *Secret) (*Secret, error)
|
||||
SecretCreate(repoID int64, secret *Secret) (*Secret, error)
|
||||
|
||||
// SecretUpdate updates a secret.
|
||||
SecretUpdate(owner, name string, secret *Secret) (*Secret, error)
|
||||
SecretUpdate(repoID int64, secret *Secret) (*Secret, error)
|
||||
|
||||
// SecretDelete deletes a secret.
|
||||
SecretDelete(owner, name, secret string) error
|
||||
SecretDelete(repoID int64, secret string) error
|
||||
|
||||
// OrgSecret returns an organization secret by name.
|
||||
OrgSecret(owner, secret string) (*Secret, error)
|
||||
|
@ -185,19 +188,19 @@ type Client interface {
|
|||
SetLogLevel(logLevel *LogLevel) (*LogLevel, error)
|
||||
|
||||
// CronList list all cron jobs of a repo
|
||||
CronList(owner, repo string) ([]*Cron, error)
|
||||
CronList(repoID int64) ([]*Cron, error)
|
||||
|
||||
// CronGet get a specific cron job of a repo by id
|
||||
CronGet(owner, repo string, cronID int64) (*Cron, error)
|
||||
CronGet(repoID, cronID int64) (*Cron, error)
|
||||
|
||||
// CronDelete delete a specific cron job of a repo by id
|
||||
CronDelete(owner, repo string, cronID int64) error
|
||||
CronDelete(repoID, cronID int64) error
|
||||
|
||||
// CronCreate create a new cron job in a repo
|
||||
CronCreate(owner, repo string, cron *Cron) (*Cron, error)
|
||||
CronCreate(repoID int64, cron *Cron) (*Cron, error)
|
||||
|
||||
// CronUpdate update an existing cron job of a repo
|
||||
CronUpdate(owner, repo string, cron *Cron) (*Cron, error)
|
||||
CronUpdate(repoID int64, cron *Cron) (*Cron, error)
|
||||
|
||||
// AgentList returns a list of all registered agents
|
||||
AgentList() ([]*Agent, error)
|
||||
|
|
|
@ -27,23 +27,26 @@ type (
|
|||
|
||||
// Repo represents a repository.
|
||||
Repo struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
Owner string `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Avatar string `json:"avatar_url,omitempty"`
|
||||
Link string `json:"link_url,omitempty"`
|
||||
Kind string `json:"scm,omitempty"`
|
||||
Clone string `json:"clone_url,omitempty"`
|
||||
Branch string `json:"default_branch,omitempty"`
|
||||
Timeout int64 `json:"timeout,omitempty"`
|
||||
Visibility string `json:"visibility"`
|
||||
IsPrivate bool `json:"private,omitempty"`
|
||||
IsTrusted bool `json:"trusted"`
|
||||
IsStarred bool `json:"starred,omitempty"`
|
||||
IsGated bool `json:"gated"`
|
||||
AllowPull bool `json:"allow_pr"`
|
||||
Config string `json:"config_file"`
|
||||
ID int64 `json:"id,omitempty"`
|
||||
ForgeRemoteID string `json:"forge_remote_id"`
|
||||
Owner string `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Avatar string `json:"avatar_url,omitempty"`
|
||||
Link string `json:"link_url,omitempty"`
|
||||
Clone string `json:"clone_url,omitempty"`
|
||||
DefaultBranch string `json:"default_branch,omitempty"`
|
||||
SCMKind string `json:"scm,omitempty"`
|
||||
Timeout int64 `json:"timeout,omitempty"`
|
||||
Visibility string `json:"visibility"`
|
||||
IsSCMPrivate bool `json:"private"`
|
||||
IsTrusted bool `json:"trusted"`
|
||||
IsGated bool `json:"gated"`
|
||||
IsActive bool `json:"active"`
|
||||
AllowPullRequests bool `json:"allow_pr"`
|
||||
Config string `json:"config_file"`
|
||||
CancelPreviousPipelineEvents []string `json:"cancel_previous_pipeline_events"`
|
||||
NetrcOnlyTrusted bool `json:"netrc_only_trusted"`
|
||||
}
|
||||
|
||||
// RepoPatch defines a repository patch request.
|
||||
|
|
Loading…
Reference in a new issue