Skip to content

Commit

Permalink
Merge pull request #140 from roots/add-trellis-version-option
Browse files Browse the repository at this point in the history
Add trellis version option for `new` command
  • Loading branch information
swalkinshaw authored Nov 13, 2020
2 parents 770d0b1 + 6779524 commit f17dd81
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 37 deletions.
23 changes: 16 additions & 7 deletions cmd/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type NewCommand struct {
name string
host string
skipVirtualenv bool
trellisVersion string
vaultPass string
}

Expand All @@ -41,6 +42,7 @@ func (c *NewCommand) init() {
c.flags.BoolVar(&c.force, "force", false, "Forces the creation of the project even if the target path is not empty")
c.flags.StringVar(&c.name, "name", "", "Main site name (the domain name). Bypasses the name prompt if specified. Example: mydomain.com")
c.flags.StringVar(&c.host, "host", "", "Main site hostname. Bypasses the host prompt if specified. Example: mydomain.com or www.mydomain.com")
c.flags.StringVar(&c.trellisVersion, "trellis-version", "latest", "Version of Trellis to create the project with (default: latest).")
c.flags.StringVar(&c.vaultPass, "vault-pass", ".vault_pass", "Path for the generated Vault pass file")
c.flags.BoolVar(&c.skipVirtualenv, "skip-virtualenv", false, "Skip creating a new virtual environment for this project")
}
Expand Down Expand Up @@ -107,11 +109,9 @@ func (c *NewCommand) Run(args []string) int {
}
}

fmt.Println("\nFetching latest versions of Trellis and Bedrock...")

trellisPath := filepath.Join(path, "trellis")
trellisVersion := github.DownloadLatestRelease("roots/trellis", path, trellisPath)
bedrockVersion := github.DownloadLatestRelease("roots/bedrock", path, filepath.Join(path, "site"))
trellisVersion := github.DownloadRelease("roots/trellis", c.trellisVersion, path, trellisPath)
bedrockVersion := github.DownloadRelease("roots/bedrock", "latest", path, filepath.Join(path, "site"))

os.Chdir(path)

