mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-12-23 00:46:30 +00:00
Merge remote-tracking branch 'upstream/master' into vagrant
This commit is contained in:
commit
564e3e8208
15 changed files with 369 additions and 8 deletions
2
Makefile
2
Makefile
|
@ -15,6 +15,7 @@ deps:
|
||||||
go get github.com/dchest/authcookie
|
go get github.com/dchest/authcookie
|
||||||
go get github.com/dchest/passwordreset
|
go get github.com/dchest/passwordreset
|
||||||
go get github.com/dchest/uniuri
|
go get github.com/dchest/uniuri
|
||||||
|
go get github.com/fluffle/goirc
|
||||||
#go get github.com/dotcloud/docker/archive
|
#go get github.com/dotcloud/docker/archive
|
||||||
#go get github.com/dotcloud/docker/utils
|
#go get github.com/dotcloud/docker/utils
|
||||||
#go get github.com/dotcloud/docker/pkg/term
|
#go get github.com/dotcloud/docker/pkg/term
|
||||||
|
@ -48,6 +49,7 @@ test:
|
||||||
go test -v github.com/drone/drone/pkg/database/testing
|
go test -v github.com/drone/drone/pkg/database/testing
|
||||||
go test -v github.com/drone/drone/pkg/mail
|
go test -v github.com/drone/drone/pkg/mail
|
||||||
go test -v github.com/drone/drone/pkg/model
|
go test -v github.com/drone/drone/pkg/model
|
||||||
|
go test -v github.com/drone/drone/pkg/plugin/deploy
|
||||||
go test -v github.com/drone/drone/pkg/queue
|
go test -v github.com/drone/drone/pkg/queue
|
||||||
|
|
||||||
install:
|
install:
|
||||||
|
|
|
@ -33,7 +33,7 @@ WHERE user_id = ? AND team_id = ?
|
||||||
|
|
||||||
// SQL Queries to retrieve a member's role by id and user.
|
// SQL Queries to retrieve a member's role by id and user.
|
||||||
const roleFindStmt = `
|
const roleFindStmt = `
|
||||||
SELECT role FROM members
|
SELECT id, team_id, user_id, role FROM members
|
||||||
WHERE user_id = ? AND team_id = ?
|
WHERE user_id = ? AND team_id = ?
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,11 @@ func AdminSettingsUpdate(w http.ResponseWriter, r *http.Request, u *User) error
|
||||||
|
|
||||||
settings.OpenInvitations = (r.FormValue("OpenInvitations") == "on")
|
settings.OpenInvitations = (r.FormValue("OpenInvitations") == "on")
|
||||||
|
|
||||||
|
// validate user input
|
||||||
|
if err := settings.Validate(); err != nil {
|
||||||
|
return RenderError(w, err, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
// persist changes
|
// persist changes
|
||||||
if err := database.SaveSettings(settings); err != nil {
|
if err := database.SaveSettings(settings); err != nil {
|
||||||
return RenderError(w, err, http.StatusBadRequest)
|
return RenderError(w, err, http.StatusBadRequest)
|
||||||
|
@ -245,8 +250,8 @@ func InstallPost(w http.ResponseWriter, r *http.Request) error {
|
||||||
settings := Settings{}
|
settings := Settings{}
|
||||||
settings.Domain = r.FormValue("Domain")
|
settings.Domain = r.FormValue("Domain")
|
||||||
settings.Scheme = r.FormValue("Scheme")
|
settings.Scheme = r.FormValue("Scheme")
|
||||||
settings.GitHubApiUrl = "https://api.github.com";
|
settings.GitHubApiUrl = "https://api.github.com"
|
||||||
settings.GitHubDomain = "github.com";
|
settings.GitHubDomain = "github.com"
|
||||||
database.SaveSettings(&settings)
|
database.SaveSettings(&settings)
|
||||||
|
|
||||||
// add the user to the session object
|
// add the user to the session object
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/pkg/database"
|
"github.com/drone/drone/pkg/database"
|
||||||
|
@ -67,6 +68,7 @@ func LinkGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
||||||
// exchange code for an auth token
|
// exchange code for an auth token
|
||||||
token, err := oauth.GrantToken(code)
|
token, err := oauth.GrantToken(code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Println("Error granting GitHub authorization token")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +79,7 @@ func LinkGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
||||||
// get the user information
|
// get the user information
|
||||||
githubUser, err := client.Users.Current()
|
githubUser, err := client.Users.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Println("Error retrieving currently authenticated GitHub user")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +87,7 @@ func LinkGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
||||||
u.GithubToken = token.AccessToken
|
u.GithubToken = token.AccessToken
|
||||||
u.GithubLogin = githubUser.Login
|
u.GithubLogin = githubUser.Login
|
||||||
if err := database.SaveUser(u); err != nil {
|
if err := database.SaveUser(u); err != nil {
|
||||||
|
log.Println("Error persisting user's GitHub auth token to the database")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,8 @@ func CommitShow(w http.ResponseWriter, r *http.Request, u *User, repo *Repo) err
|
||||||
|
|
||||||
// generate a token to connect with the websocket
|
// generate a token to connect with the websocket
|
||||||
// handler and stream output, if the build is running.
|
// handler and stream output, if the build is running.
|
||||||
data.Token = channel.CreateStream(fmt.Sprintf(
|
data.Token = channel.Token(fmt.Sprintf(
|
||||||
"%s/commit/%s/builds/%s", repo.Slug, commit.Hash, builds[0].Slug))
|
"%s/%s/%s/commit/%s/builds/%s", repo.Host, repo.Owner, repo.Name, commit.Hash, builds[0].Slug))
|
||||||
|
|
||||||
// render the repository template.
|
// render the repository template.
|
||||||
return RenderTemplate(w, "repo_commit.html", &data)
|
return RenderTemplate(w, "repo_commit.html", &data)
|
||||||
|
|
|
@ -125,7 +125,7 @@ func RepoCreateGithub(w http.ResponseWriter, r *http.Request, u *User) error {
|
||||||
// create the github key, or update if one already exists
|
// create the github key, or update if one already exists
|
||||||
_, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName)
|
_, err := client.RepoKeys.CreateUpdate(owner, name, repo.PublicKey, keyName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Unable to add Private Key to your GitHub repository")
|
return fmt.Errorf("Unable to add Public Key to your GitHub repository")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidGitHubTrailingSlash = errors.New("GitHub URL should not have a trailing slash")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Settings struct {
|
type Settings struct {
|
||||||
|
@ -38,3 +44,13 @@ func (s *Settings) URL() *url.URL {
|
||||||
Scheme: s.Scheme,
|
Scheme: s.Scheme,
|
||||||
Host: s.Domain}
|
Host: s.Domain}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate verifies all required fields are correctly populated.
|
||||||
|
func (s *Settings) Validate() error {
|
||||||
|
switch {
|
||||||
|
case strings.HasSuffix(s.GitHubApiUrl, "/"):
|
||||||
|
return ErrInvalidGitHubTrailingSlash
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,8 +14,10 @@ type Deploy struct {
|
||||||
EngineYard *EngineYard `yaml:"engineyard,omitempty"`
|
EngineYard *EngineYard `yaml:"engineyard,omitempty"`
|
||||||
Git *Git `yaml:"git,omitempty"`
|
Git *Git `yaml:"git,omitempty"`
|
||||||
Heroku *Heroku `yaml:"heroku,omitempty"`
|
Heroku *Heroku `yaml:"heroku,omitempty"`
|
||||||
|
Modulus *Modulus `yaml:"modulus,omitempty"`
|
||||||
Nodejitsu *Nodejitsu `yaml:"nodejitsu,omitempty"`
|
Nodejitsu *Nodejitsu `yaml:"nodejitsu,omitempty"`
|
||||||
Openshift *Openshift `yaml:"openshift,omitempty"`
|
Openshift *Openshift `yaml:"openshift,omitempty"`
|
||||||
|
SSH *SSH `yaml:"ssh,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deploy) Write(f *buildfile.Buildfile) {
|
func (d *Deploy) Write(f *buildfile.Buildfile) {
|
||||||
|
@ -37,10 +39,16 @@ func (d *Deploy) Write(f *buildfile.Buildfile) {
|
||||||
if d.Heroku != nil {
|
if d.Heroku != nil {
|
||||||
d.Heroku.Write(f)
|
d.Heroku.Write(f)
|
||||||
}
|
}
|
||||||
|
if d.Modulus != nil {
|
||||||
|
d.Modulus.Write(f)
|
||||||
|
}
|
||||||
if d.Nodejitsu != nil {
|
if d.Nodejitsu != nil {
|
||||||
d.Nodejitsu.Write(f)
|
d.Nodejitsu.Write(f)
|
||||||
}
|
}
|
||||||
if d.Openshift != nil {
|
if d.Openshift != nil {
|
||||||
d.Openshift.Write(f)
|
d.Openshift.Write(f)
|
||||||
}
|
}
|
||||||
|
if d.SSH != nil {
|
||||||
|
d.SSH.Write(f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
21
pkg/plugin/deploy/modulus.go
Normal file
21
pkg/plugin/deploy/modulus.go
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
package deploy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/drone/drone/pkg/build/buildfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Modulus struct {
|
||||||
|
Project string `yaml:"project,omitempty"`
|
||||||
|
Token string `yaml:"token,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Modulus) Write(f *buildfile.Buildfile) {
|
||||||
|
f.WriteEnv("MODULUS_TOKEN", m.Token)
|
||||||
|
|
||||||
|
// Install the Modulus command line interface then deploy the configured
|
||||||
|
// project.
|
||||||
|
f.WriteCmdSilent("[ -f /usr/bin/sudo ] || npm install -g modulus")
|
||||||
|
f.WriteCmdSilent("[ -f /usr/bin/sudo ] && sudo npm install -g modulus")
|
||||||
|
f.WriteCmd(fmt.Sprintf("modulus deploy -p '%s'", m.Project))
|
||||||
|
}
|
|
@ -1 +1,96 @@
|
||||||
package deploy
|
package deploy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/drone/drone/pkg/build/buildfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SSH struct holds configuration data for deployment
|
||||||
|
// via ssh, deployment done by scp-ing file(s) listed
|
||||||
|
// in artifacts to the target host, and then run cmd
|
||||||
|
// remotely.
|
||||||
|
// It is assumed that the target host already
|
||||||
|
// add this repo public key in the host's `authorized_hosts`
|
||||||
|
// file. And the private key is already copied to `.ssh/id_rsa`
|
||||||
|
// inside the build container. No further check will be done.
|
||||||
|
type SSH struct {
|
||||||
|
|
||||||
|
// Target is the deployment host in this format
|
||||||
|
// user@hostname:/full/path <PORT>
|
||||||
|
//
|
||||||
|
// PORT may be omitted if its default to port 22.
|
||||||
|
Target string `yaml:"target,omitempty"`
|
||||||
|
|
||||||
|
// Artifacts is a list of files/dirs to be deployed
|
||||||
|
// to the target host. If artifacts list more than one file
|
||||||
|
// it will be compressed into a single tar.gz file.
|
||||||
|
// if artifacts contain:
|
||||||
|
// - GITARCHIVE
|
||||||
|
//
|
||||||
|
// other file listed in artifacts will be ignored, instead, we will
|
||||||
|
// create git archive from the current revision and deploy that file
|
||||||
|
// alone.
|
||||||
|
// If you need to deploy the git archive along with some other files,
|
||||||
|
// please use build script to create the git archive, and then list
|
||||||
|
// the archive name here with the other files.
|
||||||
|
Artifacts []string `yaml:"artifacts,omitempty"`
|
||||||
|
|
||||||
|
// Cmd is a single command executed at target host after the artifacts
|
||||||
|
// is deployed.
|
||||||
|
Cmd string `yaml:"cmd,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write down the buildfile
|
||||||
|
func (s *SSH) Write(f *buildfile.Buildfile) {
|
||||||
|
host := strings.SplitN(s.Target, " ", 2)
|
||||||
|
if len(host) == 1 {
|
||||||
|
host = append(host, "22")
|
||||||
|
}
|
||||||
|
if _, err := strconv.Atoi(host[1]); err != nil {
|
||||||
|
host[1] = "22"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is artifact created?
|
||||||
|
artifact := false
|
||||||
|
|
||||||
|
for _, a := range s.Artifacts {
|
||||||
|
if a == "GITARCHIVE" {
|
||||||
|
artifact = createGitArchive(f)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.Artifacts) > 1 && !artifact {
|
||||||
|
artifact = compress(f, s.Artifacts)
|
||||||
|
} else if len(s.Artifacts) == 1 {
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf("ARTIFACT=%s", s.Artifacts[0]))
|
||||||
|
artifact = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if artifact {
|
||||||
|
scpCmd := "scp -o StrictHostKeyChecking=no -P %s ${ARTIFACT} %s"
|
||||||
|
f.WriteCmd(fmt.Sprintf(scpCmd, host[1], host[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.Cmd) > 0 {
|
||||||
|
sshCmd := "ssh -o StrictHostKeyChecking=no -p %s %s %s"
|
||||||
|
f.WriteCmd(fmt.Sprintf(sshCmd, host[1], strings.SplitN(host[0], ":", 2)[0], s.Cmd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createGitArchive(f *buildfile.Buildfile) bool {
|
||||||
|
f.WriteCmdSilent("COMMIT=$(git rev-parse HEAD)")
|
||||||
|
f.WriteCmdSilent("ARTIFACT=${PWD##*/}-${COMMIT}.tar.gz")
|
||||||
|
f.WriteCmdSilent("git archive --format=tar.gz --prefix=${PWD##*/}/ ${COMMIT} > ${ARTIFACT}")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func compress(f *buildfile.Buildfile, files []string) bool {
|
||||||
|
cmd := "tar -cf ${ARTIFACT} %s"
|
||||||
|
f.WriteCmdSilent("ARTIFACT=${PWD##*/}.tar.gz")
|
||||||
|
f.WriteCmdSilent(fmt.Sprintf(cmd, strings.Join(files, " ")))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
125
pkg/plugin/deploy/ssh_test.go
Normal file
125
pkg/plugin/deploy/ssh_test.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package deploy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/drone/drone/pkg/build/buildfile"
|
||||||
|
|
||||||
|
"launchpad.net/goyaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// emulate Build struct
|
||||||
|
type build struct {
|
||||||
|
Deploy *Deploy `yaml:"deploy,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleYml = `
|
||||||
|
deploy:
|
||||||
|
ssh:
|
||||||
|
target: user@test.example.com
|
||||||
|
cmd: /opt/bin/redeploy.sh
|
||||||
|
`
|
||||||
|
|
||||||
|
var sampleYml1 = `
|
||||||
|
deploy:
|
||||||
|
ssh:
|
||||||
|
target: user@test.example.com:/srv/app/location 2212
|
||||||
|
artifacts:
|
||||||
|
- build.result
|
||||||
|
cmd: /opt/bin/redeploy.sh
|
||||||
|
`
|
||||||
|
|
||||||
|
var sampleYml2 = `
|
||||||
|
deploy:
|
||||||
|
ssh:
|
||||||
|
target: user@test.example.com:/srv/app/location 2212
|
||||||
|
artifacts:
|
||||||
|
- build.result
|
||||||
|
- config/file
|
||||||
|
cmd: /opt/bin/redeploy.sh
|
||||||
|
`
|
||||||
|
|
||||||
|
var sampleYml3 = `
|
||||||
|
deploy:
|
||||||
|
ssh:
|
||||||
|
target: user@test.example.com:/srv/app/location 2212
|
||||||
|
artifacts:
|
||||||
|
- GITARCHIVE
|
||||||
|
cmd: /opt/bin/redeploy.sh
|
||||||
|
`
|
||||||
|
|
||||||
|
func setUp(input string) (string, error) {
|
||||||
|
var buildStruct build
|
||||||
|
err := goyaml.Unmarshal([]byte(input), &buildStruct)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
bf := buildfile.New()
|
||||||
|
buildStruct.Deploy.Write(bf)
|
||||||
|
return bf.String(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHNoArtifact(t *testing.T) {
|
||||||
|
bscr, err := setUp(sampleYml)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't unmarshal deploy script: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(bscr, `scp`) {
|
||||||
|
t.Error("Expect script not to contains scp command")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "ssh -o StrictHostKeyChecking=no -p 22 user@test.example.com /opt/bin/redeploy.sh") {
|
||||||
|
t.Error("Expect script to contains ssh command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHOneArtifact(t *testing.T) {
|
||||||
|
bscr, err := setUp(sampleYml1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't unmarshal deploy script: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "ARTIFACT=build.result") {
|
||||||
|
t.Errorf("Expect script to contains artifact")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "scp -o StrictHostKeyChecking=no -P 2212 ${ARTIFACT} user@test.example.com:/srv/app/location") {
|
||||||
|
t.Errorf("Expect script to contains scp command, got:\n%s", bscr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHMultiArtifact(t *testing.T) {
|
||||||
|
bscr, err := setUp(sampleYml2)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't unmarshal deploy script: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "ARTIFACT=${PWD##*/}.tar.gz") {
|
||||||
|
t.Errorf("Expect script to contains artifact")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "tar -cf ${ARTIFACT} build.result config/file") {
|
||||||
|
t.Errorf("Expect script to contains tar command. got:\n", bscr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHGitArchive(t *testing.T) {
|
||||||
|
bscr, err := setUp(sampleYml3)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Can't unmarshal deploy script: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "COMMIT=$(git rev-parse HEAD)") {
|
||||||
|
t.Errorf("Expect script to contains commit ref")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "ARTIFACT=${PWD##*/}-${COMMIT}.tar.gz") {
|
||||||
|
t.Errorf("Expect script to contains artifact")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(bscr, "git archive --format=tar.gz --prefix=${PWD##*/}/ ${COMMIT} > ${ARTIFACT}") {
|
||||||
|
t.Errorf("Expect script to run git archive")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,80 @@
|
||||||
package notify
|
package notify
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
irc "github.com/fluffle/goirc/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ircStartedMessage = "Building: %s, commit %s, author %s"
|
||||||
|
ircSuccessMessage = "Success: %s, commit %s, author %s"
|
||||||
|
ircFailureMessage = "Failed: %s, commit %s, author %s"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IRC struct {
|
||||||
|
Channel string `yaml:"channel,omitempty"`
|
||||||
|
Nick string `yaml:"nick,omitempty"`
|
||||||
|
Server string `yaml:"server,omitempty"`
|
||||||
|
Started bool `yaml:"on_started,omitempty"`
|
||||||
|
Success bool `yaml:"on_success,omitempty"`
|
||||||
|
Failure bool `yaml:"on_failure,omitempty"`
|
||||||
|
SSL bool `yaml:"ssl,omitempty"`
|
||||||
|
ClientStarted bool
|
||||||
|
Client *irc.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRC) Connect() {
|
||||||
|
c := irc.SimpleClient(i.Nick)
|
||||||
|
c.SSL = i.SSL
|
||||||
|
connected := make(chan bool)
|
||||||
|
c.AddHandler(irc.CONNECTED,
|
||||||
|
func(conn *irc.Conn, line *irc.Line) {
|
||||||
|
conn.Join(i.Channel)
|
||||||
|
connected <- true})
|
||||||
|
c.Connect(i.Server)
|
||||||
|
<-connected
|
||||||
|
i.Client = c
|
||||||
|
i.ClientStarted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRC) Send(context *Context) error {
|
||||||
|
|
||||||
|
if !i.ClientStarted {
|
||||||
|
i.Connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case context.Commit.Status == "Started" && i.Started:
|
||||||
|
return i.sendStarted(context)
|
||||||
|
case context.Commit.Status == "Success" && i.Success:
|
||||||
|
return i.sendSuccess(context)
|
||||||
|
case context.Commit.Status == "Failure" && i.Failure:
|
||||||
|
return i.sendFailure(context)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRC) sendStarted(context *Context) error {
|
||||||
|
msg := fmt.Sprintf(ircStartedMessage, context.Repo.Name, context.Commit.HashShort(), context.Commit.Author)
|
||||||
|
i.send(i.Channel, msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRC) sendFailure(context *Context) error {
|
||||||
|
msg := fmt.Sprintf(ircFailureMessage, context.Repo.Name, context.Commit.HashShort(), context.Commit.Author)
|
||||||
|
i.send(i.Channel, msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *IRC) sendSuccess(context *Context) error {
|
||||||
|
msg := fmt.Sprintf(ircSuccessMessage, context.Repo.Name, context.Commit.HashShort(), context.Commit.Author)
|
||||||
|
i.send(i.Channel, msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (i *IRC) send(channel string, message string) error {
|
||||||
|
i.Client.Notice(channel, message)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ type Notification struct {
|
||||||
Email *Email `yaml:"email,omitempty"`
|
Email *Email `yaml:"email,omitempty"`
|
||||||
Webhook *Webhook `yaml:"webhook,omitempty"`
|
Webhook *Webhook `yaml:"webhook,omitempty"`
|
||||||
Hipchat *Hipchat `yaml:"hipchat,omitempty"`
|
Hipchat *Hipchat `yaml:"hipchat,omitempty"`
|
||||||
|
Irc *IRC `yaml:"irc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notification) Send(context *Context) error {
|
func (n *Notification) Send(context *Context) error {
|
||||||
|
@ -49,5 +50,10 @@ func (n *Notification) Send(context *Context) error {
|
||||||
n.Hipchat.Send(context)
|
n.Hipchat.Send(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send irc notifications
|
||||||
|
if n.Irc != nil {
|
||||||
|
n.Irc.Send(context)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<div class="col-xs-9" role="main" style="padding-left:20px;">
|
<div class="col-xs-9" role="main" style="padding-left:20px;">
|
||||||
<div class="alert">Users will be granted access by Email invitation.</div>
|
<div class="alert">Users will be granted access by Email invitation.</div>
|
||||||
|
|
||||||
<div class="col-xs-5">
|
<div class="row">
|
||||||
<form action="/account/admin/users" method="POST" role="form">
|
<form action="/account/admin/users" method="POST" role="form">
|
||||||
<label>Email Address:</label>
|
<label>Email Address:</label>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<div class="col-xs-9" role="main" style="padding-left:20px;">
|
<div class="col-xs-9" role="main" style="padding-left:20px;">
|
||||||
<div class="alert">Invite a collaborator to join your Team.</div>
|
<div class="alert">Invite a collaborator to join your Team.</div>
|
||||||
|
|
||||||
<div class="col-xs-5">
|
<div class="row">
|
||||||
<form action="/account/team/{{.Team.Slug}}/members/add" method="POST" role="form">
|
<form action="/account/team/{{.Team.Slug}}/members/add" method="POST" role="form">
|
||||||
<label>Email Address:</label>
|
<label>Email Address:</label>
|
||||||
<div>
|
<div>
|
||||||
|
|
Loading…
Reference in a new issue