updating npm publish for #516

This commit is contained in:
Brad Rydzewski 2014-10-07 19:15:33 -07:00
parent 08b59888c9
commit f8d5162c02
5 changed files with 133 additions and 173 deletions

View file

@ -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 <<EOF > ~/.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
}

106
plugin/publish/npm/npm.go Normal file
View file

@ -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 <<EOF > ~/.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
}

View file

@ -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")
})
}

View file

@ -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")
}
}

View file

@ -2,6 +2,7 @@ package publish
import ( import (
"github.com/drone/drone/plugin/condition" "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/buildfile"
"github.com/drone/drone/shared/build/repo" "github.com/drone/drone/shared/build/repo"
) )
@ -10,10 +11,10 @@ import (
// for publishing build artifacts when // for publishing build artifacts when
// a Build has succeeded // a Build has succeeded
type Publish struct { type Publish struct {
S3 *S3 `yaml:"s3,omitempty"` S3 *S3 `yaml:"s3,omitempty"`
Swift *Swift `yaml:"swift,omitempty"` Swift *Swift `yaml:"swift,omitempty"`
PyPI *PyPI `yaml:"pypi,omitempty"` PyPI *PyPI `yaml:"pypi,omitempty"`
NPM *NPM `yaml:"npm,omitempty"` NPM *npm.NPM `yaml:"npm,omitempty"`
} }
func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) { func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) {