Expand Down Expand Up @@ -180,15 +180,23 @@ Create a new project in the current directory:
Create a new project in the target path:
$ trellis new ~/dev/example.com
$ trellis new ~/projects/example.com
Force create a new project in a non-empty target path:
$ trellis new --force ~/dev/example.com
$ trellis new --force ~/projects/example.com
Specify name and host to bypass the prompts:
$ trellis new --name example.com --host www.example.com ~/dev/foo
$ trellis new --name example.com --host www.example.com ~/projects/foo
Create a new project with the dev version of Trellis:
$ trellis new --trellis-version dev ~/projects/example.com
Create a new project with a specific version of Trellis:
$ trellis new --trellis-version 1.7.0 ~/projects/example.com
Arguments:
PATH Path to create new project in
Expand All @@ -198,6 +206,7 @@ Options:
--name Main site name (the domain name). Bypasses the name prompt if specified. Example: mydomain.com
--host Main site hostname. Bypasses the host prompt if specified. Example: mydomain.com or www.mydomain.com
--skip-virtualenv (default: false) Skip creating a new virtual environment for this project
--trellis-version (default: latest) Version of Trellis to start the project with. Options: "latest", "dev", or any version (such as "1.0.0")
--vault-pass (default: .vault_pass) Path for the generated Vault pass file
-h, --help show this help
`
Expand Down
31 changes: 27 additions & 4 deletions github/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package github

import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
Expand All @@ -10,22 +11,40 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/mholt/archiver"
)

var BaseURL = "https://api.github.com"
var Client = &http.Client{Timeout: time.Second * 5}

type Release struct {
Version string `json:"tag_name"`
ZipUrl string `json:"zipball_url"`
URL string `json:"html_url"`
}

func DownloadLatestRelease(repo string, path string, dest string) string {
release, err := FetchLatestRelease(repo, http.DefaultClient)
if err != nil {
log.Fatal(err)
func NewReleaseFromVersion(repo string, version string) *Release {
return &Release{
Version: version,
ZipUrl: fmt.Sprintf("%s/repos/%s/zipball/%s", BaseURL, repo, version),
}
}

func DownloadRelease(repo string, version string, path string, dest string) string {
var err error
var release *Release

if version == "latest" {
release, err = FetchLatestRelease(repo, Client)
if err != nil {
log.Fatal(err)
}
} else if version == "dev" {
release = NewReleaseFromVersion(repo, "master")
} else {
release = NewReleaseFromVersion(repo, version)
}

os.Chdir(path)
Expand Down Expand Up @@ -99,6 +118,10 @@ func DownloadFile(filepath string, url string) error {
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusNotFound {
return errors.New(fmt.Sprintf("404 Not found: %s", url))
}

_, err = io.Copy(out, resp.Body)
if err != nil {
return err
Expand Down
156 changes: 156 additions & 0 deletions github/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package github

import (
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/mholt/archiver"
)

func TestNewReleaseFromVersion(t *testing.T) {
release := NewReleaseFromVersion("roots/trellis-cli", "1.0.0")

var expectedRelease = &Release{
Version: "1.0.0",
ZipUrl: "https://api.github.com/repos/roots/trellis-cli/zipball/1.0.0",
}

if !cmp.Equal(expectedRelease, release) {
t.Errorf("expected release %s but got %s", expectedRelease, release)
}
}

func TestDownloadRelease(t *testing.T) {
tmpDir, _ := ioutil.TempDir("", "release_test")
defer os.RemoveAll(tmpDir)
os.Chdir(tmpDir)

var dir = "roots-trellis"

err := os.Mkdir(dir, os.ModePerm)
if err != nil {
t.Error(err)
}

server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Header().Set("Content-type", "application/octet-stream")
rw.Header().Set("Content-Disposition", "attachment; filename='release.zip'")

err = createZipFile([]string{dir}, rw)
if err != nil {
t.Error(err)
}
}))
defer server.Close()

BaseURL = server.URL
client := server.Client()
Client = client

const expectedVersion = "1.0.0"

version := DownloadRelease("roots/trellis", expectedVersion, tmpDir, filepath.Join(tmpDir, "test_release_dir"))

if expectedVersion != version {
t.Errorf("expected version %s but got %s", expectedVersion, version)
}
}

func TestFetechLatestRelease(t *testing.T) {
cases := []struct {
name string
response string
responseError string
release *Release
}{
{
"success response",
fmt.Sprintf(`{
"tag_name": "v1.0",
"html_url": "https://github.com/roots/trellis-cli/releases/tag/v1.0",
"zipball_url": "https://api.github.com/repos/roots/trellis-cli/zipball/v1.0"
}`),
"",
&Release{
Version: "v1.0",
URL: "https://github.com/roots/trellis-cli/releases/tag/v1.0",
ZipUrl: "https://api.github.com/repos/roots/trellis-cli/zipball/v1.0",
},
},
{
"error response",
"",
"some error",
nil,
},
}

for _, tc := range cases {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if tc.responseError != "" {
http.Error(rw, tc.responseError, 400)
} else {
rw.Write([]byte(tc.response))
}
}))
defer server.Close()

BaseURL = server.URL
client := server.Client()

release, _ := FetchLatestRelease("roots/trellis-cli", client)

if !cmp.Equal(tc.release, release) {
t.Errorf("expected release %s but got %s", tc.release, release)
}
}
}

func createZipFile(files []string, writer io.Writer) error {
zip := archiver.NewZip()

err := zip.Create(writer)
if err != nil {
return err
}

defer zip.Close()

for _, fname := range files {
info, err := os.Stat(fname)
if err != nil {
return err
}

internalName, err := archiver.NameInArchive(info, fname, fname)
if err != nil {
return err
}

file, err := os.Open(fname)
if err != nil {
return err
}

err = zip.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: internalName,
},
ReadCloser: file,
})

if err != nil {
return err
}
}

return nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/dsnet/compress v0.0.0-20171208185109-cc9eb1d7ad76 // indirect
github.com/fatih/color v1.7.0
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/google/go-cmp v0.5.3
github.com/google/go-querystring v1.0.0 // indirect
github.com/hashicorp/go-version v1.2.1
github.com/manifoldco/promptui v0.3.3-0.20190214151314-7150aa4d998c
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg=
Expand Down Expand Up @@ -80,6 +82,7 @@ github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mcuadros/go-version v0.0.0-20180611085657-6d5863ca60fa h1:XvNrttGMJfVrUqblGju4IkjYXwx6l5OAAyjaIsydzsk=
github.com/mcuadros/go-version v0.0.0-20180611085657-6d5863ca60fa/go.mod h1:76rfSfYPWj01Z85hUf/ituArm797mNKcvINh1OlsZKo=
github.com/mholt/archiver v1.1.2 h1:xukR55YIrnhDHp10lrNtRSsAK5THpWrOCuviweNSBw4=
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw=
Expand Down Expand Up @@ -171,6 +174,7 @@ golang.org/x/tools v0.0.0-20201028153306-37f0764111ff h1:TU04fJ6/hxmk+6BeFPKM3iu
golang.org/x/tools v0.0.0-20201028153306-37f0764111ff/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
Expand Down
4 changes: 1 addition & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package main
import (
"fmt"
"log"
"net/http"
"os"
"time"
"trellis-cli/cmd"
"trellis-cli/config"
"trellis-cli/github"
Expand All @@ -25,7 +23,7 @@ func main() {

updateNotifier := &update.Notifier{
CacheDir: cacheDir,
Client: &http.Client{Timeout: time.Second * 5},
Client: github.Client,
Repo: updaterRepo,
Version: version,
}
Expand Down
2 changes: 1 addition & 1 deletion trellis/virtualenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (v *Virtualenv) Install() string {
}
}

return github.DownloadLatestRelease("pypa/virtualenv", os.TempDir(), localPath)
return github.DownloadRelease("pypa/virtualenv", "latest", os.TempDir(), localPath)
}

func (v *Virtualenv) Installed() (ok bool, cmd *exec.Cmd) {
Expand Down
Loading

0 comments on commit f17dd81

Please sign in to comment.