diff --git a/Makefile b/Makefile index a1e3476ca..93ed269bf 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ database/testing \ mail \ model \ plugin/deploy \ +plugin/publish \ queue PKGS := $(addprefix github.com/drone/drone/pkg/,$(PKGS)) .PHONY := test $(PKGS) diff --git a/pkg/plugin/publish/npm.go b/pkg/plugin/publish/npm.go index 30b1a5b2a..d31879ed6 100644 --- a/pkg/plugin/publish/npm.go +++ b/pkg/plugin/publish/npm.go @@ -1 +1,73 @@ package publish + +import ( + "fmt" + + "github.com/drone/drone/pkg/build/buildfile" +) + +// use npm trick instead of running npm adduser that requires stdin +var npmLoginCmd = ` +cat < ~/.npmrc +_auth = $(echo "%s:%s" | tr -d "\r\n" | base64) +email = %s +EOF +` + +type NPM struct { + // The Email address used by NPM to connect + // and publish to a repository + Email string `yaml:"email,omitempty"` + + // The Username used by NPM to connect + // and publish to a repository + Username string `yaml:"username,omitempty"` + + // The Password used by NPM to connect + // and publish to a repository + Password string `yaml:"password,omitempty"` + + // Fails if the package name and version combination already + // exists in the registry. Overwrites when the "--force" flag is set. + Force bool `yaml:"force"` + + // The registry URL of custom npm repository + Registry string `yaml:"registry,omitempty"` + + // A folder containing the package.json file + Folder string `yaml:"folder,omitempty"` + + // Registers the published package with the given tag + Tag string `yaml:"tag,omitempty"` + + Branch string `yaml:"branch,omitempty"` +} + +func (n *NPM) Write(f *buildfile.Buildfile) { + + if len(n.Email) == 0 || len(n.Username) == 0 || len(n.Password) == 0 { + return + } + + npmPublishCmd := "npm publish %s" + + if n.Tag != "" { + npmPublishCmd += fmt.Sprintf(" --tag %s", n.Tag) + } + + if n.Force { + npmPublishCmd += " --force" + } + + f.WriteCmdSilent("echo 'publishing to NPM ...'") + + // Login to registry + f.WriteCmdSilent(fmt.Sprintf(npmLoginCmd, n.Username, n.Password, n.Email)) + + // Setup custom npm registry + if n.Registry != "" { + f.WriteCmdSilent(fmt.Sprintf("npm config set registry %s", n.Registry)) + } + + f.WriteCmd(fmt.Sprintf(npmPublishCmd, n.Folder)) +} \ No newline at end of file diff --git a/pkg/plugin/publish/npm_test.go b/pkg/plugin/publish/npm_test.go new file mode 100644 index 000000000..96c52581d --- /dev/null +++ b/pkg/plugin/publish/npm_test.go @@ -0,0 +1,91 @@ +package publish + +import ( + "strings" + "testing" + + "github.com/drone/drone/pkg/build/buildfile" + + "launchpad.net/goyaml" +) + +// emulate Build struct +type PublishToNPM struct { + Publish *Publish `yaml:"publish,omitempty"` +} + +var sampleYml1 = ` +publish: + npm: + username: foo + email: foo@example.com + password: bar +` + +var sampleYml2 = ` +publish: + npm: + username: foo + email: foo@example.com + password: bar + force: true +` + +var sampleYmlWithReg = ` +publish: + npm: + username: foo + email: foo@example.com + password: bar + registry: https://npm.example.com/me/ + folder: my-project/node-app/ + tag: 1.2.3 +` + +func setUpWithNPM(input string) (string, error) { + var buildStruct PublishToNPM + err := goyaml.Unmarshal([]byte(input), &buildStruct) + if err != nil { + return "", err + } + bf := buildfile.New() + buildStruct.Publish.Write(bf, nil) + return bf.String(), err +} + +func TestNPMPublish(t *testing.T) { + bscr, err := setUpWithNPM(sampleYml1) + if err != nil { + t.Fatalf("Can't unmarshal publish script: %s", err) + } + + if !strings.Contains(bscr, "npm publish") { + t.Error("Expect script to contain install command") + } +} + +func TestNPMForcePublish(t *testing.T) { + bscr, err := setUpWithNPM(sampleYml2) + if err != nil { + t.Fatalf("Can't unmarshal publish script: %s", err) + } + + if !strings.Contains(bscr, "npm publish --force") { + t.Error("Expect script to contain install command") + } +} + +func TestNPMPublishRegistry(t *testing.T) { + bscr, err := setUpWithNPM(sampleYmlWithReg) + if err != nil { + t.Fatalf("Can't unmarshal publish script: %s", err) + } + + if !strings.Contains(bscr, "npm config set registry https://npm.example.com/me/") { + t.Error("Expect script to contain npm config registry command") + } + + if !strings.Contains(bscr, "npm publish my-project/node-app/ --tag 1.2.3") { + t.Error("Expect script to contain npm publish command") + } +} diff --git a/pkg/plugin/publish/publish.go b/pkg/plugin/publish/publish.go index 93dceb184..546be583e 100644 --- a/pkg/plugin/publish/publish.go +++ b/pkg/plugin/publish/publish.go @@ -12,6 +12,7 @@ type Publish struct { S3 *S3 `yaml:"s3,omitempty"` Swift *Swift `yaml:"swift,omitempty"` PyPI *PyPI `yaml:"pypi,omitempty"` + NPM *NPM `yaml:"npm,omitempty"` } func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) { @@ -29,4 +30,9 @@ func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) { if p.PyPI != nil && (len(p.PyPI.Branch) == 0 || (len(p.PyPI.Branch) > 0 && r.Branch == p.PyPI.Branch)) { p.PyPI.Write(f) } + + // NPM + if p.NPM != nil && (len(p.NPM.Branch) == 0 || (len(p.NPM.Branch) > 0 && r.Branch == p.NPM.Branch)) { + p.NPM.Write(f) + } }