diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e4f9bec --- /dev/null +++ b/.editorconfig @@ -0,0 +1,42 @@ +# unifying the coding style for different editors and IDEs => editorconfig.org + +; indicate this is the root of the project +root = true + +########################################################### +; common +########################################################### + +[*] +charset = utf-8 + +end_of_line = LF +insert_final_newline = true +trim_trailing_whitespace = true + +indent_style = space +indent_size = 2 + +########################################################### +; make +########################################################### + +[Makefile] +indent_style = tab + +[makefile] +indent_style = tab + +########################################################### +; markdown +########################################################### + +[*.md] +trim_trailing_whitespace = false + +########################################################### +; golang +########################################################### + +[*.go] +indent_style = tab \ No newline at end of file diff --git a/.gitignore b/.gitignore index daf913b..d713321 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ _testmain.go *.exe *.test *.prof +vendor +drone-jenkins +coverage.txt diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f13c145 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,53 @@ +sudo: required +language: go + +services: + - docker + +go: + - 1.5.4 + - 1.6.3 + - 1.7.1 + - tip + +env: + global: + - DOCKER_CACHE_FILE=${HOME}/docker/cache.tar.gz + +cache: + directories: + - vendor + - ${HOME}/.glide + - ${HOME}/docker + +before_install: + - mkdir -p $GOPATH/bin + - curl https://glide.sh/get | sh + - if [ -f ${DOCKER_CACHE_FILE} ]; then gunzip -c ${DOCKER_CACHE_FILE} | docker load; fi + +install: + - export GO15VENDOREXPERIMENT=1 + - make install + +script: + - make test + - make docker + - if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + mkdir -p $(dirname ${DOCKER_CACHE_FILE}); + docker save $(docker history -q $TRAVIS_REPO_SLUG:latest | grep -v '') | gzip > ${DOCKER_CACHE_FILE}; + fi + +after_success: + # ignore main.go coverage + - sed -i '/main.go/d' coverage.txt + - bash <(curl -s https://codecov.io/bash) -f coverage.txt + # deploy from master + - if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_GO_VERSION" == "1.7.1" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; + make docker_deploy tag=latest; + fi + # deploy from tag + - if [ "$TRAVIS_GO_VERSION" == "1.7.1" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_TAG" != "" ]; then + docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; + make docker_deploy tag=$TRAVIS_TAG; + fi diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e672e29 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM centurylink/ca-certs + +ADD drone-sftp / + +ENTRYPOINT ["/drone-sftp"] diff --git a/Dockerfile.armhf b/Dockerfile.armhf new file mode 100644 index 0000000..2ebc614 --- /dev/null +++ b/Dockerfile.armhf @@ -0,0 +1,8 @@ +FROM armhfbuild/alpine:3.4 + +RUN apk update && \ + apk add ca-certificates && \ + rm -rf /var/cache/apk/* + +ADD drone-telegram /bin/ +ENTRYPOINT ["/bin/drone-telegram"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3b74c18 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +.PHONY: install build test html update docker_build docker_image docker docker_deploy clean + +VERSION := $(shell git describe --tags || git rev-parse --short HEAD) +DEPLOY_ACCOUNT := "appleboy" +DEPLOY_IMAGE := "drone-sftp" + +ifneq ($(shell uname), Darwin) + EXTLDFLAGS = -extldflags "-static" $(null) +else + EXTLDFLAGS = +endif + +install: + glide install + +build: + go build -ldflags="$(EXTLDFLAGS)-s -w -X main.Version=$(VERSION)" + +test: + go test -v -coverprofile=coverage.txt + +html: + go tool cover -html=coverage.txt + +update: + glide up + +docker_build: + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags="-X main.Version=$(VERSION)" + +docker_image: + docker build --rm -t $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE) . + +docker: docker_build docker_image + +docker_deploy: +ifeq ($(tag),) + @echo "Usage: make $@ tag=" + @exit 1 +endif + docker tag $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):latest $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag) + docker push $(DEPLOY_ACCOUNT)/$(DEPLOY_IMAGE):$(tag) + +clean: + rm -rf coverage.txt ${DEPLOY_IMAGE} diff --git a/README.md b/README.md index 740e5ee..5452a97 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,60 @@ -# drone-sftp -Drone plugin for uploading files to an SFTP server +# drone-jenkins + +[![Build Status](https://travis-ci.org/appleboy/drone-jenkins.svg?branch=master)](https://travis-ci.org/appleboy/drone-jenkins) [![codecov](https://codecov.io/gh/appleboy/drone-jenkins/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-jenkins) [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-jenkins)](https://goreportcard.com/report/github.com/appleboy/drone-jenkins) + +[Drone](https://github.com/drone/drone) plugin for trigger [Jenkins](https://jenkins.io/) jobs. + +## Build + +Build the binary with the following commands: + +``` +$ make build +``` + +## Testing + +Test the package with the following command: + +``` +$ make test +``` + +## Docker + +Build the docker image with the following commands: + +``` +$ make docker +``` + +Please note incorrectly building the image for the correct x64 linux and with +GCO disabled will result in an error when running the Docker image: + +``` +docker: Error response from daemon: Container command +'/bin/drone-jenkins' not found or does not exist.. +``` + +## Usage + +Execute from the working directory: + +``` +docker run --rm \ + -e PLUGIN_BASE_URL=http://example.com \ + -e PLUGIN_USERNAME=xxxxxxx \ + -e PLUGIN_TOKEN=xxxxxxx \ + -e PLUGIN_JOB=xxxxxxx \ + -e DRONE_REPO_OWNER=appleboy \ + -e DRONE_REPO_NAME=go-hello \ + -e DRONE_COMMIT_SHA=e5e82b5eb3737205c25955dcc3dcacc839b7be52 \ + -e DRONE_COMMIT_BRANCH=master \ + -e DRONE_COMMIT_AUTHOR=appleboy \ + -e DRONE_BUILD_NUMBER=1 \ + -e DRONE_BUILD_STATUS=success \ + -e DRONE_BUILD_LINK=http://github.com/appleboy/go-hello \ + -v $(pwd):$(pwd) \ + -w $(pwd) \ + appleboy/drone-jenkins +``` diff --git a/main.go b/main.go new file mode 100644 index 0000000..39b8459 --- /dev/null +++ b/main.go @@ -0,0 +1,128 @@ +package main + +import ( + "os" + + _ "github.com/joho/godotenv/autoload" + "github.com/urfave/cli" +) + +// Version for command line +var Version string + +func main() { + app := cli.NewApp() + app.Name = "telegram plugin" + app.Usage = "telegram plugin" + app.Action = run + app.Version = Version + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "base.url", + Usage: "jenkins base url", + EnvVar: "PLUGIN_BASE_URL,JENKINS_BASE_URL", + }, + cli.StringFlag{ + Name: "username", + Usage: "jenkins username", + EnvVar: "PLUGIN_USERNAME,JENKINS_USERNAME", + }, + cli.StringFlag{ + Name: "token", + Usage: "jenkins token", + EnvVar: "PLUGIN_TOKEN,JENKINS_TOKEN", + }, + cli.StringSliceFlag{ + Name: "job", + Usage: "jenkins job", + EnvVar: "PLUGIN_JOB", + }, + cli.StringFlag{ + Name: "format", + Value: "markdown", + Usage: "telegram message format", + EnvVar: "PLUGIN_FORMAT", + }, + cli.StringFlag{ + Name: "repo.owner", + Usage: "repository owner", + EnvVar: "DRONE_REPO_OWNER", + }, + cli.StringFlag{ + Name: "repo.name", + Usage: "repository name", + EnvVar: "DRONE_REPO_NAME", + }, + cli.StringFlag{ + Name: "commit.sha", + Usage: "git commit sha", + EnvVar: "DRONE_COMMIT_SHA", + }, + cli.StringFlag{ + Name: "commit.branch", + Value: "master", + Usage: "git commit branch", + EnvVar: "DRONE_COMMIT_BRANCH", + }, + cli.StringFlag{ + Name: "commit.author", + Usage: "git author name", + EnvVar: "DRONE_COMMIT_AUTHOR", + }, + cli.StringFlag{ + Name: "commit.message", + Usage: "commit message", + EnvVar: "DRONE_COMMIT_MESSAGE", + }, + cli.StringFlag{ + Name: "build.event", + Value: "push", + Usage: "build event", + EnvVar: "DRONE_BUILD_EVENT", + }, + cli.IntFlag{ + Name: "build.number", + Usage: "build number", + EnvVar: "DRONE_BUILD_NUMBER", + }, + cli.StringFlag{ + Name: "build.status", + Usage: "build status", + Value: "success", + EnvVar: "DRONE_BUILD_STATUS", + }, + cli.StringFlag{ + Name: "build.link", + Usage: "build link", + EnvVar: "DRONE_BUILD_LINK", + }, + } + app.Run(os.Args) +} + +func run(c *cli.Context) error { + plugin := Plugin{ + Repo: Repo{ + Owner: c.String("repo.owner"), + Name: c.String("repo.name"), + }, + Build: Build{ + Number: c.Int("build.number"), + Event: c.String("build.event"), + Status: c.String("build.status"), + Commit: c.String("commit.sha"), + Branch: c.String("commit.branch"), + Author: c.String("commit.author"), + Message: c.String("commit.message"), + Link: c.String("build.link"), + }, + Config: Config{ + BaseURL: c.String("base.url"), + Username: c.String("username"), + Token: c.String("token"), + Job: c.StringSlice("job"), + }, + } + + return plugin.Exec() +} diff --git a/plugin.go b/plugin.go new file mode 100644 index 0000000..56c2eef --- /dev/null +++ b/plugin.go @@ -0,0 +1,78 @@ +package main + +import ( + "errors" + "log" + "strings" +) + +type ( + // Repo information. + Repo struct { + Owner string + Name string + } + + // Build information. + Build struct { + Event string + Number int + Commit string + Message string + Branch string + Author string + Status string + Link string + } + + // Config for the plugin. + Config struct { + BaseURL string + Username string + Token string + Job []string + } + + // Plugin values. + Plugin struct { + Repo Repo + Build Build + Config Config + } +) + +func trimElement(keys []string) []string { + var newKeys []string + + for _, value := range keys { + value = strings.Trim(value, " ") + if len(value) == 0 { + continue + } + newKeys = append(newKeys, value) + } + + return newKeys +} + +// Exec executes the plugin. +func (p Plugin) Exec() error { + + if len(p.Config.BaseURL) == 0 || len(p.Config.Username) == 0 || len(p.Config.Token) == 0 { + log.Println("missing jenkins config") + + return errors.New("missing jenkins config") + } + + auth := &Auth{ + Username: p.Config.Username, + Token: p.Config.Token, + } + jenkins := NewJenkins(auth, p.Config.BaseURL) + + for _, value := range trimElement(p.Config.Job) { + jenkins.trigger(value, nil) + } + + return nil +}