mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-19 14:05:31 +00:00
Merge branch 'master' into live_commit_update
This commit is contained in:
commit
8f93561f04
46 changed files with 558 additions and 193 deletions
|
@ -1 +0,0 @@
|
||||||
.git
|
|
|
@ -5,6 +5,7 @@ env:
|
||||||
- GOROOT=/usr/local/go
|
- GOROOT=/usr/local/go
|
||||||
- PATH=$PATH:$GOROOT/bin:$GOPATH/bin
|
- PATH=$PATH:$GOROOT/bin:$GOPATH/bin
|
||||||
script:
|
script:
|
||||||
|
- sudo apt-get update 1> /dev/null 2> /dev/null
|
||||||
- sudo apt-get -y install zip libsqlite3-dev sqlite3 rpm 1> /dev/null 2> /dev/null
|
- sudo apt-get -y install zip libsqlite3-dev sqlite3 rpm 1> /dev/null 2> /dev/null
|
||||||
- gem install fpm
|
- gem install fpm
|
||||||
- rbenv rehash
|
- rbenv rehash
|
||||||
|
|
|
@ -10,7 +10,7 @@ WORKDIR /gopath/src/github.com/drone/drone
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install zip libsqlite3-dev sqlite3 1> /dev/null 2> /dev/null
|
RUN apt-get -y install zip libsqlite3-dev sqlite3 1> /dev/null 2> /dev/null
|
||||||
RUN make deps build test embed install
|
RUN make deps build embed install
|
||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
ENTRYPOINT ["/usr/local/bin/droned"]
|
ENTRYPOINT ["/usr/local/bin/droned"]
|
||||||
|
|
12
Makefile
12
Makefile
|
@ -1,4 +1,6 @@
|
||||||
SHA := $(shell git rev-parse --short HEAD)
|
SHA := $(shell git rev-parse --short HEAD)
|
||||||
|
VERSION := $(shell cat VERSION)
|
||||||
|
ITTERATION := $(shell date +%s)
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
|
@ -23,8 +25,8 @@ test_postgres:
|
||||||
build:
|
build:
|
||||||
mkdir -p packaging/output
|
mkdir -p packaging/output
|
||||||
mkdir -p packaging/root/usr/local/bin
|
mkdir -p packaging/root/usr/local/bin
|
||||||
go build -o packaging/root/usr/local/bin/drone -ldflags "-X main.revision $(SHA)" github.com/drone/drone/cli
|
go build -o packaging/root/usr/local/bin/drone -ldflags "-X main.revision $(SHA) -X main.version $(VERSION)" github.com/drone/drone/cli
|
||||||
go build -o packaging/root/usr/local/bin/droned -ldflags "-X main.revision $(SHA)" github.com/drone/drone/server
|
go build -o packaging/root/usr/local/bin/droned -ldflags "-X main.revision $(SHA) -X main.version $(VERSION)" github.com/drone/drone/server
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -t /usr/local/bin packaging/root/usr/local/bin/drone
|
install -t /usr/local/bin packaging/root/usr/local/bin/drone
|
||||||
|
@ -52,9 +54,10 @@ embed:
|
||||||
# creates a debian package for drone to install
|
# creates a debian package for drone to install
|
||||||
# `sudo dpkg -i drone.deb`
|
# `sudo dpkg -i drone.deb`
|
||||||
deb:
|
deb:
|
||||||
fpm -s dir -t deb -n drone -v 0.3 -p packaging/output/drone.deb \
|
fpm -s dir -t deb -n drone -v $(VERSION) -p packaging/output/drone.deb \
|
||||||
--deb-priority optional --category admin \
|
--deb-priority optional --category admin \
|
||||||
--force \
|
--force \
|
||||||
|
--iteration $(ITTERATION) \
|
||||||
--deb-compression bzip2 \
|
--deb-compression bzip2 \
|
||||||
--after-install packaging/scripts/postinst.deb \
|
--after-install packaging/scripts/postinst.deb \
|
||||||
--before-remove packaging/scripts/prerm.deb \
|
--before-remove packaging/scripts/prerm.deb \
|
||||||
|
@ -68,9 +71,10 @@ deb:
|
||||||
packaging/root/=/
|
packaging/root/=/
|
||||||
|
|
||||||
rpm:
|
rpm:
|
||||||
fpm -s dir -t rpm -n drone -v 0.3 -p packaging/output/drone.rpm \
|
fpm -s dir -t rpm -n drone -v $(VERSION) -p packaging/output/drone.rpm \
|
||||||
--rpm-compression bzip2 --rpm-os linux \
|
--rpm-compression bzip2 --rpm-os linux \
|
||||||
--force \
|
--force \
|
||||||
|
--iteration $(ITTERATION) \
|
||||||
--after-install packaging/scripts/postinst.rpm \
|
--after-install packaging/scripts/postinst.rpm \
|
||||||
--before-remove packaging/scripts/prerm.rpm \
|
--before-remove packaging/scripts/prerm.rpm \
|
||||||
--after-remove packaging/scripts/postrm.rpm \
|
--after-remove packaging/scripts/postrm.rpm \
|
||||||
|
|
|
@ -100,12 +100,14 @@ open=true
|
||||||
[github]
|
[github]
|
||||||
client=""
|
client=""
|
||||||
secret=""
|
secret=""
|
||||||
|
orgs=[]
|
||||||
|
|
||||||
[github_enterprise]
|
[github_enterprise]
|
||||||
client=""
|
client=""
|
||||||
secret=""
|
secret=""
|
||||||
api=""
|
api=""
|
||||||
url=""
|
url=""
|
||||||
|
orgs=[]
|
||||||
private_mode=false
|
private_mode=false
|
||||||
|
|
||||||
[bitbucket]
|
[bitbucket]
|
||||||
|
|
1
VERSION
Normal file
1
VERSION
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0.3.0-alpha
|
48
cli/keys.go
Normal file
48
cli/keys.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/codegangsta/cli"
|
||||||
|
"github.com/drone/drone/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSetKeyCommand returns the CLI command for "set-key".
|
||||||
|
func NewSetKeyCommand() cli.Command {
|
||||||
|
return cli.Command{
|
||||||
|
Name: "set-key",
|
||||||
|
Usage: "sets the SSH private key used to clone",
|
||||||
|
Flags: []cli.Flag{},
|
||||||
|
Action: func(c *cli.Context) {
|
||||||
|
handle(c, setKeyCommandFunc)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// setKeyCommandFunc executes the "set-key" command.
|
||||||
|
func setKeyCommandFunc(c *cli.Context, client *client.Client) error {
|
||||||
|
var host, owner, name, path string
|
||||||
|
var args = c.Args()
|
||||||
|
|
||||||
|
if len(args) != 0 {
|
||||||
|
host, owner, name = parseRepo(args[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) == 2 {
|
||||||
|
path = args[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not find private RSA key %s. %s", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
path_pub := path + ".pub"
|
||||||
|
priv, err := ioutil.ReadFile(path_pub)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Could not find public RSA key %s. %s", path_pub, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Repos.SetKey(host, owner, name, string(pub), string(priv))
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// commit sha for the current build.
|
// commit sha for the current build.
|
||||||
version string = "0.3-dev"
|
version string
|
||||||
revision string
|
revision string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ func main() {
|
||||||
NewDisableCommand(),
|
NewDisableCommand(),
|
||||||
NewRestartCommand(),
|
NewRestartCommand(),
|
||||||
NewWhoamiCommand(),
|
NewWhoamiCommand(),
|
||||||
|
NewSetKeyCommand(),
|
||||||
}
|
}
|
||||||
|
|
||||||
app.Run(os.Args)
|
app.Run(os.Args)
|
||||||
|
|
|
@ -14,7 +14,7 @@ type RepoService struct {
|
||||||
func (s *RepoService) Get(host, owner, name string) (*model.Repo, error) {
|
func (s *RepoService) Get(host, owner, name string) (*model.Repo, error) {
|
||||||
var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name)
|
var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name)
|
||||||
var repo = model.Repo{}
|
var repo = model.Repo{}
|
||||||
var err = s.run("PUT", path, nil, &repo)
|
var err = s.run("GET", path, nil, &repo)
|
||||||
return &repo, err
|
return &repo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,16 @@ func (s *RepoService) Disable(host, owner, name string) error {
|
||||||
return s.run("DELETE", path, nil, nil)
|
return s.run("DELETE", path, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PUT /api/repos/{host}/{owner}/{name}
|
||||||
|
func (s *RepoService) SetKey(host, owner, name, pub, priv string) error {
|
||||||
|
var path = fmt.Sprintf("/api/repos/%s/%s/%s", host, owner, name)
|
||||||
|
var in = struct {
|
||||||
|
PublicKey string `json:"public_key"`
|
||||||
|
PrivateKey string `json:"private_key"`
|
||||||
|
}{pub, priv}
|
||||||
|
return s.run("PUT", path, &in, nil)
|
||||||
|
}
|
||||||
|
|
||||||
// GET /api/user/repos
|
// GET /api/user/repos
|
||||||
func (s *RepoService) List() ([]*model.Repo, error) {
|
func (s *RepoService) List() ([]*model.Repo, error) {
|
||||||
var repos []*model.Repo
|
var repos []*model.Repo
|
||||||
|
|
|
@ -22,40 +22,35 @@ port=":80"
|
||||||
driver="sqlite3"
|
driver="sqlite3"
|
||||||
datasource="/var/lib/drone/drone.sqlite"
|
datasource="/var/lib/drone/drone.sqlite"
|
||||||
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
# Open Registration allows users to self-register for Drone.
|
|
||||||
# This is recommended if Drone is being hosted behind a
|
|
||||||
# firewall.
|
|
||||||
#
|
|
||||||
# When false, the system admin will need to manually add
|
|
||||||
# users to Drone through the admin screens.
|
|
||||||
#
|
|
||||||
# [registration]
|
|
||||||
# open=true
|
|
||||||
|
|
||||||
# [github]
|
# [github]
|
||||||
# client=""
|
# client=""
|
||||||
# secret=""
|
# secret=""
|
||||||
|
# orgs=[]
|
||||||
|
# open=false
|
||||||
|
|
||||||
# [github_enterprise]
|
# [github_enterprise]
|
||||||
# client=""
|
# client=""
|
||||||
# secret=""
|
# secret=""
|
||||||
# api=""
|
# api=""
|
||||||
# url=""
|
# url=""
|
||||||
|
# orgs=[]
|
||||||
# private_mode=false
|
# private_mode=false
|
||||||
|
# open=false
|
||||||
|
|
||||||
# [bitbucket]
|
# [bitbucket]
|
||||||
# client=""
|
# client=""
|
||||||
# secret=""
|
# secret=""
|
||||||
|
# open=false
|
||||||
|
|
||||||
# [gitlab]
|
# [gitlab]
|
||||||
# url=""
|
# url=""
|
||||||
# skip_verify=false
|
# skip_verify=false
|
||||||
|
# open=false
|
||||||
|
|
||||||
# [gogs]
|
# [gogs]
|
||||||
# url=""
|
# url=""
|
||||||
# secret=""
|
# secret=""
|
||||||
|
# open=false
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
# SMTP configuration for Drone. This is required if you plan
|
# SMTP configuration for Drone. This is required if you plan
|
||||||
|
|
|
@ -29,10 +29,11 @@ func (w *Webhook) Send(context *model.Request) error {
|
||||||
func (w *Webhook) send(context *model.Request) error {
|
func (w *Webhook) send(context *model.Request) error {
|
||||||
// data will get posted in this format
|
// data will get posted in this format
|
||||||
data := struct {
|
data := struct {
|
||||||
|
From string `json:"from_url"`
|
||||||
Owner *model.User `json:"owner"`
|
Owner *model.User `json:"owner"`
|
||||||
Repo *model.Repo `json:"repository"`
|
Repo *model.Repo `json:"repository"`
|
||||||
Commit *model.Commit `json:"commit"`
|
Commit *model.Commit `json:"commit"`
|
||||||
}{context.User, context.Repo, context.Commit}
|
}{context.Host, context.User, context.Repo, context.Commit}
|
||||||
|
|
||||||
// data json encoded
|
// data json encoded
|
||||||
payload, err := json.Marshal(data)
|
payload, err := json.Marshal(data)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
package publish
|
|
50
plugin/publish/bintray/bintray.go
Normal file
50
plugin/publish/bintray/bintray.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package bintray
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone/drone/plugin/condition"
|
||||||
|
"github.com/drone/drone/shared/build/buildfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bintray struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
ApiKey string `yaml:"api_key"`
|
||||||
|
Packages []Package `yaml:"packages"`
|
||||||
|
|
||||||
|
Condition *condition.Condition `yaml:"when,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bintray) Write(f *buildfile.Buildfile) {
|
||||||
|
var cmd string
|
||||||
|
|
||||||
|
// Validate Username, ApiKey, Packages
|
||||||
|
if len(b.Username) == 0 || len(b.ApiKey) == 0 || len(b.Packages) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "Bintray Plugin: Missing argument(s)\n\n"`)
|
||||||
|
|
||||||
|
if len(b.Username) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "\tusername not defined in yaml config"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.ApiKey) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "\tapi_key not defined in yaml config"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b.Packages) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "\tpackages not defined in yaml config"`)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.WriteCmdSilent("exit 1")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pkg := range b.Packages {
|
||||||
|
pkg.Write(b.Username, b.ApiKey, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.WriteCmd(cmd)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bintray) GetCondition() *condition.Condition {
|
||||||
|
return b.Condition
|
||||||
|
}
|
116
plugin/publish/bintray/package.go
Normal file
116
plugin/publish/bintray/package.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package bintray
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/drone/drone/shared/build/buildfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const bintray_endpoint = "https://api.bintray.com/content/%s/%s/%s/%s/%s"
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
File string `yaml:"file"`
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
Owner string `yaml:"owner"`
|
||||||
|
Repository string `yaml:"repository"`
|
||||||
|
Package string `yaml:"package"`
|
||||||
|
Version string `yaml:"version"`
|
||||||
|
Target string `yaml:"target"`
|
||||||
|
Distr string `yaml:"distr,omitempty"`
|
||||||
|
Component string `yaml:"component,omitempty"`
|
||||||
|
Arch []string `yaml:"arch,omitempty"`
|
||||||
|
Publish bool `yaml:"publish,omitempty"`
|
||||||
|
Override bool `yaml:"override,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) Write(username, api_key string, f *buildfile.Buildfile) {
|
||||||
|
if len(p.File) == 0 || len(p.Owner) == 0 || len(p.Repository) == 0 || len(p.Package) == 0 || len(p.Version) == 0 || len(p.Target) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "Bintray Plugin: Missing argument(s)\n\n"`)
|
||||||
|
|
||||||
|
if len(p.Package) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage not defined in yaml config"`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.File) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: file not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Owner) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: owner not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Repository) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: repository not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Version) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: version not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Target) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: target not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
f.WriteCmdSilent("exit 1")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p.Type {
|
||||||
|
case "deb":
|
||||||
|
p.debUpload(username, api_key, f)
|
||||||
|
case "rpm":
|
||||||
|
p.upload(username, api_key, f)
|
||||||
|
case "maven":
|
||||||
|
p.upload(username, api_key, f)
|
||||||
|
default:
|
||||||
|
p.upload(username, api_key, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) debUpload(username, api_key string, f *buildfile.Buildfile) {
|
||||||
|
if len(p.Distr) == 0 || len(p.Component) == 0 || len(p.Arch) == 0 {
|
||||||
|
f.WriteCmdSilent(`echo -e "Bintray Plugin: Missing argument(s)\n\n"`)
|
||||||
|
|
||||||
|
if len(p.Distr) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: distr not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Component) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: component not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Arch) == 0 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\tpackage %s: arch not defined in yaml config"`, p.Package))
|
||||||
|
}
|
||||||
|
|
||||||
|
f.WriteCmdSilent("exit 1")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\nUpload %s to %s/%s/%s"`, p.File, p.Owner, p.Repository, p.Package))
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf("curl -s -T %s -u%s:%s %s\\;deb_distribution\\=%s\\;deb_component\\=%s\\;deb_architecture=\\%s\\;publish\\=%d\\;override\\=%d",
|
||||||
|
p.File, username, api_key, p.getEndpoint(), p.Distr, p.Component, strings.Join(p.Arch, ","), boolToInt(p.Publish), boolToInt(p.Override)))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) upload(username, api_key string, f *buildfile.Buildfile) {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(`echo -e "\nUpload %s to %s/%s/%s"`, p.File, p.Owner, p.Repository, p.Package))
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf("curl -s -T %s -u%s:%s %s\\;publish\\=%d\\;override\\=%d",
|
||||||
|
p.File, username, api_key, p.getEndpoint(), boolToInt(p.Publish), boolToInt(p.Override)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) getEndpoint() string {
|
||||||
|
return fmt.Sprintf(bintray_endpoint, p.Owner, p.Repository, p.Package, p.Version, p.Target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func boolToInt(val bool) int {
|
||||||
|
if val {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,7 +89,7 @@ func (d *Docker) Write(f *buildfile.Buildfile) {
|
||||||
f.WriteCmd("export DOCKER_HOST=" + d.DockerHost)
|
f.WriteCmd("export DOCKER_HOST=" + d.DockerHost)
|
||||||
|
|
||||||
// Build the image
|
// Build the image
|
||||||
f.WriteCmd(fmt.Sprintf("docker build -t %s:%s %s", d.ImageName, buildImageTag, dockerPath))
|
f.WriteCmd(fmt.Sprintf("docker build --pull -t %s:%s %s", d.ImageName, buildImageTag, dockerPath))
|
||||||
|
|
||||||
// Login?
|
// Login?
|
||||||
if d.RegistryLogin == true {
|
if d.RegistryLogin == true {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
"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"
|
||||||
"gopkg.in/v1/yaml"
|
"gopkg.in/yaml.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PublishToDrone struct {
|
type PublishToDrone struct {
|
||||||
|
@ -91,7 +91,7 @@ func TestPrivateRegistryNoAuth(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker build -t registry/image:$(git rev-parse --short HEAD)") {
|
if !strings.Contains(response, "docker build --pull -t registry/image:$(git rev-parse --short HEAD)") {
|
||||||
t.Fatalf("Response: " + response + " doesn't contain registry in image-names: expected registry/image\n\n")
|
t.Fatalf("Response: " + response + " doesn't contain registry in image-names: expected registry/image\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,8 +121,8 @@ func TestPrivateRegistryAuth(t *testing.T) {
|
||||||
t.Log("\n\n\n\ndocker login -u username -p xxxxxxxx -e email@example.com https://registry:8000/v1/\n\n\n\n")
|
t.Log("\n\n\n\ndocker login -u username -p xxxxxxxx -e email@example.com https://registry:8000/v1/\n\n\n\n")
|
||||||
t.Fatalf("Response: " + response + " doesn't contain private registry login\n\n")
|
t.Fatalf("Response: " + response + " doesn't contain private registry login\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker build -t registry/image:$(git rev-parse --short HEAD) .") {
|
if !strings.Contains(response, "docker build --pull -t registry/image:$(git rev-parse --short HEAD) .") {
|
||||||
t.Log("docker build -t registry/image:$(git rev-parse --short HEAD) .")
|
t.Log("docker build --pull -t registry/image:$(git rev-parse --short HEAD) .")
|
||||||
t.Fatalf("Response: " + response + " doesn't contain registry in image-names\n\n")
|
t.Fatalf("Response: " + response + " doesn't contain registry in image-names\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ func TestSingleTag(t *testing.T) {
|
||||||
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
||||||
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should use a custom tag\n\n")
|
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should use a custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker build -t username/image:release-0.1") {
|
if !strings.Contains(response, "docker build --pull -t username/image:release-0.1") {
|
||||||
t.Fatalf("Response: " + response + " isn't tagging images using our custom tag\n\n")
|
t.Fatalf("Response: " + response + " isn't tagging images using our custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker push username/image:release-0.1") {
|
if !strings.Contains(response, "docker push username/image:release-0.1") {
|
||||||
|
@ -211,7 +211,7 @@ func TestTagsNoSingle(t *testing.T) {
|
||||||
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
||||||
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n")
|
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker build -t username/image:release-0.2") {
|
if !strings.Contains(response, "docker build --pull -t username/image:release-0.2") {
|
||||||
t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n")
|
t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker tag username/image:release-0.2 username/image:release-latest") {
|
if !strings.Contains(response, "docker tag username/image:release-0.2 username/image:release-latest") {
|
||||||
|
@ -253,7 +253,7 @@ func TestTagsWithSingle(t *testing.T) {
|
||||||
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
if strings.Contains(response, "$(git rev-parse --short HEAD)") {
|
||||||
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n")
|
t.Fatalf("Response: " + response + " is tagging images from git-refs when it should using custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker build -t username/image:release-0.3") {
|
if !strings.Contains(response, "docker build --pull -t username/image:release-0.3") {
|
||||||
t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n")
|
t.Fatalf("Response: " + response + " isn't tagging images using our first custom tag\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker tag username/image:release-0.3 username/image:release-0.2") {
|
if !strings.Contains(response, "docker tag username/image:release-0.3 username/image:release-0.2") {
|
||||||
|
@ -313,7 +313,7 @@ func TestValidYaml(t *testing.T) {
|
||||||
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(response, "docker build -t user/image:$(git rev-parse --short HEAD) - <") {
|
if !strings.Contains(response, "docker build --pull -t user/image:$(git rev-parse --short HEAD) - <") {
|
||||||
t.Fatalf("Response: " + response + "doesn't contain build command for commit hash\n\n")
|
t.Fatalf("Response: " + response + "doesn't contain build command for commit hash\n\n")
|
||||||
}
|
}
|
||||||
if !strings.Contains(response, "docker login -u user -p password -e email") {
|
if !strings.Contains(response, "docker login -u user -p password -e email") {
|
||||||
|
@ -346,7 +346,7 @@ func TestWithoutDockerFile(t *testing.T) {
|
||||||
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
t.Fatalf("Can't unmarshal script: %s\n\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(response, "docker build -t user/image:$(git rev-parse --short HEAD) .") {
|
if !strings.Contains(response, "docker build --pull -t user/image:$(git rev-parse --short HEAD) .") {
|
||||||
t.Fatalf("Response: " + response + " doesn't contain build command\n\n")
|
t.Fatalf("Response: " + response + " doesn't contain build command\n\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gopkg.in/v1/yaml"
|
"gopkg.in/yaml.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var validcfg = map[string]interface{}{
|
var validcfg = map[string]interface{}{
|
||||||
|
|
|
@ -18,8 +18,22 @@ email = %s
|
||||||
EOF
|
EOF
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// command to publish npm package if not published
|
||||||
|
const CmdPublish = `
|
||||||
|
_NPM_PACKAGE_NAME=$(cd %s && npm list | head -n 1 | cut -d ' ' -f1)
|
||||||
|
_NPM_PACKAGE_TAG="%s"
|
||||||
|
if [ -z "$(npm info ${_NPM_PACKAGE_NAME} 2> /dev/null)" ]
|
||||||
|
then
|
||||||
|
npm publish %s
|
||||||
|
[ -n ${_NPM_PACKAGE_TAG} ] && npm tag ${_NPM_PACKAGE_NAME} ${_NPM_PACKAGE_TAG}
|
||||||
|
else
|
||||||
|
echo "skipping publish, package ${_NPM_PACKAGE_NAME} already published"
|
||||||
|
fi
|
||||||
|
unset _NPM_PACKAGE_NAME
|
||||||
|
unset _NPM_PACKAGE_TAG
|
||||||
|
`
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CmdPublish = "npm publish %s"
|
|
||||||
CmdAlwaysAuth = "npm set always-auth true"
|
CmdAlwaysAuth = "npm set always-auth true"
|
||||||
CmdSetRegistry = "npm config set registry %s"
|
CmdSetRegistry = "npm config set registry %s"
|
||||||
)
|
)
|
||||||
|
@ -43,10 +57,6 @@ type NPM struct {
|
||||||
// and publish to a repository
|
// and publish to a repository
|
||||||
Password string `yaml:"password,omitempty"`
|
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
|
// The registry URL of custom npm repository
|
||||||
Registry string `yaml:"registry,omitempty"`
|
Registry string `yaml:"registry,omitempty"`
|
||||||
|
|
||||||
|
@ -94,16 +104,11 @@ func (n *NPM) Write(f *buildfile.Buildfile) {
|
||||||
f.WriteCmd(CmdAlwaysAuth)
|
f.WriteCmd(CmdAlwaysAuth)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd = fmt.Sprintf(CmdPublish, n.Folder)
|
if len(n.Folder) == 0 {
|
||||||
if len(n.Tag) != 0 {
|
n.Folder = "."
|
||||||
cmd += fmt.Sprintf(" --tag %s", n.Tag)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Force {
|
f.WriteString(fmt.Sprintf(CmdPublish, n.Folder, n.Tag, n.Folder))
|
||||||
cmd += " --force"
|
|
||||||
}
|
|
||||||
|
|
||||||
f.WriteCmd(cmd)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NPM) GetCondition() *condition.Condition {
|
func (n *NPM) GetCondition() *condition.Condition {
|
||||||
|
|
|
@ -31,23 +31,21 @@ func Test_NPM(t *testing.T) {
|
||||||
|
|
||||||
n.Write(b)
|
n.Write(b)
|
||||||
out := b.String()
|
out := b.String()
|
||||||
g.Assert(strings.Contains(out, "\nnpm publish /path/to/repo\n")).Equal(true)
|
g.Assert(strings.Contains(out, "npm publish /path/to/repo\n")).Equal(true)
|
||||||
g.Assert(strings.Contains(out, "\nnpm set")).Equal(false)
|
g.Assert(strings.Contains(out, "\nnpm set")).Equal(false)
|
||||||
g.Assert(strings.Contains(out, "\nnpm config set")).Equal(false)
|
g.Assert(strings.Contains(out, "\nnpm config set")).Equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should set force", func() {
|
g.It("Should use current directory if folder is empty", func() {
|
||||||
b := new(buildfile.Buildfile)
|
b := new(buildfile.Buildfile)
|
||||||
n := NPM{
|
n := NPM{
|
||||||
Email: "foo@bar.com",
|
Email: "foo@bar.com",
|
||||||
Username: "foo",
|
Username: "foo",
|
||||||
Password: "bar",
|
Password: "bar",
|
||||||
Folder: "/path/to/repo",
|
|
||||||
Force: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Write(b)
|
n.Write(b)
|
||||||
g.Assert(strings.Contains(b.String(), "\nnpm publish /path/to/repo --force\n")).Equal(true)
|
g.Assert(strings.Contains(b.String(), "npm publish .\n")).Equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should set tag", func() {
|
g.It("Should set tag", func() {
|
||||||
|
@ -61,7 +59,8 @@ func Test_NPM(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Write(b)
|
n.Write(b)
|
||||||
g.Assert(strings.Contains(b.String(), "\nnpm publish /path/to/repo --tag 1.0.0\n")).Equal(true)
|
g.Assert(strings.Contains(b.String(), "\n_NPM_PACKAGE_TAG=\"1.0.0\"\n")).Equal(true)
|
||||||
|
g.Assert(strings.Contains(b.String(), "npm tag ${_NPM_PACKAGE_NAME} ${_NPM_PACKAGE_TAG}\n")).Equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
g.It("Should set registry", func() {
|
g.It("Should set registry", func() {
|
||||||
|
|
|
@ -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/bintray"
|
||||||
"github.com/drone/drone/plugin/publish/npm"
|
"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"
|
||||||
|
@ -11,13 +12,14 @@ 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.NPM `yaml:"npm,omitempty"`
|
NPM *npm.NPM `yaml:"npm,omitempty"`
|
||||||
Docker *Docker `yaml:"docker,omitempty"`
|
Docker *Docker `yaml:"docker,omitempty"`
|
||||||
Github *Github `yaml:"github,omitempty"`
|
Github *Github `yaml:"github,omitempty"`
|
||||||
Dropbox *Dropbox `yaml:"dropbox,omitempty"`
|
Dropbox *Dropbox `yaml:"dropbox,omitempty"`
|
||||||
|
Bintray *bintray.Bintray `yaml:"bintray,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) {
|
func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) {
|
||||||
|
@ -55,6 +57,11 @@ func (p *Publish) Write(f *buildfile.Buildfile, r *repo.Repo) {
|
||||||
if p.Dropbox != nil && match(p.Dropbox.GetCondition(), r) {
|
if p.Dropbox != nil && match(p.Dropbox.GetCondition(), r) {
|
||||||
p.Dropbox.Write(f)
|
p.Dropbox.Write(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bintray
|
||||||
|
if p.Bintray != nil && match(p.Bintray.GetCondition(), r) {
|
||||||
|
p.Bintray.Write(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func match(c *condition.Condition, r *repo.Repo) bool {
|
func match(c *condition.Condition, r *repo.Repo) bool {
|
||||||
|
|
|
@ -27,19 +27,21 @@ type Bitbucket struct {
|
||||||
API string
|
API string
|
||||||
Client string
|
Client string
|
||||||
Secret string
|
Secret string
|
||||||
|
Open bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(url, api, client, secret string) *Bitbucket {
|
func New(url, api, client, secret string, open bool) *Bitbucket {
|
||||||
return &Bitbucket{
|
return &Bitbucket{
|
||||||
URL: url,
|
URL: url,
|
||||||
API: api,
|
API: api,
|
||||||
Client: client,
|
Client: client,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
|
Open: open,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(client, secret string) *Bitbucket {
|
func NewDefault(client, secret string, open bool) *Bitbucket {
|
||||||
return New(DefaultURL, DefaultAPI, client, secret)
|
return New(DefaultURL, DefaultAPI, client, secret, open)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorize handles Bitbucket API Authorization
|
// Authorize handles Bitbucket API Authorization
|
||||||
|
@ -155,16 +157,16 @@ func (r *Bitbucket) GetRepos(user *model.User) ([]*model.Repo, error) {
|
||||||
// these are the urls required to clone the repository
|
// these are the urls required to clone the repository
|
||||||
// TODO use the bitbucketurl.Host and bitbucketurl.Scheme instead of hardcoding
|
// TODO use the bitbucketurl.Host and bitbucketurl.Scheme instead of hardcoding
|
||||||
// so that we can support Stash.
|
// so that we can support Stash.
|
||||||
var html = fmt.Sprintf("https://bitbucket.org/%s/%s", item.Owner, item.Name)
|
var html = fmt.Sprintf("https://bitbucket.org/%s/%s", item.Owner, item.Slug)
|
||||||
var clone = fmt.Sprintf("https://bitbucket.org/%s/%s.git", item.Owner, item.Name)
|
var clone = fmt.Sprintf("https://bitbucket.org/%s/%s.git", item.Owner, item.Slug)
|
||||||
var ssh = fmt.Sprintf("git@bitbucket.org:%s/%s.git", item.Owner, item.Name)
|
var ssh = fmt.Sprintf("git@bitbucket.org:%s/%s.git", item.Owner, item.Slug)
|
||||||
|
|
||||||
var repo = model.Repo{
|
var repo = model.Repo{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
Remote: remote,
|
Remote: remote,
|
||||||
Host: hostname,
|
Host: hostname,
|
||||||
Owner: item.Owner,
|
Owner: item.Owner,
|
||||||
Name: item.Name,
|
Name: item.Slug,
|
||||||
Private: item.Private,
|
Private: item.Private,
|
||||||
URL: html,
|
URL: html,
|
||||||
CloneURL: clone,
|
CloneURL: clone,
|
||||||
|
@ -261,7 +263,7 @@ func (r *Bitbucket) ParseHook(req *http.Request) (*model.Hook, error) {
|
||||||
|
|
||||||
return &model.Hook{
|
return &model.Hook{
|
||||||
Owner: hook.Repo.Owner,
|
Owner: hook.Repo.Owner,
|
||||||
Repo: hook.Repo.Name,
|
Repo: hook.Repo.Slug,
|
||||||
Sha: hook.Commits[len(hook.Commits)-1].Hash,
|
Sha: hook.Commits[len(hook.Commits)-1].Hash,
|
||||||
Branch: hook.Commits[len(hook.Commits)-1].Branch,
|
Branch: hook.Commits[len(hook.Commits)-1].Branch,
|
||||||
Author: author,
|
Author: author,
|
||||||
|
@ -269,3 +271,7 @@ func (r *Bitbucket) ParseHook(req *http.Request) (*model.Hook, error) {
|
||||||
Message: hook.Commits[len(hook.Commits)-1].Message,
|
Message: hook.Commits[len(hook.Commits)-1].Message,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Bitbucket) OpenRegistration() bool {
|
||||||
|
return r.Open
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ var (
|
||||||
// Bitbucket cloud configuration details
|
// Bitbucket cloud configuration details
|
||||||
bitbucketClient = config.String("bitbucket-client", "")
|
bitbucketClient = config.String("bitbucket-client", "")
|
||||||
bitbucketSecret = config.String("bitbucket-secret", "")
|
bitbucketSecret = config.String("bitbucket-secret", "")
|
||||||
|
bitbucketOpen = config.Bool("bitbucket-open", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registers the Bitbucket plugin using the default
|
// Registers the Bitbucket plugin using the default
|
||||||
|
@ -19,6 +20,6 @@ func Register() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remote.Register(
|
remote.Register(
|
||||||
NewDefault(*bitbucketClient, *bitbucketSecret),
|
NewDefault(*bitbucketClient, *bitbucketSecret, *bitbucketOpen),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,11 @@ type GitHub struct {
|
||||||
Secret string
|
Secret string
|
||||||
Private bool
|
Private bool
|
||||||
SkipVerify bool
|
SkipVerify bool
|
||||||
|
Orgs []string
|
||||||
|
Open bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(url, api, client, secret string, private, skipVerify bool) *GitHub {
|
func New(url, api, client, secret string, private, skipVerify bool, orgs []string, open bool) *GitHub {
|
||||||
var github = GitHub{
|
var github = GitHub{
|
||||||
URL: url,
|
URL: url,
|
||||||
API: api,
|
API: api,
|
||||||
|
@ -37,6 +39,8 @@ func New(url, api, client, secret string, private, skipVerify bool) *GitHub {
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
Private: private,
|
Private: private,
|
||||||
SkipVerify: skipVerify,
|
SkipVerify: skipVerify,
|
||||||
|
Orgs: orgs,
|
||||||
|
Open: open,
|
||||||
}
|
}
|
||||||
// the API must have a trailing slash
|
// the API must have a trailing slash
|
||||||
if !strings.HasSuffix(github.API, "/") {
|
if !strings.HasSuffix(github.API, "/") {
|
||||||
|
@ -49,8 +53,8 @@ func New(url, api, client, secret string, private, skipVerify bool) *GitHub {
|
||||||
return &github
|
return &github
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(client, secret string) *GitHub {
|
func NewDefault(client, secret string, orgs []string, open bool) *GitHub {
|
||||||
return New(DefaultURL, DefaultAPI, client, secret, false, false)
|
return New(DefaultURL, DefaultAPI, client, secret, false, false, orgs, open)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorize handles GitHub API Authorization.
|
// Authorize handles GitHub API Authorization.
|
||||||
|
@ -92,6 +96,16 @@ func (r *GitHub) Authorize(res http.ResponseWriter, req *http.Request) (*model.L
|
||||||
return nil, fmt.Errorf("Error retrieving user or verified email. %s", errr)
|
return nil, fmt.Errorf("Error retrieving user or verified email. %s", errr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(r.Orgs) > 0 {
|
||||||
|
allowedOrg, err := UserBelongsToOrg(client, r.Orgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not check org membership. %s", err)
|
||||||
|
}
|
||||||
|
if !allowedOrg {
|
||||||
|
return nil, fmt.Errorf("User does not belong to correct org")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var login = new(model.Login)
|
var login = new(model.Login)
|
||||||
login.ID = int64(*useremail.ID)
|
login.ID = int64(*useremail.ID)
|
||||||
login.Access = token.AccessToken
|
login.Access = token.AccessToken
|
||||||
|
@ -293,3 +307,7 @@ func (r *GitHub) ParsePullRequestHook(req *http.Request) (*model.Hook, error) {
|
||||||
|
|
||||||
return &hook, nil
|
return &hook, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *GitHub) OpenRegistration() bool {
|
||||||
|
return r.Open
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package github
|
package github
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone/drone/plugin/remote/github/testdata"
|
"github.com/drone/drone/plugin/remote/github/testdata"
|
||||||
|
@ -90,5 +93,40 @@ func Test_Github(t *testing.T) {
|
||||||
g.It("Should parse a commit hook")
|
g.It("Should parse a commit hook")
|
||||||
|
|
||||||
g.It("Should parse a pull request hook")
|
g.It("Should parse a pull request hook")
|
||||||
|
|
||||||
|
g.Describe("Authorize", func() {
|
||||||
|
g.AfterEach(func() {
|
||||||
|
github.Orgs = []string{}
|
||||||
|
})
|
||||||
|
|
||||||
|
var resp = httptest.NewRecorder()
|
||||||
|
var state = "validstate"
|
||||||
|
var req, _ = http.NewRequest(
|
||||||
|
"GET",
|
||||||
|
fmt.Sprintf("%s/?code=sekret&state=%s", server.URL, state),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
req.AddCookie(&http.Cookie{Name: "github_state", Value: state})
|
||||||
|
|
||||||
|
g.It("Should authorize a valid user with no org restrictions", func() {
|
||||||
|
var login, err = github.Authorize(resp, req)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(login == nil).IsFalse()
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should authorize a valid user in the correct org", func() {
|
||||||
|
github.Orgs = []string{"octocats-inc"}
|
||||||
|
var login, err = github.Authorize(resp, req)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(login == nil).IsFalse()
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should not authorize a valid user in the wrong org", func() {
|
||||||
|
github.Orgs = []string{"acme"}
|
||||||
|
var login, err = github.Authorize(resp, req)
|
||||||
|
g.Assert(err != nil).IsTrue()
|
||||||
|
g.Assert(login == nil).IsTrue()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ func GetOrgRepos(client *github.Client, org string) ([]github.Repository, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrgs is a helper function that returns a list of
|
// GetOrgs is a helper function that returns a list of
|
||||||
// all org repositories.
|
// all orgs that a user belongs to.
|
||||||
func GetOrgs(client *github.Client) ([]github.Organization, error) {
|
func GetOrgs(client *github.Client) ([]github.Organization, error) {
|
||||||
orgs, _, err := client.Organizations.List("", nil)
|
orgs, _, err := client.Organizations.List("", nil)
|
||||||
return orgs, err
|
return orgs, err
|
||||||
|
@ -270,3 +270,25 @@ func GetPayload(req *http.Request) []byte {
|
||||||
}
|
}
|
||||||
return []byte(payload)
|
return []byte(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserBelongsToOrg returns true if the currently authenticated user is a
|
||||||
|
// member of any of the organizations provided.
|
||||||
|
func UserBelongsToOrg(client *github.Client, permittedOrgs []string) (bool, error) {
|
||||||
|
userOrgs, err := GetOrgs(client)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userOrgSet := make(map[string]struct{}, len(userOrgs))
|
||||||
|
for _, org := range userOrgs {
|
||||||
|
userOrgSet[*org.Login] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, org := range permittedOrgs {
|
||||||
|
if _, ok := userOrgSet[org]; ok {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
|
@ -12,13 +12,22 @@ func Test_Helper(t *testing.T) {
|
||||||
var server = testdata.NewServer()
|
var server = testdata.NewServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
|
var client = NewClient(server.URL, "sekret", false)
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
g := goblin.Goblin(t)
|
||||||
g.Describe("GitHub Helper Functions", func() {
|
g.Describe("GitHub Helper Functions", func() {
|
||||||
|
|
||||||
g.It("Should Get a User")
|
g.It("Should Get a User")
|
||||||
g.It("Should Get a User Primary Email")
|
g.It("Should Get a User Primary Email")
|
||||||
g.It("Should Get a User + Primary Email")
|
g.It("Should Get a User + Primary Email")
|
||||||
g.It("Should Get a list of Orgs")
|
|
||||||
|
g.It("Should Get a list of Orgs", func() {
|
||||||
|
var orgs, err = GetOrgs(client)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(len(orgs)).Equal(1)
|
||||||
|
g.Assert(*orgs[0].Login).Equal("octocats-inc")
|
||||||
|
})
|
||||||
|
|
||||||
g.It("Should Get a list of User Repos")
|
g.It("Should Get a list of User Repos")
|
||||||
g.It("Should Get a list of Org Repos")
|
g.It("Should Get a list of Org Repos")
|
||||||
g.It("Should Get a list of All Repos")
|
g.It("Should Get a list of All Repos")
|
||||||
|
@ -30,5 +39,20 @@ func Test_Helper(t *testing.T) {
|
||||||
g.It("Should Create or Update a Repo Hook")
|
g.It("Should Create or Update a Repo Hook")
|
||||||
g.It("Should Get a Repo File")
|
g.It("Should Get a Repo File")
|
||||||
|
|
||||||
|
g.Describe("UserBelongsToOrg", func() {
|
||||||
|
g.It("Should confirm user does belong to 'octocats-inc' org", func() {
|
||||||
|
var requiredOrgs = []string{"one", "octocats-inc", "two"}
|
||||||
|
var member, err = UserBelongsToOrg(client, requiredOrgs)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(member).IsTrue()
|
||||||
|
})
|
||||||
|
|
||||||
|
g.It("Should confirm user not does belong to 'octocats-inc' org", func() {
|
||||||
|
var requiredOrgs = []string{"one", "two"}
|
||||||
|
var member, err = UserBelongsToOrg(client, requiredOrgs)
|
||||||
|
g.Assert(err == nil).IsTrue()
|
||||||
|
g.Assert(member).IsFalse()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ var (
|
||||||
// GitHub cloud configuration details
|
// GitHub cloud configuration details
|
||||||
githubClient = config.String("github-client", "")
|
githubClient = config.String("github-client", "")
|
||||||
githubSecret = config.String("github-secret", "")
|
githubSecret = config.String("github-secret", "")
|
||||||
|
githubOrgs = config.Strings("github-orgs")
|
||||||
|
githubOpen = config.Bool("github-open", false)
|
||||||
|
|
||||||
// GitHub Enterprise configuration details
|
// GitHub Enterprise configuration details
|
||||||
githubEnterpriseURL = config.String("github-enterprise-url", "")
|
githubEnterpriseURL = config.String("github-enterprise-url", "")
|
||||||
|
@ -17,6 +19,8 @@ var (
|
||||||
githubEnterpriseSecret = config.String("github-enterprise-secret", "")
|
githubEnterpriseSecret = config.String("github-enterprise-secret", "")
|
||||||
githubEnterprisePrivate = config.Bool("github-enterprise-private-mode", true)
|
githubEnterprisePrivate = config.Bool("github-enterprise-private-mode", true)
|
||||||
githubEnterpriseSkipVerify = config.Bool("github-enterprise-skip-verify", false)
|
githubEnterpriseSkipVerify = config.Bool("github-enterprise-skip-verify", false)
|
||||||
|
githubEnterpriseOrgs = config.Strings("github-enterprise-orgs")
|
||||||
|
githubEnterpriseOpen = config.Bool("github-enterprise-open", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registers the GitHub plugins using the default
|
// Registers the GitHub plugins using the default
|
||||||
|
@ -33,7 +37,7 @@ func registerGitHub() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remote.Register(
|
remote.Register(
|
||||||
NewDefault(*githubClient, *githubSecret),
|
NewDefault(*githubClient, *githubSecret, *githubOrgs, *githubOpen),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +57,8 @@ func registerGitHubEnterprise() {
|
||||||
*githubEnterpriseSecret,
|
*githubEnterpriseSecret,
|
||||||
*githubEnterprisePrivate,
|
*githubEnterprisePrivate,
|
||||||
*githubEnterpriseSkipVerify,
|
*githubEnterpriseSkipVerify,
|
||||||
|
*githubEnterpriseOrgs,
|
||||||
|
*githubEnterpriseOpen,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
71
plugin/remote/github/testdata/testdata.go
vendored
71
plugin/remote/github/testdata/testdata.go
vendored
|
@ -15,13 +15,22 @@ func NewServer() *httptest.Server {
|
||||||
|
|
||||||
// evaluate the path to serve a dummy data file
|
// evaluate the path to serve a dummy data file
|
||||||
switch r.URL.Path {
|
switch r.URL.Path {
|
||||||
|
case "/login/oauth/access_token":
|
||||||
|
w.Write(accessTokenPayload)
|
||||||
|
return
|
||||||
|
case "/user":
|
||||||
|
w.Write(userPayload)
|
||||||
|
return
|
||||||
|
case "/user/emails":
|
||||||
|
w.Write(userEmailsPayload)
|
||||||
|
return
|
||||||
case "/user/repos":
|
case "/user/repos":
|
||||||
w.Write(userReposPayload)
|
w.Write(userReposPayload)
|
||||||
return
|
return
|
||||||
case "/user/orgs":
|
case "/user/orgs":
|
||||||
w.Write(userOrgsPayload)
|
w.Write(userOrgsPayload)
|
||||||
return
|
return
|
||||||
case "/orgs/github/repos":
|
case "/orgs/octocats-inc/repos":
|
||||||
w.Write(userReposPayload)
|
w.Write(userReposPayload)
|
||||||
return
|
return
|
||||||
case "/repos/octocat/Hello-World/contents/.drone.yml":
|
case "/repos/octocat/Hello-World/contents/.drone.yml":
|
||||||
|
@ -56,6 +65,64 @@ func NewServer() *httptest.Server {
|
||||||
return server
|
return server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var accessTokenPayload = []byte(`access_token=sekret&scope=repo%2Cuser%3Aemail&token_type=bearer`)
|
||||||
|
|
||||||
|
var userPayload = []byte(`
|
||||||
|
{
|
||||||
|
"login": "octocat",
|
||||||
|
"id": 1,
|
||||||
|
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/octocat",
|
||||||
|
"html_url": "https://github.com/octocat",
|
||||||
|
"followers_url": "https://api.github.com/users/octocat/followers",
|
||||||
|
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/octocat/repos",
|
||||||
|
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false,
|
||||||
|
"name": "monalisa octocat",
|
||||||
|
"company": "GitHub",
|
||||||
|
"blog": "https://github.com/blog",
|
||||||
|
"location": "San Francisco",
|
||||||
|
"email": "octocat@github.com",
|
||||||
|
"hireable": false,
|
||||||
|
"bio": "There once was...",
|
||||||
|
"public_repos": 2,
|
||||||
|
"public_gists": 1,
|
||||||
|
"followers": 20,
|
||||||
|
"following": 0,
|
||||||
|
"created_at": "2008-01-14T04:33:35Z",
|
||||||
|
"updated_at": "2008-01-14T04:33:35Z",
|
||||||
|
"total_private_repos": 100,
|
||||||
|
"owned_private_repos": 100,
|
||||||
|
"private_gists": 81,
|
||||||
|
"disk_usage": 10000,
|
||||||
|
"collaborators": 8,
|
||||||
|
"plan": {
|
||||||
|
"name": "Medium",
|
||||||
|
"space": 400,
|
||||||
|
"private_repos": 20,
|
||||||
|
"collaborators": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
var userEmailsPayload = []byte(`
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"email": "octocat@github.com",
|
||||||
|
"verified": true,
|
||||||
|
"primary": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
`)
|
||||||
|
|
||||||
// sample repository list
|
// sample repository list
|
||||||
var userReposPayload = []byte(`
|
var userReposPayload = []byte(`
|
||||||
[
|
[
|
||||||
|
@ -108,7 +175,7 @@ var emptyObjPayload = []byte(`{}`)
|
||||||
// sample org list response
|
// sample org list response
|
||||||
var userOrgsPayload = []byte(`
|
var userOrgsPayload = []byte(`
|
||||||
[
|
[
|
||||||
{ "login": "github", "id": 1 }
|
{ "login": "octocats-inc", "id": 1 }
|
||||||
]
|
]
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,14 @@ import (
|
||||||
type Gitlab struct {
|
type Gitlab struct {
|
||||||
url string
|
url string
|
||||||
SkipVerify bool
|
SkipVerify bool
|
||||||
|
Open bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(url string, skipVerify bool) *Gitlab {
|
func New(url string, skipVerify, open bool) *Gitlab {
|
||||||
return &Gitlab{
|
return &Gitlab{
|
||||||
url: url,
|
url: url,
|
||||||
SkipVerify: skipVerify,
|
SkipVerify: skipVerify,
|
||||||
|
Open: open,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,3 +193,7 @@ func (r *Gitlab) ParseHook(req *http.Request) (*model.Hook, error) {
|
||||||
|
|
||||||
return hook, nil
|
return hook, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Gitlab) OpenRegistration() bool {
|
||||||
|
return r.Open
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ func Test_Github(t *testing.T) {
|
||||||
var server = testdata.NewServer()
|
var server = testdata.NewServer()
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
var gitlab = New(server.URL, false)
|
var gitlab = New(server.URL, false, false)
|
||||||
var user = model.User{
|
var user = model.User{
|
||||||
Access: "e3b0c44298fc1c149afbf4c8996fb",
|
Access: "e3b0c44298fc1c149afbf4c8996fb",
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
var (
|
var (
|
||||||
gitlabURL = config.String("gitlab-url", "")
|
gitlabURL = config.String("gitlab-url", "")
|
||||||
gitlabSkipVerify = config.Bool("gitlab-skip-verify", false)
|
gitlabSkipVerify = config.Bool("gitlab-skip-verify", false)
|
||||||
|
gitlabOpen = config.Bool("gitlab-open", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registers the Gitlab plugin using the default
|
// Registers the Gitlab plugin using the default
|
||||||
|
@ -21,6 +22,7 @@ func Register() {
|
||||||
New(
|
New(
|
||||||
*gitlabURL,
|
*gitlabURL,
|
||||||
*gitlabSkipVerify,
|
*gitlabSkipVerify,
|
||||||
|
*gitlabOpen,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,11 @@ import (
|
||||||
type Gogs struct {
|
type Gogs struct {
|
||||||
URL string
|
URL string
|
||||||
Secret string
|
Secret string
|
||||||
|
Open bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(url string, secret string) *Gogs {
|
func New(url string, secret string, open bool) *Gogs {
|
||||||
return &Gogs{URL: url, Secret: secret}
|
return &Gogs{URL: url, Secret: secret, Open: open}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authorize handles Gogs authorization
|
// Authorize handles Gogs authorization
|
||||||
|
@ -181,3 +182,7 @@ func (r *Gogs) ParseHook(req *http.Request) (*model.Hook, error) {
|
||||||
Message: payload.Commits[0].Message,
|
Message: payload.Commits[0].Message,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Gogs) OpenRegistration() bool {
|
||||||
|
return r.Open
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
var (
|
var (
|
||||||
gogsUrl = config.String("gogs-url", "")
|
gogsUrl = config.String("gogs-url", "")
|
||||||
gogsSecret = config.String("gogs-secret", "")
|
gogsSecret = config.String("gogs-secret", "")
|
||||||
|
gogsOpen = config.Bool("gogs-open", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registers the Gogs plugin using the default
|
// Registers the Gogs plugin using the default
|
||||||
|
@ -18,6 +19,6 @@ func Register() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
remote.Register(
|
remote.Register(
|
||||||
New(*gogsUrl, *gogsSecret),
|
New(*gogsUrl, *gogsSecret, *gogsOpen),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,9 @@ type Remote interface {
|
||||||
// ParseHook parses the post-commit hook from the Request body
|
// ParseHook parses the post-commit hook from the Request body
|
||||||
// and returns the required data in a standard format.
|
// and returns the required data in a standard format.
|
||||||
ParseHook(r *http.Request) (*model.Hook, error)
|
ParseHook(r *http.Request) (*model.Hook, error)
|
||||||
|
|
||||||
|
// Registration returns true if open registration is allowed
|
||||||
|
OpenRegistration() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of registered plugins.
|
// List of registered plugins.
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,10 +23,12 @@
|
||||||
|
|
||||||
<section ng-if="feed.length > 0">
|
<section ng-if="feed.length > 0">
|
||||||
<div class="pure-g cards">
|
<div class="pure-g cards">
|
||||||
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card" href="/{{ commit | fullPath }}" ng-repeat="commit in feed | limitTo:4" data-status="{{ commit.status }}">
|
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card" href="/{{ commit | fullPath }}" ng-repeat="commit in feed" data-status="{{ commit.status }}">
|
||||||
<div class="l-box">
|
<div class="l-box">
|
||||||
<h2>{{ commit.owner }} <span class="separator">/</span> {{ commit.name }}</h2>
|
<h2>{{ commit.owner }} <span class="separator">/</span> {{ commit.name }}</h2>
|
||||||
<em>{{ commit.finished_at | fromNow }}</em>
|
<em ng-if="commit.finished_at != 0">{{ commit.finished_at | fromNow }}</em>
|
||||||
|
<em ng-if="commit.finished_at == 0 && commit.started_at != 0">Started {{ commit.started_at | fromNow }}</em>
|
||||||
|
<em ng-if="commit.finished_at == 0 && commit.started_at == 0">Created {{ commit.created_at}}</em>
|
||||||
<img ng-src="{{ commit.gravatar | gravatar }}" />
|
<img ng-src="{{ commit.gravatar | gravatar }}" />
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
@ -35,7 +37,7 @@
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="pure-g cards">
|
<div class="pure-g cards">
|
||||||
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card-inactive" href="/{{ repo | fullPath }}" ng-repeat="repo in repos | filter: { active: false } | limitTo:3">
|
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card-inactive" href="/{{ repo | fullPath }}" ng-repeat="repo in repos | orderBy:'updated_at':true | filter: { active: false } | limitTo:3">
|
||||||
<div class="l-box">
|
<div class="l-box">
|
||||||
<h2>{{ repo.owner }} <span class="separator">/</span> {{ repo.name }}</h2>
|
<h2>{{ repo.owner }} <span class="separator">/</span> {{ repo.name }}</h2>
|
||||||
<em><span class="fa fa-plus"></span> Activate</em>
|
<em><span class="fa fa-plus"></span> Activate</em>
|
||||||
|
|
|
@ -34,8 +34,7 @@
|
||||||
<p>Add a .drone.yml file and make a commit to trigger a build</p>
|
<p>Add a .drone.yml file and make a commit to trigger a build</p>
|
||||||
<div><i class="fa fa-file-code-o"></i></div>
|
<div><i class="fa fa-file-code-o"></i></div>
|
||||||
</section>
|
</section>
|
||||||
|
<section ng-repeat="group in commits | filter:{ pull_request: '' }:true | unique: 'branch'">
|
||||||
<section ng-repeat="group in commits | filter: { pull_request: '' } | unique: 'branch'">
|
|
||||||
<div class="pure-g cards">
|
<div class="pure-g cards">
|
||||||
<h2 class="pure-u-1" style="font-size:22px;margin-bottom:20px;"><i class="fa fa-code-fork"></i> {{group.branch}}</h2>
|
<h2 class="pure-u-1" style="font-size:22px;margin-bottom:20px;"><i class="fa fa-code-fork"></i> {{group.branch}}</h2>
|
||||||
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card" ng-href="/{{ repo | fullPath }}/{{ commit.branch }}/{{ commit.sha }}" ng-repeat="commit in commits | filter:{ branch:group.branch }:true | limitTo:4" data-status="{{ commit.status }}">
|
<a class="pure-u-1 pure-u-md-1-4 pure-u-lg-1-4 pure-u-xl-1-4 card card" ng-href="/{{ repo | fullPath }}/{{ commit.branch }}/{{ commit.sha }}" ng-repeat="commit in commits | filter:{ branch:group.branch }:true | limitTo:4" data-status="{{ commit.status }}">
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package capability
|
|
||||||
|
|
||||||
import (
|
|
||||||
"code.google.com/p/go.net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Capability map[string]bool
|
|
||||||
|
|
||||||
// Get the capability value from the map.
|
|
||||||
func (c Capability) Get(key string) bool {
|
|
||||||
return c[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the capability value in the map.
|
|
||||||
func (c Capability) Set(key string, value bool) {
|
|
||||||
c[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enabled returns true if the capability is
|
|
||||||
// enabled in the system.
|
|
||||||
func Enabled(c context.Context, key string) bool {
|
|
||||||
return FromContext(c).Get(key)
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package capability
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.google.com/p/go.net/context"
|
|
||||||
"github.com/franela/goblin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBlobstore(t *testing.T) {
|
|
||||||
caps := map[string]bool{}
|
|
||||||
caps[Registration] = true
|
|
||||||
|
|
||||||
ctx := NewContext(context.Background(), caps)
|
|
||||||
|
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("Capabilities", func() {
|
|
||||||
|
|
||||||
g.It("Should get capabilities from context", func() {
|
|
||||||
g.Assert(Enabled(ctx, Registration)).Equal(true)
|
|
||||||
g.Assert(Enabled(ctx, "Fake Key")).Equal(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
package capability
|
|
||||||
|
|
||||||
const (
|
|
||||||
Registration = "REGISTRATION"
|
|
||||||
)
|
|
|
@ -1,32 +0,0 @@
|
||||||
package capability
|
|
||||||
|
|
||||||
import (
|
|
||||||
"code.google.com/p/go.net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
const reqkey = "capability"
|
|
||||||
|
|
||||||
// NewContext returns a Context whose Value method returns the
|
|
||||||
// application's Blobstore data.
|
|
||||||
func NewContext(parent context.Context, caps Capability) context.Context {
|
|
||||||
return &wrapper{parent, caps}
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrapper struct {
|
|
||||||
context.Context
|
|
||||||
caps Capability
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the named key from the context.
|
|
||||||
func (c *wrapper) Value(key interface{}) interface{} {
|
|
||||||
if key == reqkey {
|
|
||||||
return c.caps
|
|
||||||
}
|
|
||||||
return c.Context.Value(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromContext returns the capability map for the
|
|
||||||
// current context.
|
|
||||||
func FromContext(c context.Context) Capability {
|
|
||||||
return c.Value(reqkey).(Capability)
|
|
||||||
}
|
|
|
@ -49,20 +49,15 @@ func (db *Userstore) GetUserList() ([]*model.User, error) {
|
||||||
|
|
||||||
// PostUser saves a User in the datastore.
|
// PostUser saves a User in the datastore.
|
||||||
func (db *Userstore) PostUser(user *model.User) error {
|
func (db *Userstore) PostUser(user *model.User) error {
|
||||||
if user.Created == 0 {
|
user.Created = time.Now().UTC().Unix()
|
||||||
user.Created = time.Now().UTC().Unix()
|
|
||||||
}
|
|
||||||
user.Updated = time.Now().UTC().Unix()
|
user.Updated = time.Now().UTC().Unix()
|
||||||
return meddler.Save(db, userTable, user)
|
return meddler.Insert(db, userTable, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutUser saves a user in the datastore.
|
// PutUser saves a user in the datastore.
|
||||||
func (db *Userstore) PutUser(user *model.User) error {
|
func (db *Userstore) PutUser(user *model.User) error {
|
||||||
if user.Created == 0 {
|
|
||||||
user.Created = time.Now().UTC().Unix()
|
|
||||||
}
|
|
||||||
user.Updated = time.Now().UTC().Unix()
|
user.Updated = time.Now().UTC().Unix()
|
||||||
return meddler.Save(db, userTable, user)
|
return meddler.Update(db, userTable, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DelUser removes the user from the datastore.
|
// DelUser removes the user from the datastore.
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/plugin/remote"
|
"github.com/drone/drone/plugin/remote"
|
||||||
"github.com/drone/drone/server/capability"
|
|
||||||
"github.com/drone/drone/server/datastore"
|
"github.com/drone/drone/server/datastore"
|
||||||
"github.com/drone/drone/server/session"
|
"github.com/drone/drone/server/session"
|
||||||
"github.com/drone/drone/server/sync"
|
"github.com/drone/drone/server/sync"
|
||||||
|
@ -49,7 +48,7 @@ func GetLogin(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
// if self-registration is disabled we should
|
// if self-registration is disabled we should
|
||||||
// return a notAuthorized error. the only exception
|
// return a notAuthorized error. the only exception
|
||||||
// is if no users exist yet in the system we'll proceed.
|
// is if no users exist yet in the system we'll proceed.
|
||||||
if capability.Enabled(ctx, capability.Registration) == false {
|
if remote.OpenRegistration() == false {
|
||||||
users, err := datastore.GetUserList(ctx)
|
users, err := datastore.GetUserList(ctx)
|
||||||
if err != nil || len(users) != 0 {
|
if err != nil || len(users) != 0 {
|
||||||
log.Println("Unable to create account. Registration is closed")
|
log.Println("Unable to create account. Registration is closed")
|
||||||
|
@ -70,6 +69,13 @@ func GetLogin(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the user id should NEVER equal zero
|
||||||
|
if u.ID == 0 {
|
||||||
|
log.Println("Unable to create account. User ID is zero")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// if this is the first user, they
|
// if this is the first user, they
|
||||||
// should be an admin.
|
// should be an admin.
|
||||||
if u.ID == 1 {
|
if u.ID == 1 {
|
||||||
|
|
|
@ -149,6 +149,10 @@ func PutRepo(c web.C, w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if in.Params != nil {
|
if in.Params != nil {
|
||||||
repo.Params = *in.Params
|
repo.Params = *in.Params
|
||||||
|
if _, err := repo.ParamMap(); err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if in.PostCommit != nil {
|
if in.PostCommit != nil {
|
||||||
repo.PostCommit = *in.PostCommit
|
repo.PostCommit = *in.PostCommit
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"github.com/drone/drone/plugin/remote/gitlab"
|
"github.com/drone/drone/plugin/remote/gitlab"
|
||||||
"github.com/drone/drone/plugin/remote/gogs"
|
"github.com/drone/drone/plugin/remote/gogs"
|
||||||
"github.com/drone/drone/server/blobstore"
|
"github.com/drone/drone/server/blobstore"
|
||||||
"github.com/drone/drone/server/capability"
|
|
||||||
"github.com/drone/drone/server/datastore"
|
"github.com/drone/drone/server/datastore"
|
||||||
"github.com/drone/drone/server/datastore/database"
|
"github.com/drone/drone/server/datastore/database"
|
||||||
"github.com/drone/drone/server/worker/director"
|
"github.com/drone/drone/server/worker/director"
|
||||||
|
@ -41,7 +40,7 @@ const (
|
||||||
var (
|
var (
|
||||||
// commit sha for the current build, set by
|
// commit sha for the current build, set by
|
||||||
// the compile process.
|
// the compile process.
|
||||||
version string = "0.3-dev"
|
version string
|
||||||
revision string
|
revision string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,10 +55,6 @@ var (
|
||||||
sslcrt = config.String("server-ssl-cert", "")
|
sslcrt = config.String("server-ssl-cert", "")
|
||||||
sslkey = config.String("server-ssl-key", "")
|
sslkey = config.String("server-ssl-key", "")
|
||||||
|
|
||||||
// Enable self-registration. When false, the system admin
|
|
||||||
// must grant user access.
|
|
||||||
open = config.Bool("registration-open", false)
|
|
||||||
|
|
||||||
workers *pool.Pool
|
workers *pool.Pool
|
||||||
worker *director.Director
|
worker *director.Director
|
||||||
pub *pubsub.PubSub
|
pub *pubsub.PubSub
|
||||||
|
@ -70,8 +65,6 @@ var (
|
||||||
nodes StringArr
|
nodes StringArr
|
||||||
|
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
|
|
||||||
caps map[string]bool
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -104,9 +97,6 @@ func main() {
|
||||||
gitlab.Register()
|
gitlab.Register()
|
||||||
gogs.Register()
|
gogs.Register()
|
||||||
|
|
||||||
caps = map[string]bool{}
|
|
||||||
caps[capability.Registration] = *open
|
|
||||||
|
|
||||||
// setup the database and cancel all pending
|
// setup the database and cancel all pending
|
||||||
// commits in the system.
|
// commits in the system.
|
||||||
db = database.MustConnect(*driver, *datasource)
|
db = database.MustConnect(*driver, *datasource)
|
||||||
|
@ -170,7 +160,6 @@ func ContextMiddleware(c *web.C, h http.Handler) http.Handler {
|
||||||
ctx = pool.NewContext(ctx, workers)
|
ctx = pool.NewContext(ctx, workers)
|
||||||
ctx = director.NewContext(ctx, worker)
|
ctx = director.NewContext(ctx, worker)
|
||||||
ctx = pubsub.NewContext(ctx, pub)
|
ctx = pubsub.NewContext(ctx, pub)
|
||||||
ctx = capability.NewContext(ctx, caps)
|
|
||||||
|
|
||||||
// add the context to the goji web context
|
// add the context to the goji web context
|
||||||
webcontext.Set(c, ctx)
|
webcontext.Set(c, ctx)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Host string `json:"-"`
|
Host string `json:"-"`
|
||||||
User *User `json:"-"`
|
User *User `json:"-"`
|
||||||
|
@ -7,3 +11,16 @@ type Request struct {
|
||||||
Commit *Commit `json:"commit"`
|
Commit *Commit `json:"commit"`
|
||||||
Prior *Commit `json:"prior_commit"`
|
Prior *Commit `json:"prior_commit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URL returns the link to the commit in
|
||||||
|
// string format.
|
||||||
|
func (r *Request) URL() string {
|
||||||
|
return fmt.Sprintf("%s/%s/%s/%s/%s/%s",
|
||||||
|
r.Host,
|
||||||
|
r.Repo.Host,
|
||||||
|
r.Repo.Owner,
|
||||||
|
r.Repo.Name,
|
||||||
|
r.Commit.Branch,
|
||||||
|
r.Commit.Sha,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue