Skip to content

Commit 119fb6d

Browse files
committed
Add rudimentary support for github repos
Signed-off-by: Richard Nixon <[email protected]>
1 parent cd739e8 commit 119fb6d

File tree

4 files changed

+316
-15
lines changed

4 files changed

+316
-15
lines changed

main.go

+90-14
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,103 @@ import (
55
"os"
66
"os/exec"
77
"path/filepath"
8+
"strings"
89
)
910

10-
func main() {
11-
// Check we have env vars set
12-
if os.Getenv("BBUSER") == "" || os.Getenv("BBAPPPASS") == "" {
13-
fmt.Println("Please set credential in environment vars BBUSER and BBAPPPASS")
14-
fmt.Println(" export BBUSER=ebeneezer")
15-
fmt.Println(" export BBAPPPASS=ijfewIIejdiiowIOEIJEDiojoewfiJIOEF")
16-
return
11+
func cloneOrSyncGitRepo(repoDir, cloneUrl, mainBranch string) {
12+
fmt.Printf(" Processing git repo %s from %s\n", repoDir, cloneUrl)
13+
if _, err := os.Stat(repoDir); err != nil {
14+
fmt.Println(" Cloning...")
15+
out, err := exec.Command("git", "clone", cloneUrl, repoDir).CombinedOutput()
16+
if err != nil {
17+
fmt.Println("Error during clone: " + string(out))
18+
}
19+
}
20+
out, err := exec.Command("git", "-C", repoDir, "reset", "--hard").CombinedOutput()
21+
if err != nil {
22+
fmt.Println("Error during hard reset: " + string(out))
23+
}
24+
out, err = exec.Command("git", "-C", repoDir, "fetch", "--all", "--prune").CombinedOutput()
25+
if err != nil {
26+
fmt.Println("Error during fetch all: " + string(out))
27+
}
28+
out, err = exec.Command("git", "-C", repoDir, "checkout", mainBranch).CombinedOutput()
29+
if err != nil {
30+
fmt.Println("Error during checkout: " + string(out))
1731
}
32+
out, err = exec.Command("git", "-C", repoDir, "pull").CombinedOutput()
33+
if err != nil {
34+
fmt.Println("Error during pull: " + string(out))
35+
}
36+
}
37+
38+
func processGitHubRepo(repo GitHubRepository) {
39+
homeDir, err := os.UserHomeDir()
40+
checkErr(err)
41+
gitHubOrgPath := filepath.Join(homeDir, "repos", "github", repo.Owner.Login)
42+
gitHubRepoPath := filepath.Join(homeDir, "repos", "github", repo.Owner.Login, repo.Name)
43+
err = os.MkdirAll(gitHubOrgPath, 0750)
44+
checkErr(err)
45+
cloneOrSyncGitRepo(gitHubRepoPath, repo.SSHUrl, repo.DefaultBranch)
46+
}
1847

19-
// Iterate the workspaces we have access to
20-
workspaces := FetchBitBucketOrganisations(os.Getenv("BBUSER"), os.Getenv("BBAPPPASS"))
21-
for _, workspace := range workspaces {
22-
processWorkspace(workspace)
48+
func processGitHubOrg(token, org string) {
49+
fmt.Printf("Processing repos in GitHub Org %v\n", org)
50+
repos := FetchGitHubRepos(token, org)
51+
for _, repo := range repos {
52+
processGitHubRepo(repo)
2353
}
2454
}
2555

56+
func processGitHubOrgs() {
57+
ghtoken := os.Getenv("GHTOKEN")
58+
if ghtoken == "" {
59+
fmt.Println("GHTOKEN is not set, skipping GitHub repositories")
60+
} else {
61+
fmt.Println("GHTOKEN is set, processing GitHub repositories")
62+
var ghorgs []string
63+
ghorg := os.Getenv("GHORG")
64+
if ghorg != "" {
65+
ghorgs = strings.Split(ghorg, ",")
66+
} else {
67+
fmt.Printf("GHORG is not set, processing all GitHub orgs\n")
68+
ghorgs = FetchGitHubOrganisations(ghtoken)
69+
}
70+
for _, ghorg := range ghorgs {
71+
processGitHubOrg(ghtoken, ghorg)
72+
}
73+
}
74+
}
75+
76+
func processBitBucketOrgs() {
77+
bbuser := os.Getenv("BBUSER")
78+
bbapppass := os.Getenv("BBAPPPASS")
79+
bborg := os.Getenv("BBORG")
80+
81+
if bbuser == "" || bbapppass == "" {
82+
fmt.Println("BBUSER and/or BBAPPPASS not set, skipping BitBucket repositories")
83+
} else {
84+
var bborgs []string
85+
if bborg == "" {
86+
fmt.Println("BBORG is not set, processing all BitBucket Organisations")
87+
bborgs = FetchBitBucketOrganisations(bbuser, bbapppass)
88+
} else {
89+
fmt.Println("BBORG is set, processing selected BitBucket repositories")
90+
bborgs = strings.Split(bborg, ",")
91+
}
92+
for _, bborg := range bborgs {
93+
processWorkspace(bborg)
94+
}
95+
}
96+
}
97+
98+
func main() {
99+
processGitHubOrgs()
100+
processBitBucketOrgs()
101+
}
102+
26103
func processWorkspace(workspace string) {
27-
fmt.Printf("Processing workspace %v\n", workspace)
104+
fmt.Printf("Processing BitBucket workspace %v\n", workspace)
28105
repos := FetchBitbucketRepos(os.Getenv("BBUSER"), os.Getenv("BBAPPPASS"), workspace)
29106

30107
for _, repo := range repos {
@@ -34,12 +111,11 @@ func processWorkspace(workspace string) {
34111
}
35112

36113
func processRepo(workspace, project, repo, mainBranch string) {
37-
//fmt.Printf(" Repo: %v/%v/%v\n", workspace, project, repo)
38114
home, err := os.UserHomeDir()
39115
checkErr(err)
40116

41117
projectDir := filepath.Join(home, "repos", workspace, project)
42-
repoDir := filepath.Join(home, "repos", workspace, project, repo)
118+
repoDir := filepath.Join(home, "repos", "bitbucket", workspace, project, repo)
43119

44120
// Make the project directory
45121
err = os.MkdirAll(projectDir, 0750)

types_gh_organisations.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"io"
6+
"net/http"
7+
)
8+
9+
func FetchGitHubOrganisations(apiToken string) []string {
10+
var organisations GitHubOrganisationsResponse
11+
url := "https://api.github.com/user/orgs?per_page=100"
12+
organisations = FetchGitHubPage(apiToken, url)
13+
organisationNames := make([]string, len(organisations))
14+
for i, organisation := range organisations {
15+
organisationNames[i] = organisation.Login
16+
}
17+
return organisationNames
18+
}
19+
20+
func FetchGitHubPage(apiToken, url string) GitHubOrganisationsResponse {
21+
var Organisations GitHubOrganisationsResponse
22+
client := http.Client{}
23+
req, err := http.NewRequest("GET", url, nil)
24+
checkErr(err)
25+
req.Header.Set("Authorization", "bearer "+apiToken)
26+
req.Header.Set("Accept", "application/vnd.github+json")
27+
resp, err := client.Do(req)
28+
checkErr(err)
29+
defer resp.Body.Close()
30+
bodyText, err := io.ReadAll(resp.Body)
31+
checkErr(err)
32+
json.Unmarshal(bodyText, &Organisations)
33+
return Organisations
34+
}
35+
36+
type GitHubOrganisationsResponse []GitHubOrganisation
37+
38+
type GitHubOrganisation struct {
39+
Login string `json:"login"`
40+
Id int `json:"id"`
41+
NodeId string `json:"node_id"`
42+
Url string `json:"url"`
43+
ReposUrl string `json:"repos_url"`
44+
EventsUrl string `json:"events_url"`
45+
HooksUrl string `json:"hooks_url"`
46+
IssuesUrl string `json:"issues_url"`
47+
MembersUrl string `json:"members_url"`
48+
PublicMembersUrl string `json:"public_members_url"`
49+
AvatarUrl string `json:"avatar_url"`
50+
Description string `json:"description"`
51+
}

types_gh_repos.go

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"time"
9+
)
10+
11+
func FetchGitHubRepos(apiToken, organisation string) GitHubRepositories {
12+
var repositories GitHubRepositories
13+
url := fmt.Sprintf("https://api.github.com/orgs/%v/repos?per_page=100", organisation)
14+
repoPage := FetchGitHubReposPage(apiToken, url)
15+
repositories = repoPage
16+
return repositories
17+
}
18+
19+
func FetchGitHubReposPage(apiToken, url string) GitHubRepositories {
20+
var Response GitHubRepositories
21+
client := http.Client{}
22+
req, err := http.NewRequest("GET", url, nil)
23+
checkErr(err)
24+
req.Header.Set("Authorization", "bearer "+apiToken)
25+
req.Header.Set("Accept", "application/json")
26+
resp, err := client.Do(req)
27+
checkErr(err)
28+
defer resp.Body.Close()
29+
bodyText, err := io.ReadAll(resp.Body)
30+
checkErr(err)
31+
err = json.Unmarshal(bodyText, &Response)
32+
checkErr(err)
33+
return Response
34+
}
35+
36+
type GitHubRepositories []GitHubRepository
37+
38+
type GitHubRepository struct {
39+
Id int64 `json:"id"`
40+
NodeID string `json:"node_id"`
41+
Name string `json:"name"`
42+
FullName string `json:"full_name"`
43+
Private bool `json:"private"`
44+
Owner GitHubRepositoryOwner `json:"owner"`
45+
HtmlUrl string `json:"html_url"`
46+
Description string `json:"description"`
47+
Fork bool `json:"fork"`
48+
Url string `json:"url"`
49+
ForksUrl string `json:"forks_url"`
50+
KeysUrl string `json:"keys_url"`
51+
CollaboratorsUrl string `json:"collaborators_url"`
52+
TeamsUrl string `json:"teams_url"`
53+
HooksUrl string `json:"hooks_url"`
54+
IssueEventsUrl string `json:"issue_events_url"`
55+
EventsUrl string `json:"events_url"`
56+
AssigneesUrl string `json:"assignees_url"`
57+
BranchesUrl string `json:"branches_url"`
58+
TagsUrl string `json:"tags_url"`
59+
BlobsUrl string `json:"blobs_url"`
60+
GitTagsUrl string `json:"git_tags_url"`
61+
GitRefsUrl string `json:"git_refs_url"`
62+
TreesUrl string `json:"trees_url"`
63+
StatusesUrl string `json:"statuses_url"`
64+
LanguagesUrl string `json:"languages_url"`
65+
StargazersUrl string `json:"stargazers_url"`
66+
ContributorsUrl string `json:"contributors_url"`
67+
SubscribersUrl string `json:"subscribers_url"`
68+
SubscriptionUrl string `json:"subscription_url"`
69+
CommitsUrl string `json:"commits_url"`
70+
GitCommitsUrl string `json:"git_commits_url"`
71+
CommentsUrl string `json:"comments_url"`
72+
IssueCommentUrl string `json:"issue_comment_url"`
73+
ContentsUrl string `json:"contents_url"`
74+
CompareUrl string `json:"compare_url"`
75+
MergesUrl string `json:"merges_url"`
76+
ArchiveUrl string `json:"archive_url"`
77+
DownloadsUrl string `json:"downloads_url"`
78+
IssuesUrl string `json:"issues_url"`
79+
PullsUrl string `json:"pulls_url"`
80+
MilestonesUrl string `json:"milestones_url"`
81+
NotificationsUrl string `json:"notifications_url"`
82+
LabelsUrl string `json:"labels_url"`
83+
ReleasesUrl string `json:"releases_url"`
84+
DeploymentsUrl string `json:"deployments_url"`
85+
CreatedAt time.Time `json:"created_at"`
86+
UpdatedAt time.Time `json:"updated_at"`
87+
PushedAt time.Time `json:"pushed_at"`
88+
GitUrl string `json:"git_url"`
89+
SSHUrl string `json:"ssh_url"`
90+
CloneUrl string `json:"clone_url"`
91+
SvnUrl string `json:"svn_url"`
92+
HomePage string `json:"homepage"`
93+
Size int64 `json:"size"`
94+
StargazersCount int64 `json:"stargazers_count"`
95+
WatchersCount int64 `json:"watchers_count"`
96+
Language string `json:"language"`
97+
HasIssues bool `json:"has_issues"`
98+
HasProjects bool `json:"has_projects"`
99+
HasDownloads bool `json:"has_downloads"`
100+
HasWiki bool `json:"has_wiki"`
101+
HasPages bool `json:"has_pages"`
102+
HasDiscussions bool `json:"has_discussions"`
103+
ForksCount int64 `json:"forks_count"`
104+
MirrorUrl string `json:"mirror_url"`
105+
Archived bool `json:"archived"`
106+
Disabled bool `json:"disabled"`
107+
OpenIssuesCount int64 `json:"open_issues_count"`
108+
License GitHubRepositoryLicense `json:"license"`
109+
AllowForking bool `json:"allow_forking"`
110+
IsTemplate bool `json:"is_template"`
111+
WebCommitSignoffRequired bool `json:"web_commit_signoff_required"`
112+
Topics []string `json:"topics"`
113+
Visibility string `json:"visibility"`
114+
Forks int64 `json:"forks"`
115+
OpenIssues int64 `json:"open_issues"`
116+
Watchers int64 `json:"watchers"`
117+
DefaultBranch string `json:"default_branch"`
118+
Permissions GitHubRepoPermissions `json:"permissions"`
119+
}
120+
121+
type GitHubRepositoryOwner struct {
122+
Login string `json:"login"`
123+
Id int64 `json:"id"`
124+
Name string `json:"name"`
125+
Email string `json:"email"`
126+
NodeID string `json:"node_id"`
127+
AvatarUrl string `json:"avatar_url"`
128+
GravatarId string `json:"gravatar_id"`
129+
Url string `json:"url"`
130+
HtmlUrl string `json:"html_url"`
131+
FollowersUrl string `json:"followers_url"`
132+
FollowingUrl string `json:"following_url"`
133+
GistsUrl string `json:"gists_url"`
134+
StarredUrl string `json:"starred_url"`
135+
SubscriptionsUrl string `json:"subscriptions_url"`
136+
OrganizationsUrl string `json:"organizations_url"`
137+
ReposUrl string `json:"repos_url"`
138+
EventsUrl string `json:"events_url"`
139+
ReceivedEventsUrl string `json:"received_events_url"`
140+
Type string `json:"type"`
141+
UserViewType string `json:"user_view_type"`
142+
SiteAdmin bool `json:"site_admin"`
143+
}
144+
145+
type GitHubRepositoryLicense struct {
146+
Key string `json:"key"`
147+
Name string `json:"name"`
148+
SpdxId string `json:"spdx_id"`
149+
Url string `json:"url"`
150+
NodeId string `json:"node_id"`
151+
}
152+
153+
type GitHubRepoPermissions struct {
154+
Admin bool `json:"admin"`
155+
Maintain bool `json:"maintain"`
156+
Push bool `json:"push"`
157+
Triage bool `json:"triage"`
158+
Pull bool `json:"pull"`
159+
}

types_test.go

+16-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,22 @@ import (
55
"testing"
66
)
77

8-
func TestFetchOrganisations(t *testing.T) {
8+
func TestFetchGitHubOrganisations(t *testing.T) {
9+
organisations := FetchGitHubOrganisations(os.Getenv("GHTOKEN"))
10+
if len(organisations) < 1 {
11+
t.Fatalf(`Length of workspaces is %v`, len(organisations))
12+
}
13+
}
14+
15+
func TestFetchGitHubRepos(t *testing.T) {
16+
organisations := FetchGitHubOrganisations(os.Getenv("GHTOKEN"))
17+
repos := FetchGitHubRepos(os.Getenv("GHTOKEN"), organisations[0])
18+
if len(repos) < 1 {
19+
t.Fatalf(`Length of repositories is %v`, len(organisations))
20+
}
21+
}
22+
23+
func TestFetchBitBucketOrganisations(t *testing.T) {
924
organisations := FetchBitBucketOrganisations(os.Getenv("BBUSER"), os.Getenv("BBAPPPASS"))
1025
if len(organisations) < 1 {
1126
t.Fatalf(`Length of workspaces is %v`, len(organisations))

0 commit comments

Comments
 (0)