/
continuous-release-manager.go
168 lines (147 loc) · 5.59 KB
/
continuous-release-manager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package main
import (
"context"
"fmt"
"os"
"strings"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
func main() {
ctx := context.Background()
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
fmt.Println("Error: GITHUB_TOKEN environment variable not set.")
os.Exit(1)
}
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
repoOwner := ""
repoName := ""
releaseCommitHash := ""
releaseName := "continuous"
releaseTag := "continuous"
isGitHubActions := os.Getenv("GITHUB_ACTIONS") == "true"
isCirrusCI := os.Getenv("CIRRUS_CI") == "true"
if isGitHubActions {
repoOwner = os.Getenv("GITHUB_REPOSITORY_OWNER")
repoName = extractRepositoryName(os.Getenv("GITHUB_REPOSITORY"))
releaseCommitHash = os.Getenv("GITHUB_SHA")
} else if isCirrusCI {
repoOwner = os.Getenv("CIRRUS_REPO_OWNER")
repoName = os.Getenv("CIRRUS_REPO_NAME")
releaseCommitHash = os.Getenv("CIRRUS_CHANGE_IN_REPO")
} else {
fmt.Println("Error: Unsupported CI environment.")
os.Exit(1)
}
logInfo("Starting release management...")
logVerbose(fmt.Sprintf("Repository Owner: %s", repoOwner))
logVerbose(fmt.Sprintf("Repository Name: %s", repoName))
logVerbose(fmt.Sprintf("Release Tag: %s", releaseTag))
logVerbose(fmt.Sprintf("Release Commit Hash: %s", releaseCommitHash))
var createdRelease *github.RepositoryRelease
var releaseID int64 // Declare the variable to store the Release ID
// Check if the release with the name "continuous" already exists
logInfo("Checking for existing release...")
release, _, err := client.Repositories.GetReleaseByTag(ctx, repoOwner, repoName, releaseTag)
if err != nil {
// An error occurred while retrieving the release
if _, ok := err.(*github.ErrorResponse); ok && err.(*github.ErrorResponse).Response.StatusCode == 404 {
// The release does not exist yet, proceed to create it
logInfo("Release with the name 'continuous' does not exist. Creating a new release...")
newRelease := &github.RepositoryRelease{
TagName: &releaseTag,
TargetCommitish: &releaseCommitHash,
Name: &releaseName,
}
createdRelease, _, err = client.Repositories.CreateRelease(ctx, repoOwner, repoName, newRelease)
if err != nil {
// Check if the error is due to insufficient permissions
if strings.Contains(err.Error(), "403 Resource not accessible by integration") {
logError("Error creating release: Insufficient permissions. Please ensure that you have the necessary access rights.\n")
logError("To fix this, go to https://github.com/%s/%s/settings/actions, under \"Workflow permissions\" set \"Read and write permissions\".\n", repoOwner, repoName)
} else {
logError(fmt.Sprintf("Error creating release: %v", err))
}
} else {
logInfo("New release created successfully!")
logVerbose(fmt.Sprintf("Release ID: %v", *createdRelease.ID))
// Store the Release ID
releaseID = *createdRelease.ID
}
} else {
// Another error occurred while retrieving the release
logError(fmt.Sprintf("Error retrieving release: %v", err))
}
} else {
// The release exists, compare the commit hashes
logVerbose(fmt.Sprintf("Release found with ID: %d", *release.ID))
if *release.TargetCommitish != releaseCommitHash {
logVerbose("Existing release commit hash differs from the desired one. Deleting the existing release and tag...")
_, err := client.Repositories.DeleteRelease(ctx, repoOwner, repoName, *release.ID)
if err != nil {
logError(fmt.Sprintf("Error deleting release: %v", err))
} else {
logInfo("Existing release deleted successfully.")
_, err := client.Git.DeleteRef(ctx, repoOwner, repoName, fmt.Sprintf("tags/%s", releaseTag))
if err != nil {
logError(fmt.Sprintf("Error deleting tag: %v", err))
} else {
logInfo("Existing tag deleted successfully.")
}
// Proceed to create a new release to replace the deleted one
newRelease := &github.RepositoryRelease{
TagName: &releaseTag,
TargetCommitish: &releaseCommitHash,
Name: &releaseName,
}
createdRelease, _, err = client.Repositories.CreateRelease(ctx, repoOwner, repoName, newRelease)
if err != nil {
logError(fmt.Sprintf("Error creating release: %v", err))
} else {
logInfo("New release created successfully!")
logVerbose(fmt.Sprintf("Release ID: %v", *createdRelease.ID))
// Store the Release ID
releaseID = *createdRelease.ID
}
}
} else {
logInfo("Release with the name 'continuous' already exists and has the desired commit hash.")
// Store the Release ID
releaseID = *release.ID
}
}
targetRelease := release
if createdRelease != nil {
targetRelease = createdRelease
}
// At the end, after all other operations are done publish it to make it non-draft
logVerbose("Publishing release...")
targetRelease.Draft = github.Bool(false) // Set the Draft field to false
_, _, err = client.Repositories.EditRelease(ctx, repoOwner, repoName, releaseID, targetRelease)
if err != nil {
logError(fmt.Sprintf("Error publishing release: %v", err))
} else {
logInfo("Release published successfully.")
}
// Print the Release ID at the end
fmt.Println(releaseID)
}
func extractRepositoryName(fullName string) string {
parts := strings.Split(fullName, "/")
if len(parts) > 1 {
return parts[1]
}
return fullName
}
func logInfo(msg string) {
fmt.Fprintf(os.Stderr, "[INFO] %s\n", msg)
}
func logVerbose(msg string) {
fmt.Fprintf(os.Stderr, "[VERBOSE] %s\n", msg)
}
func logError(format string, a ...interface{}) {
fmt.Fprintf(os.Stderr, "[ERROR] "+format+"\n", a...)
}