From 532413e79bc43de4f2454ad0a7877e944b32c961 Mon Sep 17 00:00:00 2001 From: cjhawkins <39426000+cjhawkins@users.noreply.github.com> Date: Mon, 1 Jun 2020 16:02:34 -0700 Subject: [PATCH] ZERO126 adding repo creation and initial commit (#141) * ZERO126 adding repo creation and initial commit * ZERO126 moved files, minor cleanup --- go.mod | 12 +- go.sum | 16 +-- internal/vcs/create-git-repos.go | 192 +++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 internal/vcs/create-git-repos.go diff --git a/go.mod b/go.mod index 71e3bbcf2..f2e61d127 100644 --- a/go.mod +++ b/go.mod @@ -5,18 +5,28 @@ go 1.12 require ( github.com/766b/go-outliner v0.0.0-20180511142203-fc6edecdadd7 // indirect github.com/aws/aws-sdk-go v1.25.33 - github.com/commitdev/commit0 v0.0.0-20200522203431-5176cd09c654 + github.com/chzyer/logex v1.1.10 // indirect + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect github.com/coreos/go-semver v0.2.0 github.com/google/uuid v1.1.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/mux v1.7.3 github.com/hashicorp/go-getter v1.4.0 + github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect + github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/k0kubun/pp v3.0.1+incompatible github.com/kyokomi/emoji v2.1.0+incompatible github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 + github.com/lunixbochs/vtclean v1.0.0 // indirect + github.com/machinebox/graphql v0.2.2 github.com/manifoldco/promptui v0.3.0 + github.com/matryer/is v1.3.0 // indirect + github.com/mattn/go-colorable v0.1.2 // indirect github.com/spf13/cobra v0.0.6 github.com/stretchr/testify v1.5.1 // indirect golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect + golang.org/x/sys v0.0.0-20191010194322-b09406accb47 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v2 v2.2.5 ) diff --git a/go.sum b/go.sum index 62192744a..f48e8332e 100644 --- a/go.sum +++ b/go.sum @@ -32,16 +32,12 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/commitdev/commit0 v0.0.0-20200522203431-5176cd09c654 h1:tAJNsBPx6E9YcuMizzh5v52/z+fV15YxZiODicCU0Qs= -github.com/commitdev/commit0 v0.0.0-20200522203431-5176cd09c654/go.mod h1:6gD/1wuBnjZ9aVnf3Tp0zdmAVO/2w9lRe6W/gnR/emc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -131,9 +127,13 @@ github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 h1:im9kkmH0WWwx github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo= +github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/manifoldco/promptui v0.3.0 h1:vJiVJREqDfn9ZhqTG1Dz5zP9RPWlAzWQkwRYLGyUHx4= github.com/manifoldco/promptui v0.3.0/go.mod h1:zoCNXiJnyM03LlBgTsWv8mq28s7aTC71UgKasqRJHww= +github.com/matryer/is v1.3.0 h1:9qiso3jaJrOe6qBRJRBt2Ldht05qDiFP9le0JOIhRSI= +github.com/matryer/is v1.3.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -151,6 +151,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -164,7 +165,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -172,23 +172,19 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok= github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -201,7 +197,6 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -243,7 +238,6 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/internal/vcs/create-git-repos.go b/internal/vcs/create-git-repos.go new file mode 100644 index 000000000..8cb31e60b --- /dev/null +++ b/internal/vcs/create-git-repos.go @@ -0,0 +1,192 @@ +package vcs + +import ( + "context" + "fmt" + "github.com/machinebox/graphql" + "os/exec" +) + +// this is being developed with the following assumptions: +// 1. create.go will handle parsing the repo names and github credentials and pass them into initializeRepostiories(). +// 2. if organizationName is set, create an org owned repo. if not, create a personal repo. + +// takes a list of subdirectories containing modules to create a repository and do initial commit for +func InitializeRepositories(moduleDirs []string, remoteRepository string, organizationName string, githubApiKey string) { + + for _, moduleDir := range moduleDirs { + // if organizationName is not set, create a personal github repo, else create an org owned repo. + if organizationName == "" { + if err := createPersonalRepository(moduleDir, githubApiKey); err != nil { + fmt.Printf("error creating repository: %s\n", err.Error()) + continue + } + } else { + if err := createOrganizationOwnedRepository(moduleDir, githubApiKey, organizationName); err != nil { + fmt.Printf("error creating repository: %s\n", err.Error()) + continue + } + } + + if err := doInitialCommit(moduleDir, remoteRepository); err != nil { + fmt.Printf("error initializing repository: %s\n", err.Error()) + } + } + +} + +const createPersonalRepositoryMutation = `mutation ($repoName: String!, $repoDescription: String!) { + createRepository( + input: { + name:$repoName, + visibility: PRIVATE, + description: $repoDescription + }) + { + clientMutationId + } + }` + +func createPersonalRepository(moduleDir string, githubApiKey string) error { + + fmt.Printf("Creating repository for module: %s\n", moduleDir) + + // create client and mutation + client := graphql.NewClient("https://api.github.com/graphql") + req := graphql.NewRequest(createPersonalRepositoryMutation) + req.Var("repoName", moduleDir) + req.Var("repoDescription", fmt.Sprintf("Repository for %s", moduleDir)) + + // add auth token + var bearer = fmt.Sprintf("Bearer %s", githubApiKey) + req.Header.Add("Authorization", bearer) + + ctx := context.Background() + if err := client.Run(ctx, req, nil); err != nil { + return err + } + + fmt.Printf("Repository successfully created for module: %s\n", moduleDir) + + return nil +} + +const createOrganizationRepositoryMutation = `mutation ($repoName: String!, $repoDescription: String!, $ownerId: String!) { + createRepository( + input: { + name:$repoName, + visibility: PRIVATE, + description: $repoDescription + ownerId: $ownerId + }) + { + clientMutationId + } + }` + +const getOrganizationQuery = `query ($organizationName: String!) { + organization(login: $organizationName) { + id + } + }` + +type organizationQueryResponse struct { + Organization struct { + Id string + } +} + +func createOrganizationOwnedRepository(moduleDir string, githubApiKey string, organizationName string) error { + + fmt.Printf("Creating org owned repository for module: %s\n", moduleDir) + + // create client and organization query + var bearer = fmt.Sprintf("Bearer %s", githubApiKey) + client := graphql.NewClient("https://api.github.com/graphql") + orgIdReq := graphql.NewRequest(getOrganizationQuery) + orgIdReq.Var("organizationName", organizationName) + orgIdReq.Header.Add("Authorization", bearer) + + var orgIdResp organizationQueryResponse + ctx := context.Background() + if err := client.Run(ctx, orgIdReq, &orgIdResp); err != nil { + return err + } + organizationId := orgIdResp.Organization.Id + + // create mutation and run it + req := graphql.NewRequest(createOrganizationRepositoryMutation) + req.Var("repoName", moduleDir) + req.Var("repoDescription", fmt.Sprintf("Repository for %s", moduleDir)) + req.Var("ownerId", organizationId) + req.Header.Add("Authorization", bearer) + if err := client.Run(ctx, req, nil); err != nil { + return err + } + + fmt.Printf("Repository successfully created for module: %s\n", moduleDir) + + return nil +} + +type InitialCommands struct { + description string + command string + args []string +} + +// do initial commit to a repository +func doInitialCommit(moduleDir string, remoteRepository string) error { + fmt.Printf("Initializing repository for module: %s\n", moduleDir) + + remoteOrigin := fmt.Sprintf("%s/%s.git", remoteRepository, moduleDir) + commands := []InitialCommands{ + { + description: "git init", + command: "git", + args: []string{"init"}, + }, + { + description: "git add .", + command: "git", + args: []string{"add", "."}, + }, + { + description: "git commit -m \"initial commit by zero\"", + command: "git", + args: []string{"commit", "-m", "initial commit by zero"}, + }, + { + description: fmt.Sprintf("git remote add origin %s", remoteOrigin), + command: "git", + args: []string{"remote", "add", "origin", remoteOrigin}, + }, + { + description: "git push -u origin master", + command: "git", + args: []string{"push", "-u", "origin", "master"}, + }, + } + + for _, command := range commands { + fmt.Printf(">> %s\n", command.description) + + cmd := exec.Command(command.command, command.args...) + cmd.Dir = "./" + moduleDir + out, err := cmd.CombinedOutput() + if err != nil { + fmt.Printf("ERROR: failed to run %s: %s\n", command.description, err.Error()) + // this is a partial failure. some commands may have exec'ed successfully. + break + } else { + response := string(out) + if len(response) > 0 { + fmt.Println(response) + } + } + } + + fmt.Printf("Repository successfully initialized for module: %s\n", moduleDir) + + return nil +}