Skip to content

Commit 64e2161

Browse files
authored
feat: 多个文件合并到一个提交 (#2)
* feat: 多个文件合并到一个提交 * fix: 修复程序bug * chore: 删除弃用代码
1 parent aff2297 commit 64e2161

2 files changed

Lines changed: 153 additions & 61 deletions

File tree

action.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ runs:
3333
shell: bash
3434
run: |
3535
go env -w GO111MODULE=on
36+
go env -w GOPROXY=direct
3637
go install github.com/linuxdeepin/action-sync@main
3738
- name: command
3839
shell: bash

main.go

Lines changed: 152 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,38 @@ import (
1010
"log"
1111
"net/http"
1212
"os"
13+
"regexp"
1314
"strings"
15+
"time"
1416

1517
"github.com/bradleyfalzon/ghinstallation"
1618
"github.com/google/go-github/github"
1719
)
1820

21+
type Config struct {
22+
Src string `json:"src"`
23+
Dest string `json:"dest"`
24+
Branches []string `json:"branches"`
25+
}
26+
type Branch struct {
27+
Owner string
28+
Repo string
29+
Branch string
30+
Base string
31+
}
32+
1933
func main() {
2034
privateKey := []byte(os.Getenv("PRIVATE_KEY"))
2135
var appID, installationID int64
2236
var files, message string
2337
var dryRun bool
38+
var autoMerge bool
2439
flag.Int64Var(&appID, "app_id", 0, "github app id")
2540
flag.Int64Var(&installationID, "installation_id", 0, "github installation id")
2641
flag.StringVar(&message, "message", "chore: Sync by .github", "commit message")
2742
flag.StringVar(&files, "files", "", "config files, separated by spaces")
2843
flag.BoolVar(&dryRun, "dryRun", false, "dry run")
44+
flag.BoolVar(&autoMerge, "autoMerge", true, "auto merge")
2945
flag.Parse()
3046
if appID == 0 || installationID == 0 || len(message) == 0 || len(files) == 0 {
3147
flag.PrintDefaults()
@@ -45,88 +61,163 @@ func main() {
4561
if err != nil {
4662
log.Fatal(err)
4763
}
48-
var configs []struct {
49-
Src string `json:"src"`
50-
Dest string `json:"dest"`
51-
Branches []string `json:"branches"`
52-
}
64+
var configs []Config
5365
err = json.Unmarshal(data, &configs)
5466
if err != nil {
5567
log.Fatal(err)
5668
}
5769
log.Println("Config", file)
70+
71+
mergeBranch := map[string]Branch{}
72+
cleanupBranch := map[string]Branch{}
5873
for _, config := range configs {
59-
arr := strings.SplitN(config.Dest, "/", 3)
60-
if len(arr) != 3 {
61-
log.Fatal("wrong dist. example: username/repo/file")
74+
owner, repo, path, err := split(config.Dest)
75+
if err != nil {
76+
log.Fatal(err)
6277
}
63-
owner := arr[0]
64-
repo := arr[1]
65-
path := arr[2]
6678
log.Printf("\tSync %s to %s/%s/%s", config.Src, owner, repo, path)
6779
if dryRun {
6880
continue
6981
}
70-
err = sendFile(ctx, client, config.Src, owner, repo, path, message, config.Branches)
82+
83+
var syncBranches []string
84+
branches, _, err := client.Repositories.ListBranches(ctx, owner, repo, nil)
7185
if err != nil {
7286
log.Fatal(err)
7387
}
88+
// match branch
89+
if len(config.Branches) == 0 {
90+
for i := range branches {
91+
syncBranches = append(syncBranches, *branches[i].Name)
92+
}
93+
} else {
94+
for i := range config.Branches {
95+
reg := regexp.MustCompile(config.Branches[i])
96+
match := false
97+
for j := range branches {
98+
if reg.Match([]byte(*branches[j].Name)) {
99+
match = true
100+
break
101+
}
102+
}
103+
if match {
104+
syncBranches = append(syncBranches, *branches[i].Name)
105+
}
106+
}
107+
}
108+
for i := range syncBranches {
109+
key := fmt.Sprintf("%s/%s/%s", owner, repo, syncBranches[i])
110+
var branch Branch
111+
branch, ok := cleanupBranch[key]
112+
if !ok {
113+
tempBranch := fmt.Sprintf("sync/t_%d/%s", time.Now().Unix(), syncBranches[i])
114+
tempRef := fmt.Sprintf("refs/heads/%s", tempBranch)
115+
ref, _, err := client.Git.GetRef(ctx, owner, repo, fmt.Sprintf("heads/%s", syncBranches[i]))
116+
if err != nil {
117+
log.Fatal(err)
118+
}
119+
ref.Ref = github.String(tempRef)
120+
_, _, err = client.Git.CreateRef(ctx, owner, repo, ref)
121+
if err != nil {
122+
log.Fatal(err)
123+
}
124+
branch = Branch{Owner: owner, Repo: repo, Base: syncBranches[i], Branch: tempBranch}
125+
cleanupBranch[key] = branch
126+
}
127+
128+
changed, err := sendFile(ctx, client, config.Src, owner, repo, path, message, branch.Branch)
129+
if err != nil {
130+
log.Fatal(err)
131+
}
132+
if changed {
133+
log.Printf("\t\tBranch Sync: %s TempBranch: %s\n", branch.Base, branch.Branch)
134+
mergeBranch[key] = branch
135+
} else {
136+
log.Printf("\t\tBranch No Change: %s TempBranch: %s\n", branch.Base, branch.Branch)
137+
}
138+
}
139+
}
140+
141+
for _, branch := range mergeBranch {
142+
pr, _, err := client.PullRequests.Create(ctx, branch.Owner, branch.Repo, &github.NewPullRequest{
143+
Title: &message,
144+
Head: github.String(branch2Ref(branch.Branch)),
145+
Base: github.String(branch2Ref(branch.Base)),
146+
MaintainerCanModify: github.Bool(true),
147+
})
148+
if err != nil {
149+
log.Println("create pull request: %w", err)
150+
continue
151+
}
152+
if autoMerge {
153+
_, _, err = client.PullRequests.Merge(ctx,
154+
branch.Owner, branch.Repo,
155+
pr.GetNumber(), message,
156+
&github.PullRequestOptions{SHA: pr.GetHead().GetSHA(), MergeMethod: "squash"},
157+
)
158+
if err != nil {
159+
log.Println("merge pull request: %w", err)
160+
continue
161+
}
162+
}
163+
}
164+
if autoMerge {
165+
for _, branch := range cleanupBranch {
166+
_, err := client.Git.DeleteRef(ctx, branch.Owner, branch.Repo, branch2Ref(branch.Branch))
167+
if err != nil {
168+
log.Println("delete ref faild: %w", err)
169+
}
170+
}
74171
}
75172
}
173+
}
76174

175+
func branch2Ref(branch string) string {
176+
return fmt.Sprintf("refs/heads/%s", branch)
77177
}
78178

79-
func sendFile(ctx context.Context, client *github.Client, localFile string, owner, repo, path, message string, syncBranches []string) error {
80-
if syncBranches == nil {
179+
func split(dest string) (owner, repo, path string, err error) {
180+
arr := strings.SplitN(dest, "/", 3)
181+
if len(arr) != 3 {
182+
return "", "", "", fmt.Errorf("wrong dist. example: owner/repo/file")
183+
}
184+
return arr[0], arr[1], arr[2], nil
185+
}
81186

82-
branches, _, err := client.Repositories.ListBranches(ctx, owner, repo, nil)
83-
if err != nil {
84-
return err
85-
}
86-
for i := range branches {
87-
syncBranches = append(syncBranches, *branches[i].Name)
187+
func sendFile(ctx context.Context, client *github.Client, localFile string, owner, repo, path, message string, branch string) (_changed bool, _err error) {
188+
fileContent, _, resp, err := client.Repositories.GetContents(
189+
ctx, owner, repo, path,
190+
&github.RepositoryContentGetOptions{Ref: branch},
191+
)
192+
if err != nil {
193+
if resp.StatusCode != http.StatusNotFound {
194+
return false, fmt.Errorf("get content: %w", err)
88195
}
89196
}
90-
for _, branche := range syncBranches {
91-
fileContent, _, resp, err := client.Repositories.GetContents(
92-
ctx, owner, repo, path,
93-
&github.RepositoryContentGetOptions{Ref: branche},
94-
)
95-
if err != nil {
96-
if resp.StatusCode != http.StatusNotFound {
97-
panic(err)
98-
}
99-
}
100-
var latestSha string
101-
if fileContent != nil {
102-
latestSha = fileContent.GetSHA()
103-
}
104-
content, err := os.ReadFile(localFile)
105-
if err != nil {
106-
panic(err)
107-
}
108-
sha := sha1.New()
109-
sha.Write([]byte(fmt.Sprintf("blob %d", len(content))))
110-
sha.Write([]byte{0})
111-
sha.Write(content)
112-
currentSha := hex.EncodeToString(sha.Sum(nil))
113-
if string(latestSha) == currentSha {
114-
log.Println("\t\tBranche", branche, " no change")
115-
continue
116-
}
117-
log.Println("\t\tBranche", branche, owner, repo, path, message)
118-
_, _, err = client.Repositories.UpdateFile(
119-
ctx, owner, repo, path,
120-
&github.RepositoryContentFileOptions{
121-
Message: &message,
122-
Content: content,
123-
SHA: &latestSha,
124-
Branch: &branche,
125-
},
126-
)
127-
if err != nil {
128-
return err
129-
}
197+
var latestSha string
198+
if fileContent != nil {
199+
latestSha = fileContent.GetSHA()
200+
}
201+
content, err := os.ReadFile(localFile)
202+
if err != nil {
203+
return false, fmt.Errorf("read file: %w", err)
204+
}
205+
sha := sha1.New()
206+
sha.Write([]byte(fmt.Sprintf("blob %d", len(content))))
207+
sha.Write([]byte{0})
208+
sha.Write(content)
209+
currentSha := hex.EncodeToString(sha.Sum(nil))
210+
if string(latestSha) == currentSha {
211+
return false, nil
130212
}
131-
return nil
213+
_, _, err = client.Repositories.UpdateFile(
214+
ctx, owner, repo, path,
215+
&github.RepositoryContentFileOptions{
216+
Message: &message,
217+
Content: content,
218+
SHA: &latestSha,
219+
Branch: &branch,
220+
},
221+
)
222+
return true, nil
132223
}

0 commit comments

Comments
 (0)