Skip to content

Commit fc69a4f

Browse files
committed
Sync milestones between repositories (#3)
Closes #3 This took so long I hate go
1 parent e94d6bc commit fc69a4f

12 files changed

+249
-10
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ go.work.sum
2323

2424
# env file
2525
.env
26+
27+
# JetBrains IDEs
28+
.idea/

client/github/github_client.go

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package github
2+
3+
import "github.com/google/go-github/v67/github"
4+
5+
var client = github.NewClient(nil)

client/github/github_milestones.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"github.com/google/go-github/v67/github"
6+
"propromo/utils"
7+
)
8+
9+
func ListGitHubMilestones(repo utils.GitRepo) ([]*github.Milestone, error) {
10+
ctx := context.Background()
11+
12+
milestones, _, err := client.Issues.ListMilestones(ctx, repo.Owner, repo.Repository, nil)
13+
return milestones, err
14+
}
15+
16+
func CreateGitHubMilestone(token string, repo utils.GitRepo, milestone *github.Milestone) (*github.Milestone, error) {
17+
ctx := context.Background()
18+
client := github.NewClient(nil).WithAuthToken(token)
19+
20+
milestones, _, err := client.Issues.CreateMilestone(ctx, repo.Owner, repo.Repository, milestone)
21+
return milestones, err
22+
}

cmd/github/github.go

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package cmd
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
)
6+
7+
var GithubCmd = &cobra.Command{
8+
Use: "github",
9+
Short: "Github-related utilities",
10+
}
11+
12+
func init() {
13+
GithubCmd.AddCommand(syncCmd)
14+
}

cmd/github/sync.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package cmd
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
"github.com/spf13/viper"
6+
"propromo/cmdutils"
7+
)
8+
9+
var syncCmd = &cobra.Command{
10+
Use: "sync",
11+
Short: "Syncing utilities for GitHub",
12+
}
13+
14+
var source string
15+
var targets []string
16+
17+
func init() {
18+
syncCmd.AddCommand(milestonesCmd)
19+
}
20+
21+
func getToken() string {
22+
token := viper.GetString("token")
23+
if token == "" {
24+
cmdutils.Logger.Fatal("No token provided.")
25+
}
26+
return token
27+
}
28+
29+
func syncFlags(cmd *cobra.Command) {
30+
cmd.Flags().String("token", "", "github token")
31+
cobra.CheckErr(viper.BindPFlag("token", cmd.Flags().Lookup("token")))
32+
33+
cmd.Flags().StringVarP(&source, "source", "s", "", "Source repository")
34+
cobra.CheckErr(cmd.MarkFlagRequired("source"))
35+
cmd.Flags().StringSliceVarP(&targets, "target", "t", []string{}, "Comma-separated target repository(s)")
36+
cobra.CheckErr(cmd.MarkFlagRequired("target"))
37+
}

cmd/github/sync_milestones.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
githubmodel "github.com/google/go-github/v67/github"
7+
"github.com/spf13/cobra"
8+
"propromo/client/github"
9+
"propromo/cmdutils"
10+
"propromo/utils"
11+
)
12+
13+
var milestonesCmd = &cobra.Command{
14+
Use: "milestones",
15+
Short: "Sync milestones from one repo to others",
16+
Run: func(command *cobra.Command, args []string) {
17+
fmt.Println("Syncing from", source, "to", targets)
18+
19+
sourceRepo, err := utils.ParseGitRepo(source)
20+
cobra.CheckErr(err)
21+
22+
milestones, err := github.ListGitHubMilestones(sourceRepo)
23+
cobra.CheckErr(err)
24+
25+
repos := make([]utils.GitRepo, len(targets))
26+
for i, target := range targets {
27+
repo, err := utils.ParseGitRepo(target)
28+
cobra.CheckErr(err)
29+
repos[i] = repo
30+
}
31+
32+
token := getToken()
33+
for _, repo := range repos {
34+
for _, milestone := range milestones {
35+
_, err := github.CreateGitHubMilestone(token, repo, &githubmodel.Milestone{
36+
Title: milestone.Title,
37+
State: milestone.State,
38+
Description: milestone.Description,
39+
DueOn: milestone.DueOn,
40+
})
41+
42+
var ghErr *githubmodel.ErrorResponse
43+
if errors.As(err, &ghErr) && len(ghErr.Errors) == 1 && ghErr.Errors[0].Code == "already_exists" {
44+
cmdutils.Logger.Info("Milestone already exists!", "repo", repo.String(), "milestone", *milestone.Title)
45+
continue
46+
}
47+
cmdutils.Logger.Info("Milestone successfully created", "repo", repo.String(), "milestone", *milestone.Title)
48+
}
49+
}
50+
},
51+
}
52+
53+
func init() {
54+
syncFlags(milestonesCmd)
55+
}

cmd/root.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ package cmd
22

33
import (
44
"fmt"
5-
"os"
6-
75
"github.com/spf13/cobra"
86
"github.com/spf13/viper"
7+
"os"
8+
github "propromo/cmd/github"
99
)
1010

1111
var cfgFile string
1212

1313
var rootCmd = &cobra.Command{
1414
Use: "propromo-cli",
1515
Short: "A CLI that integrates with propromo",
16-
Long: `propromo-cli is a CLI that integrates with your VCS. It can sync milestones and labels between repositories.`,
16+
Long: `propromo-cli is a CLI that integrates with your VCS. It can sync milestones and labels between repositories.`,
1717
}
1818

