├── .dockerignore ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── codeql.yml │ ├── docker.yml │ ├── goreleaser.yml │ └── lint.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yaml ├── .hadolint.yaml ├── DOCS.md ├── LICENSE ├── Makefile ├── README.md ├── README.zh-cn.md ├── README.zh-tw.md ├── docker └── Dockerfile ├── gitlab.go ├── gitlab_test.go ├── go.mod ├── go.sum ├── images ├── gitlab-logo.svg ├── logo.png ├── projectID.png └── user_token.png ├── main.go ├── plugin.go └── plugin_test.go /.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !release/ 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ["https://www.paypal.me/appleboy46"] 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | - package-ecosystem: gomod 8 | directory: / 9 | schedule: 10 | interval: weekly 11 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [master] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [master] 20 | schedule: 21 | - cron: "41 23 * * 6" 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: ["go"] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | - name: Perform CodeQL Analysis 54 | uses: github/codeql-action/analyze@v3 55 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: Docker Image 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - "v*" 9 | pull_request: 10 | branches: 11 | - "master" 12 | 13 | jobs: 14 | build-docker: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout repository 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Setup go 23 | uses: actions/setup-go@v5 24 | with: 25 | go-version: "^1" 26 | 27 | - name: Build binary 28 | run: | 29 | make build_linux_amd64 30 | make build_linux_arm64 31 | - name: Set up QEMU 32 | uses: docker/setup-qemu-action@v3 33 | 34 | - name: Set up Docker Buildx 35 | uses: docker/setup-buildx-action@v3 36 | 37 | - name: Login to GitHub Container Registry 38 | uses: docker/login-action@v3 39 | with: 40 | registry: ghcr.io 41 | username: ${{ github.repository_owner }} 42 | password: ${{ secrets.GITHUB_TOKEN }} 43 | 44 | - name: Docker meta 45 | id: docker-meta 46 | uses: docker/metadata-action@v5 47 | with: 48 | images: | 49 | ghcr.io/${{ github.repository }} 50 | tags: | 51 | type=raw,value=latest,enable={{is_default_branch}} 52 | type=semver,pattern={{version}} 53 | type=semver,pattern={{major}}.{{minor}} 54 | type=semver,pattern={{major}} 55 | 56 | - name: Build and push 57 | uses: docker/build-push-action@v6 58 | with: 59 | context: . 60 | platforms: linux/amd64,linux/arm64 61 | file: docker/Dockerfile 62 | push: ${{ github.event_name != 'pull_request' }} 63 | tags: ${{ steps.docker-meta.outputs.tags }} 64 | labels: ${{ steps.docker-meta.outputs.labels }} 65 | -------------------------------------------------------------------------------- /.github/workflows/goreleaser.yml: -------------------------------------------------------------------------------- 1 | name: Goreleaser 2 | 3 | on: 4 | push: 5 | tags: 6 | - "*" 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | goreleaser: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Setup go 21 | uses: actions/setup-go@v5 22 | with: 23 | go-version: "^1" 24 | 25 | - name: Run GoReleaser 26 | uses: goreleaser/goreleaser-action@v6 27 | with: 28 | # either 'goreleaser' (default) or 'goreleaser-pro' 29 | distribution: goreleaser 30 | version: latest 31 | args: release --clean 32 | env: 33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 34 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint and Testing 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout repository 12 | uses: actions/checkout@v4 13 | 14 | - name: Setup go 15 | uses: actions/setup-go@v5 16 | with: 17 | go-version: "^1" 18 | 19 | - name: Setup golangci-lint 20 | uses: golangci/golangci-lint-action@v6 21 | with: 22 | version: latest 23 | args: --verbose 24 | 25 | - uses: hadolint/hadolint-action@v3.1.0 26 | name: hadolint for Dockerfile 27 | with: 28 | dockerfile: docker/Dockerfile 29 | 30 | test: 31 | strategy: 32 | matrix: 33 | os: [ubuntu-latest] 34 | go: [1.21, 1.22, 1.23] 35 | include: 36 | - os: ubuntu-latest 37 | go-build: ~/.cache/go-build 38 | name: ${{ matrix.os }} @ Go ${{ matrix.go }} 39 | runs-on: ${{ matrix.os }} 40 | env: 41 | GO111MODULE: on 42 | GOPROXY: https://proxy.golang.org 43 | steps: 44 | - name: Set up Go ${{ matrix.go }} 45 | uses: actions/setup-go@v5 46 | with: 47 | go-version: ${{ matrix.go }} 48 | 49 | - name: Checkout Code 50 | uses: actions/checkout@v4 51 | with: 52 | ref: ${{ github.ref }} 53 | 54 | - uses: actions/cache@v4 55 | with: 56 | path: | 57 | ${{ matrix.go-build }} 58 | ~/go/pkg/mod 59 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 60 | restore-keys: | 61 | ${{ runner.os }}-go- 62 | - name: Run Tests 63 | run: | 64 | make test 65 | 66 | - name: Upload coverage to Codecov 67 | uses: codecov/codecov-action@v5 68 | with: 69 | flags: ${{ matrix.os }},go-${{ matrix.go }} 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | drone-gitlab-ci 17 | coverage.txt 18 | .env 19 | dist 20 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 5m 3 | linters: 4 | enable: 5 | - asciicheck 6 | - dogsled 7 | - durationcheck 8 | - errcheck 9 | - errorlint 10 | - exportloopref 11 | - gci 12 | - gofmt 13 | - goimports 14 | - gosec 15 | - misspell 16 | - nakedret 17 | - nilerr 18 | - perfsprint 19 | - revive 20 | - testifylint 21 | - usestdlibvars 22 | - wastedassign 23 | 24 | linters-settings: 25 | gosec: 26 | # To select a subset of rules to run. 27 | # Available rules: https://github.com/securego/gosec#available-rules 28 | # Default: [] - means include all rules 29 | includes: [] 30 | # To exclude a subset of rules from running. 31 | # Default: [] - means exclude no rules 32 | excludes: 33 | - G402 34 | perfsprint: 35 | err-error: true 36 | errorf: true 37 | int-conversion: true 38 | sprintf1: true 39 | strconcat: true 40 | testifylint: 41 | enable-all: true 42 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod tidy 4 | 5 | builds: 6 | - env: 7 | - CGO_ENABLED=0 8 | goos: 9 | - darwin 10 | - linux 11 | - windows 12 | - freebsd 13 | goarch: 14 | - amd64 15 | - arm 16 | - arm64 17 | goarm: 18 | - "5" 19 | - "6" 20 | - "7" 21 | ignore: 22 | - goos: darwin 23 | goarch: arm 24 | - goos: darwin 25 | goarch: ppc64le 26 | - goos: darwin 27 | goarch: s390x 28 | - goos: windows 29 | goarch: ppc64le 30 | - goos: windows 31 | goarch: s390x 32 | - goos: windows 33 | goarch: arm 34 | goarm: "5" 35 | - goos: windows 36 | goarch: arm 37 | goarm: "6" 38 | - goos: windows 39 | goarch: arm 40 | goarm: "7" 41 | - goos: windows 42 | goarch: arm64 43 | - goos: freebsd 44 | goarch: ppc64le 45 | - goos: freebsd 46 | goarch: s390x 47 | - goos: freebsd 48 | goarch: arm 49 | goarm: "5" 50 | - goos: freebsd 51 | goarch: arm 52 | goarm: "6" 53 | - goos: freebsd 54 | goarch: arm 55 | goarm: "7" 56 | - goos: freebsd 57 | goarch: arm64 58 | flags: 59 | - -trimpath 60 | ldflags: 61 | - -s -w 62 | - -X main.Version={{.Version}} 63 | binary: >- 64 | {{ .ProjectName }}- 65 | {{- if .IsSnapshot }}{{ .Branch }}- 66 | {{- else }}{{- .Version }}-{{ end }} 67 | {{- .Os }}- 68 | {{- if eq .Arch "amd64" }}amd64 69 | {{- else if eq .Arch "amd64_v1" }}amd64 70 | {{- else if eq .Arch "386" }}386 71 | {{- else }}{{ .Arch }}{{ end }} 72 | {{- if .Arm }}-{{ .Arm }}{{ end }} 73 | no_unique_dist_dir: true 74 | hooks: 75 | post: 76 | - cmd: xz -k -9 {{ .Path }} 77 | dir: ./dist/ 78 | 79 | archives: 80 | - format: binary 81 | name_template: "{{ .Binary }}" 82 | allow_different_binary_count: true 83 | 84 | checksum: 85 | name_template: "checksums.txt" 86 | extra_files: 87 | - glob: ./**.xz 88 | 89 | snapshot: 90 | version_template: "{{ incpatch .Version }}" 91 | 92 | release: 93 | # You can add extra pre-existing files to the release. 94 | # The filename on the release will be the last part of the path (base). 95 | # If another file with the same name exists, the last one found will be used. 96 | # 97 | # Templates: allowed 98 | extra_files: 99 | - glob: ./**.xz 100 | 101 | changelog: 102 | use: github 103 | groups: 104 | - title: Features 105 | regexp: "^.*feat[(\\w)]*:+.*$" 106 | order: 0 107 | - title: "Bug fixes" 108 | regexp: "^.*fix[(\\w)]*:+.*$" 109 | order: 1 110 | - title: "Enhancements" 111 | regexp: "^.*chore[(\\w)]*:+.*$" 112 | order: 2 113 | - title: "Refactor" 114 | regexp: "^.*refactor[(\\w)]*:+.*$" 115 | order: 3 116 | - title: "Build process updates" 117 | regexp: ^.*?(build|ci)(\(.+\))??!?:.+$ 118 | order: 4 119 | - title: "Documentation updates" 120 | regexp: ^.*?docs?(\(.+\))??!?:.+$ 121 | order: 4 122 | - title: Others 123 | order: 999 124 | -------------------------------------------------------------------------------- /.hadolint.yaml: -------------------------------------------------------------------------------- 1 | ignored: 2 | - DL3018 3 | - DL3008 4 | -------------------------------------------------------------------------------- /DOCS.md: -------------------------------------------------------------------------------- 1 | --- 2 | date: 2019-19-19T00:00:00+00:00 3 | title: Gitlab-CI 4 | author: appleboy 5 | tags: [ infrastructure, trigger, gitlab, gitlab-ci ] 6 | repo: appleboy/drone-gitlab-ci 7 | logo: gitlab-ci.svg 8 | image: appleboy/drone-gitlab-ci 9 | --- 10 | 11 | The Gitlab-ci plugin allows you to trigger Gitlab-ci job automatically. The below pipeline configuration demonstrates simple usage: 12 | 13 | ```yaml 14 | - name: trigger gitlab job 15 | image: appleboy/drone-gitlab-ci 16 | settings: 17 | host: https://gitlab.com 18 | token: xxxxxxxxxx 19 | ref: master 20 | id: gitlab-project-id 21 | ``` 22 | 23 | Example configuration with debug mode: 24 | 25 | ```diff 26 | - name: trigger gitlab job 27 | image: appleboy/drone-gitlab-ci 28 | settings: 29 | host: https://gitlab.com 30 | token: xxxxxxxxxx 31 | ref: master 32 | id: gitlab-project-id 33 | + debug: true 34 | ``` 35 | 36 | Example configuration using credentials from secrets: 37 | 38 | ```diff 39 | - name: trigger gitlab job 40 | image: appleboy/drone-gitlab-ci 41 | settings: 42 | host: https://gitlab.com 43 | + token: 44 | + from_secret: gitlab_token 45 | id: gitlab-project-id 46 | ``` 47 | 48 | ## Parameter Reference 49 | 50 | host 51 | : gitlab-ci server base url. 52 | 53 | token 54 | : gitlab-ci user token 55 | 56 | ref 57 | : valid refs are only the branches and tags 58 | 59 | id 60 | : gitlab-ci project id 61 | 62 | debug 63 | : enable debug mode 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Bo-Yi Wu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DIST := dist 2 | EXECUTABLE := drone-gitlab-ci 3 | GOFMT ?= gofumpt -l -s -w 4 | GO ?= go 5 | GOFILES := $(shell find . -name "*.go" -type f) 6 | HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" ) 7 | 8 | ifneq ($(shell uname), Darwin) 9 | EXTLDFLAGS = -extldflags "-static" $(null) 10 | else 11 | EXTLDFLAGS = 12 | endif 13 | 14 | ifeq ($(HAS_GO), GO) 15 | GOPATH ?= $(shell $(GO) env GOPATH) 16 | export PATH := $(GOPATH)/bin:$(PATH) 17 | 18 | CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766 19 | CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS) 20 | endif 21 | 22 | ifeq ($(OS), Windows_NT) 23 | GOFLAGS := -v -buildmode=exe 24 | EXECUTABLE ?= $(EXECUTABLE).exe 25 | else ifeq ($(OS), Windows) 26 | GOFLAGS := -v -buildmode=exe 27 | EXECUTABLE ?= $(EXECUTABLE).exe 28 | else 29 | GOFLAGS := -v 30 | EXECUTABLE ?= $(EXECUTABLE) 31 | endif 32 | 33 | ifneq ($(DRONE_TAG),) 34 | VERSION ?= $(DRONE_TAG) 35 | else 36 | VERSION ?= $(shell git describe --tags --always || git rev-parse --short HEAD) 37 | endif 38 | 39 | TAGS ?= 40 | LDFLAGS ?= -X 'main.Version=$(VERSION)' 41 | 42 | all: build 43 | 44 | test: 45 | @$(GO) test -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1 46 | 47 | install: $(GOFILES) 48 | $(GO) install -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' 49 | 50 | build: $(EXECUTABLE) 51 | 52 | $(EXECUTABLE): $(GOFILES) 53 | $(GO) build -v -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o bin/$@ 54 | 55 | build_linux_amd64: 56 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/amd64/$(DEPLOY_IMAGE) 57 | 58 | build_linux_arm64: 59 | CGO_ENABLED=0 GOOS=linux GOARCH=arm64 $(GO) build -a -tags '$(TAGS)' -ldflags '$(EXTLDFLAGS)-s -w $(LDFLAGS)' -o release/linux/arm64/$(DEPLOY_IMAGE) 60 | 61 | clean: 62 | $(GO) clean -x -i ./... 63 | rm -rf coverage.txt $(EXECUTABLE) 64 | 65 | version: 66 | @echo $(VERSION) 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # drone-gitlab-ci 2 | 3 | ![logo](./images/logo.png) 4 | 5 | [繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md) | [English](./README.md) 6 | 7 | [![Lint and Testing](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml/badge.svg)](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml) 8 | [![GoDoc](https://godoc.org/github.com/appleboy/drone-gitlab-ci?status.svg)](https://godoc.org/github.com/appleboy/drone-gitlab-ci) 9 | [![codecov](https://codecov.io/gh/appleboy/drone-gitlab-ci/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-gitlab-ci) 10 | [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-gitlab-ci)](https://goreportcard.com/report/github.com/appleboy/drone-gitlab-ci) 11 | 12 | [Drone](https://www.drone.io/) plugin for trigger [gitlab-ci](https://about.gitlab.com/solutions/continuous-integration/) jobs. 13 | 14 | ## GitLab Setting 15 | 16 | See the detail documentation for [Pipeline trigger tokens API](https://docs.gitlab.com/ee/api/pipeline_triggers.html). You can create personal access tokens to authenticate with: 17 | 18 | 1. The GitLab API. 19 | 2. GitLab repositories. 20 | 3. The GitLab registry. 21 | 22 | See the [GitLab token overview](https://docs.gitlab.com/ee/security/tokens/index.html#personal-access-tokens). 23 | 24 | ![token](./images/user_token.png) 25 | 26 | How to get the project ID? going to your project’s `Settings ➔ General` under Gerneral project. 27 | 28 | ![projectID](./images/projectID.png) 29 | 30 | ## Build or Download a binary 31 | 32 | The pre-compiled binaries can be downloaded from [release page](https://github.com/appleboy/drone-gitlab-ci/releases). Support the following OS type. 33 | 34 | - Windows amd64/386 35 | - Linux amd64/386 36 | - Darwin amd64/386 37 | 38 | With `Go` installed 39 | 40 | ```sh 41 | go install github.com/appleboy/drone-gitlab-ci 42 | ``` 43 | 44 | or build the binary with the following command: 45 | 46 | ```sh 47 | make build 48 | ``` 49 | 50 | ## Usage 51 | 52 | There are three ways to trigger gitlab-ci jobs. 53 | 54 | ### Usage from binary 55 | 56 | trigger job. 57 | 58 | ```bash 59 | drone-gitlab-ci \ 60 | --host https://gitlab.com/ \ 61 | --token XXXXXXXX \ 62 | --ref master \ 63 | --project-id gitlab-ci-project-id 64 | ``` 65 | 66 | Enable debug mode. 67 | 68 | ```diff 69 | drone-gitlab-ci \ 70 | --host https://gitlab.com/ \ 71 | --token XXXXXXXX \ 72 | --ref master \ 73 | --project-id gitlab-ci-project-id 74 | + --debug 75 | ``` 76 | 77 | ### Usage from docker 78 | 79 | trigger job. 80 | 81 | ```bash 82 | docker run --rm \ 83 | -e GITLAB_HOST=https://gitlab.com/ 84 | -e GITLAB_TOKEN=xxxxx 85 | -e GITLAB_REF=master 86 | -e GITLAB_ID=gitlab-ci-project-id 87 | appleboy/drone-gitlab-ci 88 | ``` 89 | 90 | Enable debug mode. 91 | 92 | ```bash 93 | docker run --rm \ 94 | -e GITLAB_HOST=https://gitlab.com/ \ 95 | -e GITLAB_TOKEN=xxxxx \ 96 | -e GITLAB_REF=master \ 97 | -e GITLAB_ID=gitlab-ci-project-id \ 98 | -e GITLAB_DEBUG=true \ 99 | appleboy/drone-gitlab-ci 100 | ``` 101 | 102 | ### Usage from drone ci 103 | 104 | Execute from the working directory: 105 | 106 | ```sh 107 | docker run --rm \ 108 | -e PLUGIN_HOST=https://gitlab.com/ \ 109 | -e PLUGIN_TOKEN=xxxxx \ 110 | -e PLUGIN_REF=master \ 111 | -e PLUGIN_ID=gitlab-ci-project-id \ 112 | -e PLUGIN_DEBUG=true \ 113 | -v $(pwd):$(pwd) \ 114 | -w $(pwd) \ 115 | appleboy/drone-gitlab-ci 116 | ``` 117 | 118 | You can get more [information](DOCS.md) about how to use scp plugin in drone. 119 | 120 | ## Testing 121 | 122 | Test the package with the following command: 123 | 124 | ```sh 125 | make test 126 | ``` 127 | -------------------------------------------------------------------------------- /README.zh-cn.md: -------------------------------------------------------------------------------- 1 | # drone-gitlab-ci 2 | 3 | ![logo](./images/logo.png) 4 | 5 | [繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md) | [English](./README.md) 6 | 7 | [![Lint and Testing](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml/badge.svg)](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml) 8 | [![GoDoc](https://godoc.org/github.com/appleboy/drone-gitlab-ci?status.svg)](https://godoc.org/github.com/appleboy/drone-gitlab-ci) 9 | [![codecov](https://codecov.io/gh/appleboy/drone-gitlab-ci/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-gitlab-ci) 10 | [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-gitlab-ci)](https://goreportcard.com/report/github.com/appleboy/drone-gitlab-ci) 11 | 12 | [Drone](https://www.drone.io/) 插件用于触发 [gitlab-ci](https://about.gitlab.com/solutions/continuous-integration/) 任务。 13 | 14 | ## GitLab 设置 15 | 16 | 请参阅 [Pipeline trigger tokens API](https://docs.gitlab.com/ee/api/pipeline_triggers.html) 的详细文档。您可以创建个人访问令牌来进行身份验证: 17 | 18 | 1. GitLab API。 19 | 2. GitLab 仓库。 20 | 3. GitLab 注册表。 21 | 22 | 请参阅 [GitLab token 概述](https://docs.gitlab.com/ee/security/tokens/index.html#personal-access-tokens)。 23 | 24 | ![token](./images/user_token.png) 25 | 26 | 如何获取项目 ID?前往您的项目 `设置 ➔ 一般` 下的一般项目。 27 | 28 | ![projectID](./images/projectID.png) 29 | 30 | ## 构建或下载二进制文件 31 | 32 | 可以从 [发布页面](https://github.com/appleboy/drone-gitlab-ci/releases) 下载预编译的二进制文件。支持以下操作系统类型。 33 | 34 | - Windows amd64/386 35 | - Linux amd64/386 36 | - Darwin amd64/386 37 | 38 | 安装 `Go` 39 | 40 | ```sh 41 | go install github.com/appleboy/drone-gitlab-ci 42 | ``` 43 | 44 | 或者使用以下命令构建二进制文件: 45 | 46 | ```sh 47 | make build 48 | ``` 49 | 50 | ## 用法 51 | 52 | 有三种方法可以触发 gitlab-ci 任务。 53 | 54 | ### 从二进制文件使用 55 | 56 | 触发任务。 57 | 58 | ```bash 59 | drone-gitlab-ci \ 60 | --host https://gitlab.com/ \ 61 | --token XXXXXXXX \ 62 | --ref master \ 63 | --project-id gitlab-ci-project-id 64 | ``` 65 | 66 | 启用调试模式。 67 | 68 | ```bash 69 | drone-gitlab-ci \ 70 | --host https://gitlab.com/ \ 71 | --token XXXXXXXX \ 72 | --ref master \ 73 | --project-id gitlab-ci-project-id \ 74 | --debug 75 | ``` 76 | 77 | ### 从 docker 使用 78 | 79 | 触发任务。 80 | 81 | ```bash 82 | docker run --rm \ 83 | -e GITLAB_HOST=https://gitlab.com/ 84 | -e GITLAB_TOKEN=xxxxx 85 | -e GITLAB_REF=master 86 | -e GITLAB_ID=gitlab-ci-project-id 87 | appleboy/drone-gitlab-ci 88 | ``` 89 | 90 | 启用调试模式。 91 | 92 | ```bash 93 | docker run --rm \ 94 | -e GITLAB_HOST=https://gitlab.com/ \ 95 | -e GITLAB_TOKEN=xxxxx \ 96 | -e GITLAB_REF=master \ 97 | -e GITLAB_ID=gitlab-ci-project-id \ 98 | -e GITLAB_DEBUG=true \ 99 | appleboy/drone-gitlab-ci 100 | ``` 101 | 102 | ### 从 drone ci 使用 103 | 104 | 从工作目录执行: 105 | 106 | ```sh 107 | docker run --rm \ 108 | -e PLUGIN_HOST=https://gitlab.com/ \ 109 | -e PLUGIN_TOKEN=xxxxx \ 110 | -e PLUGIN_REF=master \ 111 | -e PLUGIN_ID=gitlab-ci-project-id \ 112 | -e PLUGIN_DEBUG=true \ 113 | -v $(pwd):$(pwd) \ 114 | -w $(pwd) \ 115 | appleboy/drone-gitlab-ci 116 | ``` 117 | 118 | 您可以在 [此处](DOCS.md) 获取有关如何在 drone 中使用 scp 插件的更多 [信息](DOCS.md)。 119 | 120 | ## 测试 121 | 122 | 使用以下命令测试包: 123 | 124 | ```sh 125 | make test 126 | ``` 127 | -------------------------------------------------------------------------------- /README.zh-tw.md: -------------------------------------------------------------------------------- 1 | # drone-gitlab-ci 2 | 3 | ![logo](./images/logo.png) 4 | 5 | [繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md) | [English](./README.md) 6 | 7 | [![Lint and Testing](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml/badge.svg)](https://github.com/appleboy/drone-gitlab-ci/actions/workflows/lint.yml) 8 | [![GoDoc](https://godoc.org/github.com/appleboy/drone-gitlab-ci?status.svg)](https://godoc.org/github.com/appleboy/drone-gitlab-ci) 9 | [![codecov](https://codecov.io/gh/appleboy/drone-gitlab-ci/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/drone-gitlab-ci) 10 | [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/drone-gitlab-ci)](https://goreportcard.com/report/github.com/appleboy/drone-gitlab-ci) 11 | 12 | [Drone](https://www.drone.io/) 插件用於觸發 [gitlab-ci](https://about.gitlab.com/solutions/continuous-integration/) 任務。 13 | 14 | ## GitLab 設定 15 | 16 | 請參閱 [Pipeline trigger tokens API](https://docs.gitlab.com/ee/api/pipeline_triggers.html) 的詳細文檔。您可以創建個人訪問令牌來進行身份驗證: 17 | 18 | 1. GitLab API。 19 | 2. GitLab 儲存庫。 20 | 3. GitLab 註冊表。 21 | 22 | 請參閱 [GitLab token 概述](https://docs.gitlab.com/ee/security/tokens/index.html#personal-access-tokens)。 23 | 24 | ![token](./images/user_token.png) 25 | 26 | 如何獲取項目 ID?前往您的項目 `設定 ➔ 一般` 下的一般項目。 27 | 28 | ![projectID](./images/projectID.png) 29 | 30 | ## 構建或下載二進制文件 31 | 32 | 可以從 [發佈頁面](https://github.com/appleboy/drone-gitlab-ci/releases) 下載預編譯的二進制文件。支持以下操作系統類型。 33 | 34 | - Windows amd64/386 35 | - Linux amd64/386 36 | - Darwin amd64/386 37 | 38 | 安裝 `Go` 39 | 40 | ```sh 41 | go install github.com/appleboy/drone-gitlab-ci 42 | ``` 43 | 44 | 或使用以下命令構建二進制文件: 45 | 46 | ```sh 47 | make build 48 | ``` 49 | 50 | ## 用法 51 | 52 | 有三種方式觸發 gitlab-ci 任務。 53 | 54 | ### 從二進制文件使用 55 | 56 | 觸發任務。 57 | 58 | ```bash 59 | drone-gitlab-ci \ 60 | --host https://gitlab.com/ \ 61 | --token XXXXXXXX \ 62 | --ref master \ 63 | --project-id gitlab-ci-project-id 64 | ``` 65 | 66 | 啟用調試模式。 67 | 68 | ```bash 69 | drone-gitlab-ci \ 70 | --host https://gitlab.com/ \ 71 | --token XXXXXXXX \ 72 | --ref master \ 73 | --project-id gitlab-ci-project-id \ 74 | --debug 75 | ``` 76 | 77 | ### 從 docker 使用 78 | 79 | 觸發任務。 80 | 81 | ```bash 82 | docker run --rm \ 83 | -e GITLAB_HOST=https://gitlab.com/ 84 | -e GITLAB_TOKEN=xxxxx 85 | -e GITLAB_REF=master 86 | -e GITLAB_ID=gitlab-ci-project-id 87 | appleboy/drone-gitlab-ci 88 | ``` 89 | 90 | 啟用調試模式。 91 | 92 | ```bash 93 | docker run --rm \ 94 | -e GITLAB_HOST=https://gitlab.com/ \ 95 | -e GITLAB_TOKEN=xxxxx \ 96 | -e GITLAB_REF=master \ 97 | -e GITLAB_ID=gitlab-ci-project-id \ 98 | -e GITLAB_DEBUG=true \ 99 | appleboy/drone-gitlab-ci 100 | ``` 101 | 102 | ### 從 drone ci 使用 103 | 104 | 從工作目錄執行: 105 | 106 | ```sh 107 | docker run --rm \ 108 | -e PLUGIN_HOST=https://gitlab.com/ \ 109 | -e PLUGIN_TOKEN=xxxxx \ 110 | -e PLUGIN_REF=master \ 111 | -e PLUGIN_ID=gitlab-ci-project-id \ 112 | -e PLUGIN_DEBUG=true \ 113 | -v $(pwd):$(pwd) \ 114 | -w $(pwd) \ 115 | appleboy/drone-gitlab-ci 116 | ``` 117 | 118 | 您可以獲取更多有關如何在 drone 中使用 scp 插件的[信息](DOCS.md)。 119 | 120 | ## 測試 121 | 122 | 使用以下命令測試包: 123 | 124 | ```sh 125 | make test 126 | ``` 127 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.20 2 | 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | 6 | LABEL maintainer="Bo-Yi Wu " \ 7 | org.label-schema.name="Drone Gitlab CI Plugin" \ 8 | org.label-schema.vendor="Bo-Yi Wu" \ 9 | org.label-schema.schema-version="1.0" 10 | 11 | LABEL org.opencontainers.image.source=https://github.com/appleboy/drone-gitlab-ci 12 | LABEL org.opencontainers.image.description="Drone Gitlab CI" 13 | LABEL org.opencontainers.image.licenses=MIT 14 | 15 | RUN apk add --no-cache ca-certificates && \ 16 | rm -rf /var/cache/apk/* 17 | 18 | COPY release/${TARGETOS}/${TARGETARCH}/drone-gitlab-ci /bin/ 19 | 20 | ENTRYPOINT ["/bin/drone-gitlab-ci"] 21 | -------------------------------------------------------------------------------- /gitlab.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package main provides functionality to interact with GitLab's API, specifically for creating and managing pipelines. 3 | 4 | The Gitlab struct contains an authenticated client to communicate with the GitLab API. 5 | 6 | Functions: 7 | 8 | - NewGitlab: Initializes a new Gitlab client with the provided host, token, and configuration options. 9 | - CreatePipeline: Triggers the creation of a new pipeline in a specified GitLab project. 10 | - GetPipelineStatus: Retrieves the status of a specific pipeline for a given project. 11 | 12 | Types: 13 | 14 | - Gitlab: Contains the authenticated client for GitLab API interactions. 15 | 16 | Dependencies: 17 | 18 | - "crypto/tls" 19 | - "net/http" 20 | - "github.com/xanzy/go-gitlab" 21 | */ 22 | package main 23 | 24 | import ( 25 | "crypto/tls" 26 | "net/http" 27 | 28 | "github.com/appleboy/com/convert" 29 | "github.com/xanzy/go-gitlab" 30 | ) 31 | 32 | type ( 33 | // Gitlab contain Auth and BaseURL 34 | Gitlab struct { 35 | client *gitlab.Client 36 | } 37 | ) 38 | 39 | // NewGitlab initializes a new Gitlab client with the provided host, token, and configuration options. 40 | func NewGitlab(host, token string, insecure bool) (*Gitlab, error) { 41 | httpClient := http.DefaultClient 42 | if insecure { 43 | httpClient = &http.Client{ 44 | Transport: &http.Transport{ 45 | TLSClientConfig: &tls.Config{ 46 | InsecureSkipVerify: true, 47 | }, 48 | }, 49 | } 50 | } 51 | 52 | g, err := gitlab.NewClient( 53 | token, 54 | gitlab.WithBaseURL(host), 55 | gitlab.WithHTTPClient(httpClient), 56 | ) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | return &Gitlab{ 62 | client: g, 63 | }, nil 64 | } 65 | 66 | // CreatePipeline triggers the creation of a new pipeline in a specified GitLab project. 67 | // 68 | // Parameters: 69 | // - projectID: The ID of the GitLab project where the pipeline will be created. 70 | // - ref: The branch or tag name to create the pipeline for. 71 | // - variables: A map of environment variables to set for the pipeline. 72 | // 73 | // Returns: 74 | // - *gitlab.Pipeline: The created pipeline object. 75 | // - error: An error object if the pipeline creation fails, otherwise nil. 76 | func (g *Gitlab) CreatePipeline(projectID string, ref string, variables map[string]string) (*gitlab.Pipeline, error) { 77 | allenvs := make([]*gitlab.PipelineVariableOptions, 0) 78 | options := &gitlab.CreatePipelineOptions{ 79 | Ref: convert.ToPtr(ref), 80 | Variables: convert.ToPtr(allenvs), 81 | } 82 | for k, v := range variables { 83 | // Usage of single iteration variable in range loop 84 | key, value := k, v 85 | allenvs = append(allenvs, &gitlab.PipelineVariableOptions{ 86 | Key: convert.ToPtr(key), 87 | Value: convert.ToPtr(value), 88 | }) 89 | } 90 | pipeline, _, err := g.client.Pipelines.CreatePipeline(projectID, options) 91 | if err != nil { 92 | return nil, err 93 | } 94 | 95 | return pipeline, nil 96 | } 97 | 98 | // GetPipelineStatus retrieves the status of a specific pipeline for a given project. 99 | // It takes the project ID as a string and the pipeline ID as an integer. 100 | // It returns the status of the pipeline as a string and an error if any occurs during the retrieval process. 101 | func (g *Gitlab) GetPipelineStatus(projectID string, pipelineID int) (string, error) { 102 | pipeline, _, err := g.client.Pipelines.GetPipeline(projectID, pipelineID) 103 | if err != nil { 104 | return "", err 105 | } 106 | 107 | return pipeline.Status, nil 108 | } 109 | -------------------------------------------------------------------------------- /gitlab_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/appleboy/drone-gitlab-ci 2 | 3 | go 1.21.0 4 | 5 | require ( 6 | github.com/appleboy/com v0.2.1 7 | github.com/joho/godotenv v1.5.1 8 | github.com/stretchr/testify v1.10.0 9 | github.com/urfave/cli/v2 v2.27.5 10 | github.com/xanzy/go-gitlab v0.115.0 11 | github.com/yassinebenaid/godump v0.11.1 12 | ) 13 | 14 | require ( 15 | github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect 16 | github.com/davecgh/go-spew v1.1.1 // indirect 17 | github.com/google/go-querystring v1.1.0 // indirect 18 | github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 19 | github.com/hashicorp/go-retryablehttp v0.7.7 // indirect 20 | github.com/pmezard/go-difflib v1.0.0 // indirect 21 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 22 | github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect 23 | golang.org/x/oauth2 v0.24.0 // indirect 24 | golang.org/x/sys v0.26.0 // indirect 25 | golang.org/x/text v0.21.0 // indirect 26 | golang.org/x/time v0.8.0 // indirect 27 | gopkg.in/yaml.v3 v3.0.1 // indirect 28 | ) 29 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/appleboy/com v0.2.1 h1:dHAHauX3eYDuheAahI83HIGFxpi0SEb2ZAu9EZ9hbUM= 2 | github.com/appleboy/com v0.2.1/go.mod h1:kByEI3/vzI5GM1+O5QdBHLsXaOsmFsJcOpCSgASi4sg= 3 | github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= 4 | github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= 5 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 6 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= 8 | github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 9 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 10 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 11 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 12 | github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= 13 | github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 14 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 15 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 16 | github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= 17 | github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= 18 | github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= 19 | github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= 20 | github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= 21 | github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= 22 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 23 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 24 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 25 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 26 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 27 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 28 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 29 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 30 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 31 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 32 | github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w= 33 | github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ= 34 | github.com/xanzy/go-gitlab v0.115.0 h1:6DmtItNcVe+At/liXSgfE/DZNZrGfalQmBRmOcJjOn8= 35 | github.com/xanzy/go-gitlab v0.115.0/go.mod h1:5XCDtM7AM6WMKmfDdOiEpyRWUqui2iS9ILfvCZ2gJ5M= 36 | github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= 37 | github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= 38 | github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI= 39 | github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44= 40 | golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= 41 | golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 42 | golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= 43 | golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 44 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 45 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 46 | golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= 47 | golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 48 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 49 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 50 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 51 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 52 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 53 | -------------------------------------------------------------------------------- /images/gitlab-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleboy/drone-gitlab-ci/beaa366bc7e17f1db7f746bedf33cd56e5479fec/images/logo.png -------------------------------------------------------------------------------- /images/projectID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleboy/drone-gitlab-ci/beaa366bc7e17f1db7f746bedf33cd56e5479fec/images/projectID.png -------------------------------------------------------------------------------- /images/user_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleboy/drone-gitlab-ci/beaa366bc7e17f1db7f746bedf33cd56e5479fec/images/user_token.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "strings" 8 | "time" 9 | 10 | "github.com/joho/godotenv" 11 | "github.com/urfave/cli/v2" 12 | "github.com/yassinebenaid/godump" 13 | ) 14 | 15 | // Version set at compile-time 16 | var Version string 17 | 18 | func main() { 19 | // Load env-file if it exists first 20 | if filename, found := os.LookupEnv("PLUGIN_ENV_FILE"); found { 21 | _ = godotenv.Load(filename) 22 | } 23 | 24 | if _, err := os.Stat("/run/drone/env"); err == nil { 25 | _ = godotenv.Overload("/run/drone/env") 26 | } 27 | 28 | copyright := fmt.Sprintf("Copyright (c) %v Bo-Yi Wu", time.Now().Year()) 29 | app := &cli.App{ 30 | Name: "gitlab-ci plugin", 31 | Usage: "trigger gitlab-ci pipeline", 32 | Copyright: copyright, 33 | Authors: []*cli.Author{ 34 | { 35 | Name: "Bo-Yi Wu", 36 | Email: "appleboy.tw@gmail.com", 37 | }, 38 | }, 39 | Action: run, 40 | Version: Version, 41 | Flags: []cli.Flag{ 42 | &cli.StringFlag{ 43 | Name: "host", 44 | Usage: "gitlab-ci base url", 45 | EnvVars: []string{"PLUGIN_HOST", "GITLAB_HOST", "INPUT_HOST"}, 46 | Value: "https://gitlab.com", 47 | }, 48 | &cli.StringFlag{ 49 | Name: "token", 50 | Aliases: []string{"t"}, 51 | Usage: "gitlab-ci token", 52 | EnvVars: []string{"PLUGIN_TOKEN", "GITLAB_TOKEN", "INPUT_TOKEN"}, 53 | }, 54 | &cli.StringFlag{ 55 | Name: "project-id", 56 | Aliases: []string{"p"}, 57 | Usage: "gitlab-ci project id", 58 | EnvVars: []string{"PLUGIN_ID", "GITLAB_PROJECT_ID", "INPUT_PROJECT_ID"}, 59 | }, 60 | &cli.StringFlag{ 61 | Name: "ref", 62 | Aliases: []string{"r"}, 63 | Usage: "gitlab-ci valid refs are only the branches and tags", 64 | EnvVars: []string{"PLUGIN_REF", "GITLAB_REF", "INPUT_REF"}, 65 | Value: "main", 66 | }, 67 | &cli.BoolFlag{ 68 | Name: "debug", 69 | Aliases: []string{"d"}, 70 | Usage: "debug mode", 71 | EnvVars: []string{"PLUGIN_DEBUG", "GITLAB_DEBUG", "INPUT_DEBUG"}, 72 | }, 73 | &cli.StringSliceFlag{ 74 | Name: "variables", 75 | Usage: "gitlab-ci variables", 76 | EnvVars: []string{"PLUGIN_VARIABLES", "GITLAB_VARIABLES", "INPUT_VARIABLES"}, 77 | }, 78 | &cli.BoolFlag{ 79 | Name: "insecure", 80 | Aliases: []string{"k"}, 81 | Usage: "allow connections to SSL sites without certs", 82 | EnvVars: []string{"PLUGIN_INSECURE", "GITLAB_INSECURE", "INPUT_INSECURE"}, 83 | }, 84 | &cli.DurationFlag{ 85 | Name: "timeout", 86 | Usage: "timeout waiting for pipeline to complete", 87 | EnvVars: []string{"PLUGIN_TIMEOUT", "GITLAB_TIMEOUT", "INPUT_TIMEOUT"}, 88 | Value: time.Minute * 60, 89 | }, 90 | &cli.DurationFlag{ 91 | Name: "interval", 92 | Aliases: []string{"i"}, 93 | Usage: "interval waiting for pipeline to complete", 94 | EnvVars: []string{"PLUGIN_INTERVAL", "GITLAB_INTERVAL", "INPUT_INTERVAL"}, 95 | Value: time.Second * 5, 96 | }, 97 | &cli.BoolFlag{ 98 | Name: "wait", 99 | Aliases: []string{"w"}, 100 | Usage: "wait for pipeline to complete", 101 | EnvVars: []string{"PLUGIN_WAIT", "GITLAB_WAIT", "INPUT_WAIT"}, 102 | }, 103 | &cli.BoolFlag{ 104 | Name: "github", 105 | Usage: "github actions", 106 | EnvVars: []string{"PLUGIN_GITHUB", "GITHUB_ACTIONS", "INPUT_GITHUB"}, 107 | }, 108 | }, 109 | } 110 | 111 | // Override a template 112 | cli.AppHelpTemplate = ` 113 | ________ ________.__ __ .__ ___. _________ .___ 114 | \______ \_______ ____ ____ ____ / _____/|__|/ |_| | _____ \_ |__ \_ ___ \| | 115 | | | \_ __ \/ _ \ / \_/ __ \ ______ / \ ___| \ __\ | \__ \ | __ \ ______ / \ \/| | 116 | | | \ | \( <_> ) | \ ___/ /_____/ \ \_\ \ || | | |__/ __ \| \_\ \ /_____/ \ \___| | 117 | /_______ /__| \____/|___| /\___ > \______ /__||__| |____(____ /___ / \______ /___| 118 | \/ \/ \/ \/ \/ \/ \/ 119 | 120 | version: {{.Version}} 121 | NAME: 122 | {{.Name}} - {{.Usage}} 123 | 124 | USAGE: 125 | {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} 126 | {{if len .Authors}} 127 | AUTHOR: 128 | {{range .Authors}}{{ . }}{{end}} 129 | {{end}}{{if .Commands}} 130 | COMMANDS: 131 | {{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}} 132 | GLOBAL OPTIONS: 133 | {{range .VisibleFlags}}{{.}} 134 | {{end}}{{end}}{{if .Copyright }} 135 | COPYRIGHT: 136 | {{.Copyright}} 137 | {{end}}{{if .Version}} 138 | VERSION: 139 | {{.Version}} 140 | {{end}} 141 | REPOSITORY: 142 | Github: https://github.com/appleboy/drone-gitlab-ci 143 | ` 144 | 145 | if err := app.Run(os.Args); err != nil { 146 | log.Fatal(err) 147 | } 148 | } 149 | 150 | func run(c *cli.Context) error { 151 | variables := make(map[string]string) 152 | 153 | for _, v := range c.StringSlice("variables") { 154 | s := strings.Split(v, "=") 155 | if len(s) == 2 { 156 | variables[s[0]] = s[1] 157 | } 158 | } 159 | 160 | plugin := Plugin{ 161 | Host: c.String("host"), 162 | Token: c.String("token"), 163 | Ref: c.String("ref"), 164 | ProjectID: c.String("project-id"), 165 | Debug: c.Bool("debug"), 166 | Variables: variables, 167 | Insecure: c.Bool("insecure"), 168 | Timeout: c.Duration("timeout"), 169 | Interval: c.Duration("interval"), 170 | Wait: c.Bool("wait"), 171 | IsGitHub: c.Bool("github"), 172 | } 173 | 174 | if plugin.Debug { 175 | godump.Dump(plugin) 176 | } 177 | 178 | return plugin.Exec() 179 | } 180 | -------------------------------------------------------------------------------- /plugin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "log/slog" 7 | "os" 8 | "strconv" 9 | "time" 10 | 11 | gh "github.com/appleboy/com/gh" 12 | ) 13 | 14 | type ( 15 | // Plugin values. 16 | Plugin struct { 17 | Host string 18 | Token string 19 | Ref string 20 | ProjectID string 21 | Debug bool 22 | Variables map[string]string 23 | Insecure bool 24 | Timeout time.Duration 25 | Interval time.Duration 26 | Wait bool 27 | IsGitHub bool 28 | } 29 | ) 30 | 31 | // Exec executes the plugin. 32 | func (p Plugin) Exec() error { 33 | l := slog.New(slog.NewTextHandler(os.Stderr, nil)). 34 | With("project_id", p.ProjectID) 35 | 36 | if err := p.Validate(); err != nil { 37 | return err 38 | } 39 | 40 | // Create Gitlab object 41 | g, err := NewGitlab(p.Host, p.Token, p.Insecure) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | // Create pipeline 47 | pipeline, err := g.CreatePipeline(p.ProjectID, p.Ref, p.Variables) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | l.Info( 53 | "pipeline created", 54 | "pipeline_id", pipeline.ID, 55 | "pipeline_sha", pipeline.SHA, 56 | "pipeline_ref", pipeline.Ref, 57 | "pipeline_status", pipeline.Status, 58 | "pipeline_web_url", pipeline.WebURL, 59 | "pipeline_created_at", pipeline.CreatedAt, 60 | ) 61 | 62 | // Set output 63 | if p.IsGitHub { 64 | if err := gh.SetOutput(map[string]string{ 65 | "id": strconv.Itoa(pipeline.ID), 66 | "sha": pipeline.SHA, 67 | "ref": pipeline.Ref, 68 | "web_url": pipeline.WebURL, 69 | }); err != nil { 70 | return err 71 | } 72 | } 73 | 74 | // Wait for pipeline to complete 75 | if !p.Wait { 76 | return nil 77 | } 78 | 79 | // Wait for pipeline to complete 80 | ticker := time.NewTicker(p.Interval) 81 | ctxTimeout, cancel := context.WithTimeout(context.Background(), p.Timeout) 82 | defer cancel() 83 | defer ticker.Stop() 84 | 85 | l.Info("waiting for pipeline to complete", "timeout", p.Timeout) 86 | for { 87 | select { 88 | case <-ctxTimeout.Done(): 89 | return errors.New("timeout waiting for pipeline to complete after " + p.Timeout.String()) 90 | case <-ticker.C: 91 | // Check pipeline status 92 | status, err := g.GetPipelineStatus(p.ProjectID, pipeline.ID) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | l.Info("pipeline status", 98 | "status", status, 99 | "triggered_by", pipeline.User.Name, 100 | ) 101 | 102 | // https://docs.gitlab.com/ee/api/pipelines.html 103 | // created, waiting_for_resource, preparing, pending, 104 | // running, success, failed, canceled, skipped, manual, scheduled 105 | if status == "success" || 106 | status == "failed" || 107 | status == "canceled" || 108 | status == "skipped" { 109 | l.Info("pipeline completed", "status", status) 110 | if p.IsGitHub { 111 | // update status 112 | if err := gh.SetOutput(map[string]string{"status": status}); err != nil { 113 | return err 114 | } 115 | } 116 | return nil 117 | } 118 | 119 | if ctxTimeout.Err() != nil { 120 | if p.IsGitHub { 121 | // update status 122 | if err := gh.SetOutput(map[string]string{"status": status}); err != nil { 123 | return err 124 | } 125 | } 126 | return ctxTimeout.Err() 127 | } 128 | } 129 | } 130 | } 131 | 132 | // Validate checks the plugin configuration. 133 | func (p Plugin) Validate() error { 134 | if len(p.Host) == 0 { 135 | return errors.New("missing host") 136 | } 137 | if len(p.Token) == 0 { 138 | return errors.New("missing token") 139 | } 140 | if len(p.ProjectID) == 0 { 141 | return errors.New("missing project id") 142 | } 143 | return nil 144 | } 145 | -------------------------------------------------------------------------------- /plugin_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestMissingConfig(t *testing.T) { 10 | var plugin Plugin 11 | 12 | err := plugin.Exec() 13 | 14 | assert.Error(t, err) 15 | } 16 | --------------------------------------------------------------------------------