Merge pull request #74 from spotify/blam/run-cookie-cutter
Actually run the Cookie Cutter in the Folder
This commit is contained in:
+11
-1
@@ -1,3 +1,4 @@
|
||||
### Builder Stage
|
||||
FROM golang:1.13 AS build
|
||||
ARG service
|
||||
|
||||
@@ -13,7 +14,9 @@ COPY $service/ /build/$service/
|
||||
|
||||
RUN go build .
|
||||
|
||||
FROM debian:buster
|
||||
|
||||
### Running Container Stage
|
||||
FROM debian:buster AS default
|
||||
ARG service
|
||||
|
||||
RUN apt-get update && apt-get install -y ca-certificates
|
||||
@@ -23,3 +26,10 @@ WORKDIR /app/
|
||||
COPY --from=build /build/$service/$service /app/service
|
||||
|
||||
CMD ["./service"]
|
||||
|
||||
|
||||
### Scaffolder Stage
|
||||
### needs extra cookiecutter
|
||||
FROM default AS scaffolder
|
||||
RUN apt-get update && apt-get install -y python-pip
|
||||
RUN pip install cookiecutter==1.7.0 --index-url https://pypi.python.org/simple
|
||||
|
||||
@@ -3,35 +3,38 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/golang/protobuf/jsonpb"
|
||||
identity "github.com/spotify/backstage/backend/proto/identity/v1"
|
||||
pb "github.com/spotify/backstage/backend/proto/scaffolder/v1"
|
||||
"github.com/spotify/backstage/scaffolder/fs"
|
||||
"github.com/spotify/backstage/scaffolder/remote"
|
||||
"github.com/spotify/backstage/scaffolder/lib"
|
||||
"github.com/spotify/backstage/scaffolder/repository"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"log"
|
||||
)
|
||||
|
||||
// Server is the inventory Grpc server
|
||||
type Server struct {
|
||||
repository *repository.Repository
|
||||
github *remote.Github
|
||||
github *lib.Github
|
||||
fs *fs.Filesystem
|
||||
cookie *lib.Cutter
|
||||
git *lib.Git
|
||||
}
|
||||
|
||||
// NewServer creates a new server for with all the things
|
||||
func NewServer() *Server {
|
||||
return &Server{
|
||||
github: remote.NewGithubClient(),
|
||||
github: lib.NewGithubClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Create scaffolds the repo in github and then will create push to the repository
|
||||
func (s *Server) Create(ctx context.Context, req *pb.CreateRequest) (*pb.CreateReply, error) {
|
||||
// first create the repository with github
|
||||
fmt.Sprintf("Creating repository for Component %s", req.ComponentId)
|
||||
repo := remote.Repository{
|
||||
log.Printf("Creating repository for Component %s", req.ComponentId)
|
||||
repo := lib.Repository{
|
||||
Name: req.ComponentId,
|
||||
Org: req.Org,
|
||||
Private: req.Private,
|
||||
@@ -41,16 +44,59 @@ func (s *Server) Create(ctx context.Context, req *pb.CreateRequest) (*pb.CreateR
|
||||
}
|
||||
|
||||
// move the template into a temporary directory
|
||||
tempFolder, _ := s.fs.PrepareTemplate(fs.Template{req.TemplateId})
|
||||
tempFolder, err := s.fs.PrepareTemplate(
|
||||
fs.Template{
|
||||
ID: req.TemplateId,
|
||||
},
|
||||
)
|
||||
|
||||
fmt.Sprintf("Created temporary folder %s", tempFolder)
|
||||
// use git bindings to add the remote with access token and push to the directory
|
||||
return nil, nil
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not prepare the template")
|
||||
}
|
||||
|
||||
// get the optional metadatafields from the json
|
||||
marshaler := &jsonpb.Marshaler{}
|
||||
cutterMetadata, err := marshaler.MarshalToString(req.Metadata)
|
||||
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not marshal the cookiecutter metadata")
|
||||
}
|
||||
|
||||
cookieTemplate := lib.CookieCutterTemplate{
|
||||
Path: tempFolder,
|
||||
ComponentID: req.ComponentId,
|
||||
Metadata: cutterMetadata,
|
||||
}
|
||||
|
||||
// create the cookicutter json
|
||||
if err := s.cookie.WriteMetadata(cookieTemplate); err != nil {
|
||||
return nil, status.Error(codes.Internal, "Could not write cookie metadata")
|
||||
}
|
||||
|
||||
// run the cookiecutter on the folder
|
||||
if err := s.cookie.Run(cookieTemplate); err != nil {
|
||||
return nil, status.Error(codes.Internal, "Failed to run the cookie cutter")
|
||||
}
|
||||
|
||||
// push to github
|
||||
pushOptions := lib.PushRepositoryOptions{
|
||||
TempFolder: tempFolder,
|
||||
ComponentID: req.ComponentId,
|
||||
Org: req.Org,
|
||||
}
|
||||
|
||||
if err := s.git.Push(pushOptions); err != nil {
|
||||
return nil, status.Error(codes.Internal, "Failed to push the repository to Github")
|
||||
}
|
||||
|
||||
return &pb.CreateReply{
|
||||
ComponentId: req.ComponentId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ListTemplates returns the local templatess
|
||||
func (s *Server) ListTemplates(ctx context.Context, req *pb.Empty) (*pb.ListTemplatesReply, error) {
|
||||
// todo (blam): yes we currently read the disk on every load. but it's fine for now 🤷♂️
|
||||
// TODO(blam): yes we currently read the disk on every load. but it's fine for now 🤷♂️
|
||||
definitions, err := s.repository.Load()
|
||||
var templates []*pb.Template
|
||||
|
||||
@@ -59,6 +105,7 @@ func (s *Server) ListTemplates(ctx context.Context, req *pb.Empty) (*pb.ListTemp
|
||||
Id: definition.ID,
|
||||
Name: definition.Name,
|
||||
Description: definition.Description,
|
||||
|
||||
// need to actually call the idenity service here to get the
|
||||
// actual user and propgate back when needed.
|
||||
User: &identity.User{
|
||||
|
||||
@@ -9,7 +9,8 @@ import (
|
||||
)
|
||||
|
||||
// Filesystem Repository
|
||||
type Filesystem struct{}
|
||||
type Filesystem struct {
|
||||
}
|
||||
|
||||
func file(src, dst string) error {
|
||||
var err error
|
||||
@@ -78,7 +79,6 @@ type Template struct {
|
||||
// and return the temp location
|
||||
func (f *Filesystem) PrepareTemplate(template Template) (string, error) {
|
||||
tempDirectory, _ := ioutil.TempDir(os.TempDir(), template.ID)
|
||||
fmt.Println(tempDirectory)
|
||||
if err := dir("./templates/"+template.ID, tempDirectory); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -14,4 +14,5 @@ require (
|
||||
github.com/spotify/backstage/proto v0.0.0-00010101000000-000000000000
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
|
||||
google.golang.org/grpc v1.27.0
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1
|
||||
)
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@@ -14,14 +24,41 @@ github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts=
|
||||
github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
|
||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
@@ -31,6 +68,10 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -39,12 +80,20 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
@@ -54,5 +103,13 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
|
||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Cutter is the wrapper around cookiecutter
|
||||
type Cutter struct {
|
||||
}
|
||||
|
||||
// CookieCutterTemplate holds the template ID and metadata for copying
|
||||
type CookieCutterTemplate struct {
|
||||
Path string
|
||||
Metadata string
|
||||
ComponentID string
|
||||
}
|
||||
|
||||
// WriteMetadata runs cookiecutter in the folder provided
|
||||
func (c *Cutter) WriteMetadata(template CookieCutterTemplate) error {
|
||||
var temporaryCookieCutter map[string]interface{}
|
||||
err := json.Unmarshal([]byte(template.Metadata), &temporaryCookieCutter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
temporaryCookieCutter["component_id"] = template.ComponentID
|
||||
finalMetadata, _ := json.Marshal(temporaryCookieCutter)
|
||||
|
||||
file, err := os.Create(fmt.Sprintf("%s/cookiecutter.json", template.Path))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
_, err = file.Write(finalMetadata)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Run will run the cookie cutter
|
||||
func (c *Cutter) Run(template CookieCutterTemplate) error {
|
||||
// TODO(blam): Probably need to wrap this in a timeout or something to avoid waiting to long
|
||||
log.Printf("Running cookiecutter on %s", template.Path)
|
||||
log.Printf("With metadata %s", template.Metadata)
|
||||
|
||||
cmd := exec.Command("cookiecutter", "--no-input", "-v", template.Path)
|
||||
cmd.Dir = template.Path
|
||||
output, err := cmd.Output()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Cookie cutter failed with output: %s", output)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/config"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/object"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Git is the wrapper around Git
|
||||
type Git struct{}
|
||||
|
||||
// PushRepositoryOptions holds the arguments for the push
|
||||
type PushRepositoryOptions struct {
|
||||
TempFolder string
|
||||
ComponentID string
|
||||
Org string
|
||||
}
|
||||
|
||||
// Push will push the repository to github
|
||||
func (g *Git) Push(options PushRepositoryOptions) error {
|
||||
// use git bindings to add the remote with access token and push to the directory
|
||||
repo, err := git.PlainInit(options.TempFolder, false)
|
||||
if err != nil {
|
||||
log.Printf("Failed to init the git repository")
|
||||
return err
|
||||
}
|
||||
|
||||
worktree, err := repo.Worktree()
|
||||
if err != nil {
|
||||
log.Printf("Failed to create the worktree")
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = worktree.Add(".")
|
||||
if err != nil {
|
||||
log.Printf("Failed to add the files to the worktre")
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = worktree.Commit("Initial Commit", &git.CommitOptions{
|
||||
Author: &object.Signature{
|
||||
Name: "Backstage",
|
||||
Email: "backstage@spotfy.com",
|
||||
When: time.Now(),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to create the initial commit")
|
||||
return err
|
||||
}
|
||||
|
||||
var org string = os.Getenv("BOSS_GH_USERNAME")
|
||||
if options.Org != "" {
|
||||
org = options.Org
|
||||
}
|
||||
|
||||
remote := fmt.Sprintf(
|
||||
"https://%s:%s@github.com/%s/%s.git",
|
||||
os.Getenv("BOSS_GH_USERNAME"),
|
||||
os.Getenv("BOSS_GH_ACCESS_TOKEN"),
|
||||
org,
|
||||
options.ComponentID,
|
||||
)
|
||||
|
||||
_, err = repo.CreateRemote(&config.RemoteConfig{
|
||||
Name: "github",
|
||||
URLs: []string{remote},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failed to create the remote")
|
||||
return err
|
||||
}
|
||||
|
||||
err = repo.Push(&git.PushOptions{
|
||||
RemoteName: "github",
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Failled to push the repository")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package remote
|
||||
package lib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
gh "github.com/google/go-github/v29/github"
|
||||
"golang.org/x/oauth2"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
@@ -19,8 +19,7 @@ func NewGithubClient() *Github {
|
||||
accessToken := os.Getenv("BOSS_GH_ACCESS_TOKEN")
|
||||
|
||||
if accessToken == "" {
|
||||
fmt.Println("No BOSS_GH_ACCESS_TOKEN set. Cannot continue")
|
||||
os.Exit(1)
|
||||
log.Fatal("No BOSS_GH_ACCESS_TOKEN set. Cannot continue")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"component_id": "",
|
||||
"owner": "",
|
||||
"description": "I promise to update this description // {{cookiecutter.owner}}",
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"schema": [{
|
||||
"id": "owner",
|
||||
"title": "owner",
|
||||
"type": "text",
|
||||
"description": "The owner name used to identify the owner of this component",
|
||||
"validators": [
|
||||
{ "type": "required" },
|
||||
{ "type": "string-range", "min": 4, "max": 33 },
|
||||
{ "type": "regex", "match": "^[a-z][a-z0-9]+$", "message": "Owner names must consist only of lowercase letters" }
|
||||
]
|
||||
}]
|
||||
}
|
||||
@@ -2,5 +2,22 @@
|
||||
"id": "react-ssr-template",
|
||||
"name": "React SSR",
|
||||
"description": "Next.js application skeleton for creating isomorphic web applications.",
|
||||
"ownerId": "ownerId"
|
||||
"ownerId": "ownerId",
|
||||
"fields": [
|
||||
{
|
||||
"id": "description",
|
||||
"title": "description",
|
||||
"type": "text",
|
||||
"description": "Description of the component",
|
||||
"validators": [
|
||||
{ "type": "required" },
|
||||
{ "type": "string-range", "min": 4, "max": 33 },
|
||||
{
|
||||
"type": "regex",
|
||||
"match": "^[a-z][a-z0-9]+$",
|
||||
"message": "Owner names must consist only of lowercase letters"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -15,6 +15,7 @@ services:
|
||||
container_name: boss-identity
|
||||
build:
|
||||
context: backend
|
||||
target: default
|
||||
args:
|
||||
service: identity
|
||||
restart: unless-stopped
|
||||
@@ -33,6 +34,7 @@ services:
|
||||
container_name: boss-builds
|
||||
build:
|
||||
context: backend
|
||||
target: default
|
||||
args:
|
||||
service: builds
|
||||
restart: unless-stopped
|
||||
@@ -42,6 +44,7 @@ services:
|
||||
container_name: boss-scaffolder
|
||||
build:
|
||||
context: backend
|
||||
target: scaffolder
|
||||
args:
|
||||
service: scaffolder
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
FROM python:3.8-slim
|
||||
FROM python:3.8-slim AS scaffolder
|
||||
RUN pip install cookiecutter==1.7.0 --index-url https://pypi.python.org/simple
|
||||
ENTRYPOINT [ "cookiecutter" ]
|
||||
Reference in New Issue
Block a user