From f8d5162c0298019bbd66e156fbaf7159e76aa358 Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Tue, 7 Oct 2014 19:15:33 -0700 Subject: [PATCH] updating npm publish for #516 --- plugin/publish/npm.go | 78 ------------------------ plugin/publish/npm/npm.go | 106 +++++++++++++++++++++++++++++++++ plugin/publish/npm/npm_test.go | 22 +++++++ plugin/publish/npm_test.go | 91 ---------------------------- plugin/publish/publish.go | 9 +-- 5 files changed, 133 insertions(+), 173 deletions(-) delete mode 100644 plugin/publish/npm.go create mode 100644 plugin/publish/npm/npm.go create mode 100644 plugin/publish/npm/npm_test.go delete mode 100644 plugin/publish/npm_test.go diff --git a/plugin/publish/npm.go b/plugin/publish/npm.go deleted file mode 100644 index c01126e3..00000000 --- a/plugin/publish/npm.go +++ /dev/null @@ -1,78 +0,0 @@ -package publish - -import ( - "fmt" - - "github.com/drone/drone/plugin/condition" - "github.com/drone/drone/shared/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"` - - Condition *condition.Condition `yaml:"when,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)) -} - -func (n *NPM) GetCondition() *condition.Condition { - return n.Condition -} diff --git a/plugin/publish/npm/npm.go b/plugin/publish/npm/npm.go new file mode 100644 index 00000000..df02a8ed --- /dev/null +++ b/plugin/publish/npm/npm.go @@ -0,0 +1,106 @@ +package npm + +import ( + "fmt" + + "github.com/drone/config" + "github.com/drone/drone/plugin/condition" + "github.com/drone/drone/shared/build/buildfile" +) + +// command to create the .npmrc file that stores +// the login credentials, as opposed to npm login +// which requires stdin. +const CmdLogin = ` +cat < ~/.npmrc +_auth = $(echo "%s:%s" | tr -d "\r\n" | base64) +email = %s +EOF +` + +const CmdPublish = "npm publish %s" + +var ( + DefaultUser = config.String("npm-user", "") + DefaultPass = config.String("npm-pass", "") + DefaultEmail = config.String("npm-email", "") +) + +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"` + + // Force npm to always require authentication when accessing the registry. + AlwaysAuth bool `yaml:"always_auth"` + + Condition *condition.Condition `yaml:"when,omitempty"` +} + +func (n *NPM) Write(f *buildfile.Buildfile) { + // If the yaml doesn't provide a username or password + // we should attempt to use the global defaults. + if len(n.Email) == 0 { + n.Username = *DefaultUser + n.Password = *DefaultPass + n.Email = *DefaultEmail + } + + // If the yaml doesn't provide a username or password, + // and there was not global configuration defined, EXIT. + if len(n.Email) == 0 || + len(n.Username) == 0 || + len(n.Password) == 0 { + return + } + + var cmd = CmdPublish + + if len(n.Tag) != 0 { + cmd += fmt.Sprintf(" --tag %s", n.Tag) + } + + if n.Force { + cmd += " --force" + } + + // Setup the npm credentials + f.WriteCmdSilent(fmt.Sprintf(CmdLogin, n.Username, n.Password, n.Email)) + + // Setup custom npm registry + if len(n.Registry) != 0 { + f.WriteCmd(fmt.Sprintf("npm config set registry %s", n.Registry)) + } + + // Set npm to always authenticate + if n.AlwaysAuth { + f.WriteCmd("npm set always-auth true") + } + + f.WriteCmd(fmt.Sprintf(cmd, n.Folder)) +} + +func (n *NPM) GetCondition() *condition.Condition { + return n.Condition +} diff --git a/plugin/publish/npm/npm_test.go b/plugin/publish/npm/npm_test.go new file mode 100644 index 00000000..cd61492d --- /dev/null +++ b/plugin/publish/npm/npm_test.go @@ -0,0 +1,22 @@ +package npm + +import ( + "testing" + + "github.com/franela/goblin" +) + +func Test_NPM(t *testing.T) { + + g := goblin.Goblin(t) + g.Describe("NPM Publish", func() { + g.It("Should set force") + g.It("Should set tag") + g.It("Should set registry") + g.It("Should set always-auth") + g.It("Should run publish") + g.It("Should create npmrc") + g.It("Should fail when no username or password") + g.It("Should use default username or password") + }) +} diff --git a/plugin/publish/npm_test.go b/plugin/publish/npm_test.go deleted file mode 100644 index 388e743e..00000000 --- a/plugin/publish/npm_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package publish - -import ( - "strings" - "testing" - - "github.com/drone/drone/shared/build/buildfile" - - "gopkg.in/yaml.v1" -) - -// 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 := yaml.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/plugin/publish/publish.go b/plugin/publish/publish.go index 86d861f3..60ed6bb5 100644 --- a/plugin/publish/publish.go +++ b/plugin/publish/publish.go @@ -2,6 +2,7 @@ package publish import ( "github.com/drone/drone/plugin/condition" + "github.com/drone/drone/plugin/publish/npm" "github.com/drone/drone/shared/build/buildfile" "github.com/drone/drone/shared/build/repo" ) @@ -10,10 +11,10 @@ import ( // for publishing build artifacts when // a Build has succeeded type Publish struct { - S3 *S3 `yaml:"s3,omitempty"` - Swift *Swift `yaml:"swift,omitempty"` - PyPI *PyPI `yaml:"pypi,omitempty"` - NPM *NPM `yaml:"npm,omitempty"` + S3 *S3 `yaml:"s3,omitempty"` + Swift *Swift `yaml:"swift,omitempty"` + PyPI *PyPI `yaml:"pypi,omitempty"` + NPM *npm.NPM `yaml:"npm,omitempty"` } func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) {