1919
func Execute() {
@@ -27,6 +27,8 @@ func init() {
2727
cobra.OnInitialize(initConfig)
2828

2929
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (defaults are $XDG_CONFIG_HOME/propromo-cli.yml and $HOME/propromo-cli.yml)")
30+
31+
rootCmd.AddCommand(github.GithubCmd)
3032
}
3133

3234
func initConfig() {

cmdutils/logger.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package cmdutils
2+
3+
import (
4+
"github.com/charmbracelet/log"
5+
"os"
6+
)
7+
8+
var Logger = log.NewWithOptions(os.Stdout, log.Options{
9+
ReportCaller: true,
10+
ReportTimestamp: true,
11+
})

go.mod

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,41 @@
1-
module propromo.cli
1+
module propromo
22

33
go 1.23.2
44

55
require (
6+
github.com/charmbracelet/log v0.4.0
7+
github.com/google/go-github/v67 v67.0.0
8+
github.com/spf13/cobra v1.8.1
9+
github.com/spf13/viper v1.19.0
10+
)
11+
12+
require (
13+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
14+
github.com/charmbracelet/lipgloss v0.10.0 // indirect
615
github.com/fsnotify/fsnotify v1.7.0 // indirect
16+
github.com/go-logfmt/logfmt v0.6.0 // indirect
17+
github.com/google/go-querystring v1.1.0 // indirect
718
github.com/hashicorp/hcl v1.0.0 // indirect
819
github.com/inconshreveable/mousetrap v1.1.0 // indirect
20+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
921
github.com/magiconair/properties v1.8.7 // indirect
22+
github.com/mattn/go-isatty v0.0.18 // indirect
23+
github.com/mattn/go-runewidth v0.0.15 // indirect
1024
github.com/mitchellh/mapstructure v1.5.0 // indirect
25+
github.com/muesli/reflow v0.3.0 // indirect
26+
github.com/muesli/termenv v0.15.2 // indirect
1127
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
28+
github.com/rivo/uniseg v0.4.7 // indirect
1229
github.com/sagikazarmark/locafero v0.4.0 // indirect
1330
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
1431
github.com/sourcegraph/conc v0.3.0 // indirect
1532
github.com/spf13/afero v1.11.0 // indirect
1633
github.com/spf13/cast v1.6.0 // indirect
17-
github.com/spf13/cobra v1.8.1 // indirect
1834
github.com/spf13/pflag v1.0.5 // indirect
19-
github.com/spf13/viper v1.19.0 // indirect
2035
github.com/subosito/gotenv v1.6.0 // indirect
2136
go.uber.org/atomic v1.9.0 // indirect
2237
go.uber.org/multierr v1.9.0 // indirect
23-
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
38+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
2439
golang.org/x/sys v0.18.0 // indirect
2540
golang.org/x/text v0.14.0 // indirect
2641
gopkg.in/ini.v1 v1.67.0 // indirect

go.sum

+49-2
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,61 @@
1+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
2+
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
3+
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
4+
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
5+
github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8ZM=
6+
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
17
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
28
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
39
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
11+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
13+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
414
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
515
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
16+
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
17+
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
18+
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
19+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
20+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
21+
github.com/google/go-github/v67 v67.0.0 h1:g11NDAmfaBaCO8qYdI9fsmbaRipHNWRIU/2YGvlh4rg=
22+
github.com/google/go-github/v67 v67.0.0/go.mod h1:zH3K7BxjFndr9QSeFibx4lTKkYS3K9nDanoI1NjaOtY=
23+
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
24+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
625
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
726
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
827
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
928
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
29+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
30+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
31+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
32+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
33+
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
34+
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
1035
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
1136
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
37+
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
38+
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
39+
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
40+
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
41+
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
1242
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
1343
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
44+
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
45+
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
46+
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
47+
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
1448
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
1549
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
1650
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
51+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
52+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
53+
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
54+
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
55+
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
56+
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
57+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
58+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
1759
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
1860
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
1961
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
@@ -39,20 +81,25 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
3981
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
4082
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
4183
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
84+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
4285
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
4386
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
4487
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
4588
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
4689
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
4790
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
4891
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
49-
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
50-
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
92+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
93+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
94+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5195
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
5296
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5397
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
5498
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
99+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
55100
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
101+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
102+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
56103
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
57104
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
58105
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package main
22

3-
import "propromo.cli/cmd"
3+
import "propromo/cmd"
44

55
func main() {
66
cmd.Execute()

utils/git.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type GitRepo struct {
9+
Owner string
10+
Repository string
11+
}
12+
13+
func (repo *GitRepo) String() string {
14+
return fmt.Sprintf("%s/%s", repo.Owner, repo.Repository)
15+
}
16+
17+
func ParseGitRepo(s string) (GitRepo, error) {
18+
// parse `org/repo` to `org` and `repo`
19+
result := strings.Split(s, "/")
20+
if len(strings.Split(s, "/")) != 2 {
21+
return GitRepo{}, fmt.Errorf("invalid git repo: %s", s)
22+
}
23+
24+
return GitRepo{
25+
Owner: result[0],
26+
Repository: result[1],
27+
}, nil
28+
}

0 commit comments

Comments
 (0)