drone版本代码初始化
commit
80f58ef743
@ -0,0 +1,2 @@
|
||||
*
|
||||
!release/*
|
@ -0,0 +1,107 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: linux-amd64
|
||||
|
||||
platform:
|
||||
arch: amd64
|
||||
os: linux
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.14.15
|
||||
commands:
|
||||
- go test -race ./...
|
||||
- go build -o /dev/null github.com/drone/drone/cmd/drone-server
|
||||
- go build -o /dev/null -tags "oss nolimit" github.com/drone/drone/cmd/drone-server
|
||||
|
||||
- name: build
|
||||
image: golang:1.14.15
|
||||
commands:
|
||||
- sh scripts/build.sh
|
||||
environment:
|
||||
GOARCH: amd64
|
||||
GOOS: linux
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:18
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
dockerfile: docker/Dockerfile.server.linux.amd64
|
||||
repo: drone/drone
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
when:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: vm
|
||||
name: linux-arm64
|
||||
|
||||
pool:
|
||||
use: ubuntu_arm64
|
||||
|
||||
platform:
|
||||
arch: arm64
|
||||
os: linux
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: golang:1.14.15
|
||||
commands:
|
||||
- sh scripts/build.sh
|
||||
environment:
|
||||
GOARCH: arm64
|
||||
GOOS: linux
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:18
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
dockerfile: docker/Dockerfile.server.linux.arm64
|
||||
repo: drone/drone
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
depends_on:
|
||||
- linux-amd64
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: manifest
|
||||
|
||||
steps:
|
||||
- name: publish
|
||||
image: plugins/manifest:1.2
|
||||
settings:
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
spec: docker/manifest.server.tmpl
|
||||
username:
|
||||
from_secret: docker_username
|
||||
password:
|
||||
from_secret: docker_password
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- tag
|
||||
|
||||
depends_on:
|
||||
- linux-arm64
|
||||
|
@ -0,0 +1,13 @@
|
||||
.vscode
|
||||
__debug_bin
|
||||
*.sqlite
|
||||
*.txt
|
||||
*.out
|
||||
*.key
|
||||
.env
|
||||
.env.*
|
||||
release/
|
||||
scripts/*.go
|
||||
docker/**/data
|
||||
TODO*
|
||||
.idea
|
@ -0,0 +1,11 @@
|
||||
1. Clone the repository
|
||||
2. Install go 1.11 or later with Go modules enabled
|
||||
3. Install binaries to $GOPATH/bin
|
||||
|
||||
go install github.com/drone/drone/cmd/drone-server
|
||||
|
||||
4. Start the server at localhost:8080
|
||||
|
||||
export DRONE_GITHUB_CLIENT_ID=...
|
||||
export DRONE_GITHUB_CLIENT_SECRET=...
|
||||
drone-server
|
@ -0,0 +1,11 @@
|
||||
1. Clone the repository
|
||||
2. Install go 1.11 or later with Go modules enabled
|
||||
3. Install binaries to $GOPATH/bin
|
||||
|
||||
go install -tags "oss nolimit" github.com/drone/drone/cmd/drone-server
|
||||
|
||||
4. Start the server at localhost:8080
|
||||
|
||||
export DRONE_GITHUB_CLIENT_ID=...
|
||||
export DRONE_GITHUB_CLIENT_SECRET=...
|
||||
drone-server
|
@ -0,0 +1,797 @@
|
||||
# Changelog
|
||||
|
||||
## [v2.20.0](https://github.com/harness/drone/tree/v2.20.0) (2023-08-21)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.19.0...v2.20.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- + sync gitea redirecturl config from gitee for customize login redire… [\#3319](https://github.com/harness/drone/pull/3319) ([fireinice](https://github.com/fireinice))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(CI-8780\) set approved stages to waiting, if they have stage depende… [\#3355](https://github.com/harness/drone/pull/3355) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.19.0](https://github.com/harness/drone/tree/v2.19.0) (2023-08-15)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/scheduler_experiment...v2.19.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Support arbitrary action value from parameter in query string [\#3341](https://github.com/harness/drone/pull/3341) ([filippopisano](https://github.com/filippopisano))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- bump drone-ui to 2.11.5 [\#3350](https://github.com/harness/drone/pull/3350) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump drone-ui to 2.11.4 [\#3349](https://github.com/harness/drone/pull/3349) ([d1wilko](https://github.com/d1wilko))
|
||||
- \(fix\) prevent scheduler deadlock [\#3344](https://github.com/harness/drone/pull/3344) ([tphoney](https://github.com/tphoney))
|
||||
- bump drone-ui to 2.11.3 [\#3337](https://github.com/harness/drone/pull/3337) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) prep for v2.19.0 [\#3352](https://github.com/harness/drone/pull/3352) ([tphoney](https://github.com/tphoney))
|
||||
- remove repetitive words [\#3342](https://github.com/harness/drone/pull/3342) ([cuishuang](https://github.com/cuishuang))
|
||||
- Revert "fix scheduler queue deadlock" [\#3331](https://github.com/harness/drone/pull/3331) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [scheduler_experiment](https://github.com/harness/drone/tree/scheduler_experiment) (2023-07-05)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.18.0...scheduler_experiment)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fix scheduler queue deadlock [\#3330](https://github.com/harness/drone/pull/3330) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.18.0](https://github.com/harness/drone/tree/v2.18.0) (2023-07-04)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.17.0...v2.18.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- support custom pipeline message [\#3294](https://github.com/harness/drone/pull/3294) ([zc2638](https://github.com/zc2638))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- bump drone-ui to 2.11.2 [\#3327](https://github.com/harness/drone/pull/3327) ([d1wilko](https://github.com/d1wilko))
|
||||
- Fix comment errors [\#3302](https://github.com/harness/drone/pull/3302) ([weidongkl](https://github.com/weidongkl))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- v2.18.0 release prep [\#3328](https://github.com/harness/drone/pull/3328) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.17.0](https://github.com/harness/drone/tree/v2.17.0) (2023-04-25)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.16.0...v2.17.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Add `authtype` to logging middleware [\#3310](https://github.com/harness/drone/pull/3310) ([colinhoglund](https://github.com/colinhoglund))
|
||||
- Add config for the buffer [\#3308](https://github.com/harness/drone/pull/3308) ([TheJokersThief](https://github.com/TheJokersThief))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- store/card: fix dropped error [\#3300](https://github.com/harness/drone/pull/3300) ([alrs](https://github.com/alrs))
|
||||
- bump drone-ui to 2.9.1 [\#3298](https://github.com/harness/drone/pull/3298) ([d1wilko](https://github.com/d1wilko))
|
||||
- Starlark: Update `go.starlark.net` dependency [\#3284](https://github.com/harness/drone/pull/3284) ([dsotirakis](https://github.com/dsotirakis))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep for v2.17.0 [\#3316](https://github.com/harness/drone/pull/3316) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- bump drone-ui to 2.11.1 [\#3315](https://github.com/harness/drone/pull/3315) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump drone-ui to 2.11.0 [\#3313](https://github.com/harness/drone/pull/3313) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump drone-ui to 2.10.0 [\#3311](https://github.com/harness/drone/pull/3311) ([d1wilko](https://github.com/d1wilko))
|
||||
- \(maint\) move to use the arm64 pool [\#3296](https://github.com/harness/drone/pull/3296) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.16.0](https://github.com/harness/drone/tree/v2.16.0) (2022-12-15)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.15.0...v2.16.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Make Starlark file size limit configurable [\#3291](https://github.com/harness/drone/pull/3291) ([andrii-kasparevych](https://github.com/andrii-kasparevych))
|
||||
- Enhance status check label for promotions [\#3263](https://github.com/harness/drone/pull/3263) ([michelangelomo](https://github.com/michelangelomo))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(bugfix\) bump go-scm to v1.28.0 [\#3290](https://github.com/harness/drone/pull/3290) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) 2.16.0 release prep [\#3295](https://github.com/harness/drone/pull/3295) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.15.0](https://github.com/harness/drone/tree/v2.15.0) (2022-10-28)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.14.0...v2.15.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui version [\#3279](https://github.com/harness/drone/pull/3279) ([d1wilko](https://github.com/d1wilko))
|
||||
- Add endpoint for allowing admins to force rotate a user's token [\#3272](https://github.com/harness/drone/pull/3272) ([ShiftedMr](https://github.com/ShiftedMr))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep v2.15.0 [\#3281](https://github.com/harness/drone/pull/3281) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.14.0](https://github.com/harness/drone/tree/v2.14.0) (2022-10-18)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.13.0...v2.14.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- \(DRON-418\) send webhook and set status for failed builds [\#3266](https://github.com/harness/drone/pull/3266) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- v2.14.0 release prep [\#3275](https://github.com/harness/drone/pull/3275) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.13.0](https://github.com/harness/drone/tree/v2.13.0) (2022-09-21)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.12.1...v2.13.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- feat: update drone-yaml module [\#3249](https://github.com/harness/drone/pull/3249) ([jimsheldon](https://github.com/jimsheldon))
|
||||
- support time zone [\#3241](https://github.com/harness/drone/pull/3241) ([zc2638](https://github.com/zc2638))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- update discourse.drone.io to community.harness.io [\#3261](https://github.com/harness/drone/pull/3261) ([kit101](https://github.com/kit101))
|
||||
- \(DRON-392\) cascade deletes on purge [\#3243](https://github.com/harness/drone/pull/3243) ([tphoney](https://github.com/tphoney))
|
||||
- Template converter, don't skip .yaml extension. [\#3242](https://github.com/harness/drone/pull/3242) ([staffanselander](https://github.com/staffanselander))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- v2.13.0 release prep [\#3268](https://github.com/harness/drone/pull/3268) ([tphoney](https://github.com/tphoney))
|
||||
- \(maint\) disable arm builds [\#3262](https://github.com/harness/drone/pull/3262) ([tphoney](https://github.com/tphoney))
|
||||
- Update links to discourse in issue template [\#3233](https://github.com/harness/drone/pull/3233) ([alikhil](https://github.com/alikhil))
|
||||
|
||||
## [v2.12.1](https://github.com/harness/drone/tree/v2.12.1) (2022-06-15)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.12.0...v2.12.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(bug\) - fix original template scripts & remove amend scripts [\#3229](https://github.com/harness/drone/pull/3229) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- \(bug\) - remove unique index on template name [\#3226](https://github.com/harness/drone/pull/3226) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Added OAuth2 token refresher for Gitlab [\#3215](https://github.com/harness/drone/pull/3215) ([EndymionWight](https://github.com/EndymionWight))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep for v2.12.1 [\#3232](https://github.com/harness/drone/pull/3232) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- \(maint\) fix starlark test on windows [\#3230](https://github.com/harness/drone/pull/3230) ([tphoney](https://github.com/tphoney))
|
||||
- \(maint\) fix unit tests so they pass on windows [\#3228](https://github.com/harness/drone/pull/3228) ([tphoney](https://github.com/tphoney))
|
||||
- Update Readme to Fix Typo [\#3223](https://github.com/harness/drone/pull/3223) ([hrittikhere](https://github.com/hrittikhere))
|
||||
- \(bug\) add unit test for comments in template file [\#3221](https://github.com/harness/drone/pull/3221) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Bump scm version to v1.24.0 [\#3219](https://github.com/harness/drone/pull/3219) ([kit101](https://github.com/kit101))
|
||||
|
||||
## [v2.12.0](https://github.com/harness/drone/tree/v2.12.0) (2022-05-16)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.11.1...v2.12.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump SCM version to v1.21.1 [\#3204](https://github.com/harness/drone/pull/3204) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump ui version [\#3202](https://github.com/harness/drone/pull/3202) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(fix\) update drone ui to 2.8.2 [\#3211](https://github.com/harness/drone/pull/3211) ([tphoney](https://github.com/tphoney))
|
||||
- \(dron-267\) correctly set parent for promotion retry [\#3210](https://github.com/harness/drone/pull/3210) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep v2.12.0 [\#3214](https://github.com/harness/drone/pull/3214) ([tphoney](https://github.com/tphoney))
|
||||
- fixing URL [\#3208](https://github.com/harness/drone/pull/3208) ([dnielsen](https://github.com/dnielsen))
|
||||
- update community information with updated links [\#3199](https://github.com/harness/drone/pull/3199) ([mrsantons](https://github.com/mrsantons))
|
||||
|
||||
## [v2.11.1](https://github.com/harness/drone/tree/v2.11.1) (2022-03-15)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.11.0...v2.11.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- ignore nil repos in list and add better debugging [\#3196](https://github.com/harness/drone/pull/3196) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) release prep for 2.11.1 [\#3197](https://github.com/harness/drone/pull/3197) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.11.0](https://github.com/harness/drone/tree/v2.11.0) (2022-03-08)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.10.0...v2.11.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump UI and SCM versions [\#3193](https://github.com/harness/drone/pull/3193) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) release prep for 2.11.0 [\#3194](https://github.com/harness/drone/pull/3194) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.10.0](https://github.com/harness/drone/tree/v2.10.0) (2022-03-03)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.9.1...v2.10.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump UI version to v2.7.0 [\#3190](https://github.com/harness/drone/pull/3190) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump UI version to v2.6.2 [\#3188](https://github.com/harness/drone/pull/3188) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) release prep for 2.10.0 [\#3191](https://github.com/harness/drone/pull/3191) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.9.1](https://github.com/harness/drone/tree/v2.9.1) (2022-01-27)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.9.0...v2.9.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- bump ui version 2.6.1 [\#3185](https://github.com/harness/drone/pull/3185) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) release prep for 2.9.1 [\#3186](https://github.com/harness/drone/pull/3186) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.9.0](https://github.com/harness/drone/tree/v2.9.0) (2022-01-26)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.8.0...v2.9.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui to v2.6.0 [\#3183](https://github.com/harness/drone/pull/3183) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep for v2.9.0 [\#3184](https://github.com/harness/drone/pull/3184) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.8.0](https://github.com/harness/drone/tree/v2.8.0) (2022-01-11)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.7.3...v2.8.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump UI to v2.5.0 [\#3180](https://github.com/harness/drone/pull/3180) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- \(feat\) ignore archive repos on sync [\#3178](https://github.com/harness/drone/pull/3178) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Datadog add the tag of 'remote:gitee' [\#3174](https://github.com/harness/drone/pull/3174) ([kit101](https://github.com/kit101))
|
||||
- Add tag filter when call build list endpoint [\#3173](https://github.com/harness/drone/pull/3173) ([michelangelomo](https://github.com/michelangelomo))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(maint\) add warning around typo for stage\_id in step struct [\#3179](https://github.com/harness/drone/pull/3179) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep v2.8.0 [\#3181](https://github.com/harness/drone/pull/3181) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.7.3](https://github.com/harness/drone/tree/v2.7.3) (2021-12-30)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.7.2...v2.7.3)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- bump go-scm to v1.16.3 [\#3175](https://github.com/harness/drone/pull/3175) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep v2.7.3 [\#3176](https://github.com/harness/drone/pull/3176) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.7.2](https://github.com/harness/drone/tree/v2.7.2) (2021-12-19)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.7.1...v2.7.2)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump go-scm to v1.16.2 [\#3169](https://github.com/harness/drone/pull/3169) ([kit101](https://github.com/kit101))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fixbug gitee provide refresher [\#3168](https://github.com/harness/drone/pull/3168) ([kit101](https://github.com/kit101))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep 2.7.2 [\#3172](https://github.com/harness/drone/pull/3172) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.7.1](https://github.com/harness/drone/tree/v2.7.1) (2021-12-17)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.7.0...v2.7.1)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fixes issue with redirects on double slashes in url [\#3170](https://github.com/harness/drone/pull/3170) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep v2.7.1 [\#3171](https://github.com/harness/drone/pull/3171) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.7.0](https://github.com/harness/drone/tree/v2.7.0) (2021-12-15)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.6.0...v2.7.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump UI to v2.4.1 [\#3167](https://github.com/harness/drone/pull/3167) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(DRON-157\) use deploy string in deployment [\#3165](https://github.com/harness/drone/pull/3165) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release v2.7.0 [\#3166](https://github.com/harness/drone/pull/3166) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.6.0](https://github.com/harness/drone/tree/v2.6.0) (2021-11-30)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.5.0...v2.6.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- Feat: implemented gitee client [\#3156](https://github.com/harness/drone/pull/3156) ([kit101](https://github.com/kit101))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep for v2.6.0 [\#3163](https://github.com/harness/drone/pull/3163) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.5.0](https://github.com/harness/drone/tree/v2.5.0) (2021-11-17)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.4.0...v2.5.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui to v2.4.0 [\#3160](https://github.com/harness/drone/pull/3160) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- add new endpoint for uploading cards [\#3159](https://github.com/harness/drone/pull/3159) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- refactor create / find / delete end points for cards [\#3158](https://github.com/harness/drone/pull/3158) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- bump ui to v2.3.1 [\#3155](https://github.com/harness/drone/pull/3155) ([d1wilko](https://github.com/d1wilko))
|
||||
- provide ability to create/read/store card data in drone server [\#3149](https://github.com/harness/drone/pull/3149) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- \(DRON-124\) adding new status endpoint [\#3143](https://github.com/harness/drone/pull/3143) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fix a typo in readme [\#3150](https://github.com/harness/drone/pull/3150) ([nothatDinger](https://github.com/nothatDinger))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release prep for v2.5.0 [\#3161](https://github.com/harness/drone/pull/3161) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
## [v2.4.0](https://github.com/harness/drone/tree/v2.4.0) (2021-09-23)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.3.1...v2.4.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui version to v2.3.0 [\#3146](https://github.com/harness/drone/pull/3146) ([d1wilko](https://github.com/d1wilko))
|
||||
- verify if the application is buildable [\#3144](https://github.com/harness/drone/pull/3144) ([marko-gacesa](https://github.com/marko-gacesa))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fixes build issue with bitbucket cloud [\#3147](https://github.com/harness/drone/pull/3147) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Fix stepLimit param in Starlark and Template OSS code [\#3141](https://github.com/harness/drone/pull/3141) ([phil-davis](https://github.com/phil-davis))
|
||||
- fix a broken link in readme [\#3140](https://github.com/harness/drone/pull/3140) ([empire](https://github.com/empire))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\)-release 2.4.0 [\#3148](https://github.com/harness/drone/pull/3148) ([d1wilko](https://github.com/d1wilko))
|
||||
- Allow jsonnet imports in pipeline configuration [\#3105](https://github.com/harness/drone/pull/3105) ([hhamalai](https://github.com/hhamalai))
|
||||
|
||||
## [v2.3.1](https://github.com/harness/drone/tree/v2.3.1) (2021-09-09)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.3.0...v2.3.1)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui to v2.2.1 - https://github.com/drone/drone-ui/blob/main/CHANGELOG.md [\#3138](https://github.com/harness/drone/pull/3138) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\)-release 2.3.1 [\#3139](https://github.com/harness/drone/pull/3139) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.3.0](https://github.com/harness/drone/tree/v2.3.0) (2021-09-09)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.2.0...v2.3.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui to v2.2.0 - https://github.com/drone/drone-ui/blob/main/CHANGELOG.md [\#3137](https://github.com/harness/drone/pull/3137) ([d1wilko](https://github.com/d1wilko))
|
||||
- Make starlark step limit configurable [\#3134](https://github.com/harness/drone/pull/3134) ([phil-davis](https://github.com/phil-davis))
|
||||
- \(feat\) drone h/a: wrapped scheduler's signal func with redis mutex [\#3130](https://github.com/harness/drone/pull/3130) ([marko-gacesa](https://github.com/marko-gacesa))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- \(fix\) trim http/s prefixes from config hostnames [\#3136](https://github.com/harness/drone/pull/3136) ([tphoney](https://github.com/tphoney))
|
||||
- \(fix\) remove unused jwt-go library [\#3129](https://github.com/harness/drone/pull/3129) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.2.0](https://github.com/harness/drone/tree/v2.2.0) (2021-09-01)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.1.0...v2.2.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- \(maint\) ui version v2.1.0 - https://github.com/drone/drone-ui/blob/main/CHANGELOG.md [\#3132](https://github.com/harness/drone/pull/3132) ([d1wilko](https://github.com/d1wilko))
|
||||
- Ability to cancel running builds, if a new commit is pushed [\#3126](https://github.com/harness/drone/pull/3126) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fix templating reg expression to match if .drone.yml contains --- characters [\#3131](https://github.com/harness/drone/pull/3131) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- add check on template extension type - throw error if invalid [\#3128](https://github.com/harness/drone/pull/3128) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\)-release 2.2.0 [\#3133](https://github.com/harness/drone/pull/3133) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Rename files with camelCase name to use snake\_case convention [\#3127](https://github.com/harness/drone/pull/3127) ([marko-gacesa](https://github.com/marko-gacesa))
|
||||
- event-stream supports timeout [\#3125](https://github.com/harness/drone/pull/3125) ([zc2638](https://github.com/zc2638))
|
||||
- \(maint\) Readme update Add Contributor Section [\#3111](https://github.com/harness/drone/pull/3111) ([mrsantons](https://github.com/mrsantons))
|
||||
|
||||
## [v2.1.0](https://github.com/harness/drone/tree/v2.1.0) (2021-08-24)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.0.6...v2.1.0)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- \(maint\) ui version v2.0.1. - https://github.com/drone/drone-ui/blob/main/CHANGELOG.md [\#3123](https://github.com/harness/drone/pull/3123) ([d1wilko](https://github.com/d1wilko))
|
||||
- add support for yaml templates [\#3120](https://github.com/harness/drone/pull/3120) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- Update error message to forbidden if user membership doesn't exist on repo [\#3122](https://github.com/harness/drone/pull/3122) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- update create template path to have namespace, instead of inside the payload [\#3121](https://github.com/harness/drone/pull/3121) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- update dependency drone/go-scm to 1.15.2 to fix gitea build problem [\#3118](https://github.com/harness/drone/pull/3118) ([sesky4](https://github.com/sesky4))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) v2.1.0 release prep [\#3124](https://github.com/harness/drone/pull/3124) ([d1wilko](https://github.com/d1wilko))
|
||||
|
||||
## [v2.0.6](https://github.com/harness/drone/tree/v2.0.6) (2021-08-17)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.0.5...v2.0.6)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- \(maint\) v2.0.6 release prep [\#3119](https://github.com/harness/drone/pull/3119) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
## [v2.0.5](https://github.com/harness/drone/tree/v2.0.5) (2021-08-17)
|
||||
|
||||
[Full Changelog](https://github.com/harness/drone/compare/v2.0.4...v2.0.5)
|
||||
|
||||
**Implemented enhancements:**
|
||||
|
||||
- bump ui version [\#3115](https://github.com/harness/drone/pull/3115) ([d1wilko](https://github.com/d1wilko))
|
||||
- bump ui version [\#3114](https://github.com/harness/drone/pull/3114) ([d1wilko](https://github.com/d1wilko))
|
||||
- Add support for nested data objects within templates [\#3110](https://github.com/harness/drone/pull/3110) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- \(feat\) redis implementation for pub-sub, log streaming and canceller [\#3108](https://github.com/harness/drone/pull/3108) ([marko-gacesa](https://github.com/marko-gacesa))
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- fix issue where map changes order therefore test randomly fails [\#3112](https://github.com/harness/drone/pull/3112) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- release 2.0.5 [\#3117](https://github.com/harness/drone/pull/3117) ([eoinmcafee00](https://github.com/eoinmcafee00))
|
||||
- Update pull\_request\_template.md [\#3107](https://github.com/harness/drone/pull/3107) ([tphoney](https://github.com/tphoney))
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [2.0.4]
|
||||
### Fixed
|
||||
- DRON-97 remove use of request animation frame to prevent high CPU on tab refocus events.
|
||||
|
||||
## [2.0.3]
|
||||
### Fixed
|
||||
- DONE-91 handle extra slashes in url. [#3009](https://github.com/drone/drone/pull/3099).
|
||||
|
||||
## [2.0.2]
|
||||
### Added
|
||||
- Merge remote-tracking branch 'origin/master'
|
||||
- prevent repository list short circuit in UI
|
||||
- remove deprecated steps from building file [#3097](https://github.com/drone/drone/pull/3097)
|
||||
- adding depends_on, image and detached fields to step [#3072](https://github.com/drone/drone/pull/3072)
|
||||
- Add ctx.build.debug boolean [#3082](https://github.com/drone/drone/pull/3082)
|
||||
- Bump github.com/google/go-jsonnet to v0.17.0 [#3084](https://github.com/drone/drone/pull/3084)
|
||||
- bump go-scm v1.15.1 [#3096](https://github.com/drone/drone/pull/3096)
|
||||
- bitbucket server build issue [#3092](https://github.com/drone/drone/pull/3092)
|
||||
- update scm version [#3091](https://github.com/drone/drone/pull/3091)
|
||||
- Limit graceful shutdown duration [#3093](https://github.com/drone/drone/pull/3093)
|
||||
- bump user interface
|
||||
- bump ui version
|
||||
- ignore skip directive for promote and rollback events
|
||||
- new feature: maximum open DB connections is configurable[#3089](https://github.com/drone/drone/pull/3089)
|
||||
- jsonnet additional parameters [#3087](https://github.com/drone/drone/pull/3087)
|
||||
- hide login button if user already authenticated
|
||||
- new feature: configuration templates [#3081](https://github.com/drone/drone/pull/3081)
|
||||
|
||||
### Fixed
|
||||
- various typos [#3088](https://github.com/drone/drone/pull/3088)
|
||||
- handle error properly if template doesn't exist [#3095](https://github.com/drone/drone/pull/3093)
|
||||
- oss build issue [#3086](https://github.com/drone/drone/pull/3086)
|
||||
- graceful shutdown [#3083](https://github.com/drone/drone/pull/3083)
|
||||
|
||||
## [2.0.1]
|
||||
### Added
|
||||
- support for configuring the internal yaml cache size.
|
||||
|
||||
## [2.0.0]
|
||||
### Added
|
||||
- feature flags for mixed-mode database encryption.
|
||||
|
||||
### Changed
|
||||
- user-interface re-design
|
||||
|
||||
### Breaking
|
||||
- removed deprecated kubernetes integration in favor of official kubernetes runner.
|
||||
- removed deprecated nomad integration in favor of official nomad runner.
|
||||
|
||||
## [1.10.1]
|
||||
### Added
|
||||
- support for repository-level concurrency limits.
|
||||
- support for gitlab and github internal visibility on initial sync.
|
||||
|
||||
### Fixed
|
||||
- create machine user with a custom API token.
|
||||
|
||||
## [1.10.0]
|
||||
### Added
|
||||
- support for starlark scripts in core.
|
||||
- support for executing pipelines in debug mode.
|
||||
|
||||
## [1.9.2]
|
||||
### Added
|
||||
- update go-scm dependency to fix
|
||||
|
||||
## [1.9.1]
|
||||
### Added
|
||||
- support for increasing the http request timeout for extensions. [#2998](https://github.com/drone/drone/pull/2998).
|
||||
- support for skipping a pipeline if the validation extension returns an ErrSkip.
|
||||
- support for blocking a pipeline if the validation extension returns an ErrBlock.
|
||||
|
||||
### Fixed
|
||||
- rollback endpoint should be available to users with write permission.
|
||||
- retrying a build should re-use custom build parameters from parent build.
|
||||
|
||||
## [1.9.0] - 2020-07-12
|
||||
### Added
|
||||
- ui support for deployment list and summary.
|
||||
- ui support for promoting and rolling back builds.
|
||||
- feature flag to use static secret when signing webhooks, from @chiraggadasc.
|
||||
|
||||
### Fixed
|
||||
- ui branch list improperly capped.
|
||||
|
||||
### Changed
|
||||
- upgrade drone/envsubst dependency
|
||||
- upgrade drone/go-scm dependency
|
||||
|
||||
## [1.8.1] - 2020-06-23
|
||||
### Fixed
|
||||
- support for gitea api pagination, repository sync hanging.
|
||||
|
||||
## [1.8.0] - 2020-06-10
|
||||
### Added
|
||||
- re-assigned repository ownership when deactivating a user.
|
||||
- re-assigned repository ownership when deleting a user.
|
||||
- de-activate a repository when deleting a user if re-assignment fails.
|
||||
- de-activate a repository when deactivating a user if re-assignment fails.
|
||||
- routine to cleanup builds stuck in a pending state.
|
||||
- routine to cleanup builds stuck in a running state.
|
||||
- private mode setting requires authentication to view public repositories.
|
||||
|
||||
### Fixed
|
||||
- canceling a build emits a sql.ErrNoRows error.
|
||||
- custom token is ignored when creating a user account via the API.
|
||||
- machine accounts with sufficient permissions can create builds via the API.
|
||||
|
||||
### Changed
|
||||
- upgraded Go toolchain to version 1.14.4.
|
||||
|
||||
## [1.7.0] - 2020-03-27
|
||||
### Added
|
||||
- endpoint to display the latest build by branch. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to display the latest build by pull request. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to display the latest build by environment. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete a branch from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete a pull request from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete an environment from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- page to view the latest build per branch.
|
||||
|
||||
### Fixed
|
||||
- sync routine not executing asynchronously, being cancelled by http context.
|
||||
- sync routine should ignore gitlab subrepositories
|
||||
- convert deploy events in 0.8 yaml to promote events.
|
||||
- do not execute cron job for disabled repositories. [#2931](https://github.com/drone/drone/issues/2931).
|
||||
- remove trailing slash from gitea url to prevent oauth2 token refresh errors, by [@cmj0121](https://github.com/cmj0121). [#2920](https://github.com/drone/drone/issues/2920).
|
||||
- disable font ligatures in build log output. [drone/drone-ui#322](https://github.com/drone/drone-ui/pull/322).
|
||||
- missing am/pm in timestamps
|
||||
|
||||
## [1.6.5] - 2020-01-29
|
||||
### Changed
|
||||
- update version of go-scm
|
||||
- update alpine version in docker images
|
||||
- use ticker for cron jobs for more accurate timing
|
||||
|
||||
## [1.6.4] - 2019-12-30
|
||||
### Added
|
||||
- optionally enable pprof endpoints for profiling, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.3] - 2019-12-10
|
||||
### Fixed
|
||||
- disable caching generated yaml files by commit sha, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Added
|
||||
- support for bitbucket skipverify, by [@toni-moreno](https://github.com/toni-moreno).
|
||||
- support for gitea skipverify, by [@toni-moreno](https://github.com/toni-moreno).
|
||||
|
||||
## [1.6.2] - 2019-11-08
|
||||
### Added
|
||||
- support for loading license contents from env, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- regression not converting legacy pipeline when using new runners, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.1] - 2019-10-17
|
||||
### Added
|
||||
- updated autocert library in support of acme v2 protocol, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- fixed nil pointer when manually adding user from api, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.0] - 2019-10-04
|
||||
### Added
|
||||
- added nsswitch to docker images
|
||||
- option to auto-cancel pending builds when newer build enqueued, by [@bradrydzewski](https://github.com/bradrydzewski). [#1980](https://github.com/drone/drone/issues/1980).
|
||||
- endpoint to list all repositories in the database, by [@bradrydzewski](https://github.com/bradrydzewski). [#2785](https://github.com/drone/drone/issues/2785).
|
||||
|
||||
### Fixed
|
||||
- improve sync to handle duplicate repository names with different unique identifiers, by [@bradrydzewski](https://github.com/bradrydzewski). [#2658](https://github.com/drone/drone/issues/2658). _You can revert to the previous sync logic with DRONE_DATABASE_LEGACY_BATCH=true_.
|
||||
|
||||
## [1.5.1] - 2019-09-30
|
||||
### Added
|
||||
- allow organization admins access to organization secret endpoints, by [@bradrydzewski](https://github.com/bradrydzewski). [#2838](https://github.com/drone/drone/issues/2838).
|
||||
|
||||
### Fixed
|
||||
- fix invalid deep links in UI for github enterprise, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ensure correct casing when manually adding user, by [@bradrydzewski](https://github.com/bradrydzewski). [#2766](https://github.com/drone/drone/issues/2766).
|
||||
|
||||
## [1.5.0] - 2019-09-28
|
||||
### Added
|
||||
- endpoint to execute a cron pipeline on-demand, by [@bradrydzewski](https://github.com/bradrydzewski). [#2781](https://github.com/drone/drone/issues/2781).
|
||||
- endpoint to list builds by branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#1495](https://github.com/drone/drone/issues/1495).
|
||||
- ignore skip comments when cron event, by [@bradrydzewski](https://github.com/bradrydzewski). [#2835](https://github.com/drone/drone/issues/2835).
|
||||
- support for admission extensions, by [@bradrydzewski](https://github.com/bradrydzewski). [#2043](https://github.com/drone/drone/issues/2043).
|
||||
- endpoint to provide link to git resources, by [@bradrydzewski](https://github.com/bradrydzewski). [#2843](https://github.com/drone/drone/issues/2843).
|
||||
- improve bitbucket status display text on new pull request screen, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- missing cron job name in user interface, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- log lines not properly wrapping in user interface, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
[#309](https://github.com/drone/drone-ui/issues/309).
|
||||
|
||||
### Breaking
|
||||
- the server now runs in multi-machine mode by default. In order to run the server in single-machine mode (agents disabled) you must set DRONE_AGENTS_DISABLED=true.
|
||||
|
||||
## [1.4.0] - 2019-09-12
|
||||
### Added
|
||||
- upgrade to Go 1.13 to resolve arm segfault, by [@KN4CK3R](https://github.com/KN4CK3R). [#2823](https://github.com/drone/drone/issues/2823).
|
||||
- configure default visibility, by [@JordanSussman](https://github.com/JordanSussman). [#2824](https://github.com/drone/drone/issues/2824).
|
||||
- configure default trusted flag, by [@vyckou](https://github.com/vyckou).
|
||||
- support for validation plugins, by [@bradrydzewski](https://github.com/bradrydzewski). [#2266](https://github.com/drone/drone/issues/2266).
|
||||
- support for conversion plugins, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- support for cron event type, by [@bradrydzewski](https://github.com/bradrydzewski). [#2705](https://github.com/drone/drone/issues/2705).
|
||||
- support for rollback event, by [@bradrydzewski](https://github.com/bradrydzewski). [#2695](https://github.com/drone/drone/issues/2695).
|
||||
- support for lets encrypt email, by [@bradrydzewski](https://github.com/bradrydzewski). [#2505](https://github.com/drone/drone/issues/2505).
|
||||
|
||||
### Removed
|
||||
- Support for basic auth as an option for Gitea, by [@techknowlogick](https://giteahub.com/techknowlogick). [#2721](https://github.com/drone/drone/issues/2721)
|
||||
|
||||
### Fixed
|
||||
- copy cron job name when restarting a cron job, by [@bradrydzewski](https://github.com/bradrydzewski). [#2760](https://github.com/drone/drone/issues/2760).
|
||||
|
||||
## [1.3.1] - 2019-08-26
|
||||
### Added
|
||||
- support for the GitHub deployment status API, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.3.0] - 2019-08-20
|
||||
### Added
|
||||
- support for storing logs in Azure Cloud Storage, by [@Lucretius](https://github.com/Lucretius). [#2788](https://github.com/drone/drone/pull/2788)
|
||||
- support for windows server 1903, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- button to view the full log file, by [@dramich](https://github.com/dramich). [drone/drone-ui#287](https://github.com/drone/drone-ui/pull/287).
|
||||
|
||||
### Fixed
|
||||
- read gogs sha from webhook, by [@marcotuna](https://github.com/marcotuna).
|
||||
- create bind volume on host if not exists, by [@bradrydzewski](https://github.com/bradrydzewski). [#2725](https://github.com/drone/drone/issues/2725).
|
||||
- preserve whitespace in build logs, by [@geek1011](https://github.com/geek1011). [drone/drone-ui#294](https://github.com/drone/drone-ui/pull/294).
|
||||
- enable log file download on firefox, by [@bobmanary](https://github.com/bobmanary). [drone/drone-ui#303](https://github.com/drone/drone-ui/pull/303)
|
||||
|
||||
### Security
|
||||
- upgraded to Go 1.12.9 due to CVE-2019-9512 and CVE-2019-9514
|
||||
|
||||
## [1.2.3] - 2019-07-30
|
||||
### Added
|
||||
|
||||
- disable github status for cron jobs
|
||||
- support for action in conditionals, by [@bradrydzewski](https://github.com/bradrydzewski). [#2685](https://github.com/drone/drone/issues/2685).
|
||||
|
||||
### Fixed
|
||||
|
||||
- improve cancel logic for dangling stages, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- improve error when kubernetes malforms the port configuration, by [@bradrydzewski](https://github.com/bradrydzewski). [#2742](https://github.com/drone/drone/issues/2742).
|
||||
- copy parameters from parent build when promoting, by [@bradrydzewski](https://github.com/bradrydzewski). [#2748](https://github.com/drone/drone/issues/2748).
|
||||
|
||||
## [1.2.2] - 2019-07-29
|
||||
### Added
|
||||
|
||||
- support for legacy environment variables
|
||||
- support for legacy workspace based on repository name
|
||||
- support for github deployment hooks
|
||||
- provide base sha for github pull requests
|
||||
- option to filter webhooks by event and type
|
||||
- upgrade drone-yaml to v1.2.2
|
||||
- upgrade drone-runtime to v1.0.7
|
||||
|
||||
### Fixed
|
||||
|
||||
- error when manually creating an empty user, by [@bradrydzewski](https://github.com/bradrydzewski). [#2738](https://github.com/drone/drone/issues/2738).
|
||||
|
||||
## [1.2.1] - 2019-06-11
|
||||
### Added
|
||||
|
||||
- support for legacy tokens to ease upgrade path, by [@bradrydzewski](https://github.com/bradrydzewski). [#2713](https://github.com/drone/drone/issues/2713).
|
||||
- include repository name and id in batch update error message, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
|
||||
- fix inconsistent base64 encoding and decoding of encrypted secrets, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-yaml to version 1.1.2 for improved 0.8 to 1.0 yaml marshal escaping.
|
||||
- update drone-yaml to version 1.1.3 for improved 0.8 to 1.0 workspace conversion.
|
||||
|
||||
## [1.2.0] - 2019-05-30
|
||||
### Added
|
||||
|
||||
- endpoint to trigger new build for default branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- endpoint to trigger new build for branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- endpoint to trigger new build for branch and sha, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- enable optional prometheus metrics guest access, by [@janberktold](https://github.com/janberktold)
|
||||
- fallback to database when logs not found in s3, by [@bradrydzewski](https://github.com/bradrydzewski). [#2689](https://github.com/drone/drone/issues/2689).
|
||||
- support for custom stage definitions and runners, by [@bradrydzewski](https://github.com/bradrydzewski). [#2680](https://github.com/drone/drone/issues/2680).
|
||||
- update drone-yaml to version 1.1.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- retrieve latest build by branch, by [@tboerger](https://github.com/tboerger).
|
||||
- copy the fork value when restarting a build, by [@bradrydzewski](https://github.com/bradrydzewski). [#2708](https://github.com/drone/drone/issues/2708).
|
||||
- make healthz available without redirect, by [@bradrydzewski](https://github.com/bradrydzewski). [#2706](https://github.com/drone/drone/issues/2706).
|
||||
|
||||
## [1.1.0] - 2019-04-23
|
||||
### Added
|
||||
|
||||
- specify a user for the pipeline step, by [@bradrydzewski](https://github.com/bradrydzewski). [#2651](https://github.com/drone/drone/issues/2651).
|
||||
- support for Gitea oauth2, by [@techknowlogick](https://github.com/techknowlogick). [#2622](https://github.com/drone/drone/pull/2622).
|
||||
- ping the docker daemon before starting the agent, by [@bradrydzewski](https://github.com/bradrydzewski). [#2495](https://github.com/drone/drone/issues/2495).
|
||||
- support for Cron job name in Yaml trigger block, by [@bradrydzewski](https://github.com/bradrydzewski). [#2628](https://github.com/drone/drone/issues/2628).
|
||||
- support for Cron job name in Yaml when block, by [@bradrydzewski](https://github.com/bradrydzewski). [#2628](https://github.com/drone/drone/issues/2628).
|
||||
- sqlite username column changed to case-insensitive, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- endpoint to purge repository from database, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- support for per-organization secrets, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- include system metadata in global webhooks, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ability to customize cookie secure flag, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-yaml from version 1.0.6 to 1.0.8.
|
||||
- update drone-runtime from version 1.0.4 to 1.0.6.
|
||||
- update go-scm from version 1.0.3 to 1.0.4.
|
||||
|
||||
### Fixed
|
||||
|
||||
- fixed error in mysql table creation syntax, from [@xuyang2](https://github.com/xuyang2). [#2677](https://github.com/drone/drone/pull/2677).
|
||||
- fixed stuck builds when upstream dependency is skipped, from [@bradrydzewski](https://github.com/bradrydzewski). [#2634](https://github.com/drone/drone/issues/2634).
|
||||
- fixed issue running steps with dependencies on failure, from [@bradrydzewski](https://github.com/bradrydzewski). [#2667](https://github.com/drone/drone/issues/2667).
|
||||
|
||||
## [1.0.1] - 2019-04-10
|
||||
### Added
|
||||
|
||||
- pass stage environment variables to pipeline steps, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update go-scm to version 1.3.0, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-runtime to version to 1.0.4, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ping docker daemon before agent starts to ensure connectivity, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
|
||||
\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
|
@ -0,0 +1,326 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [2.0.4]
|
||||
### Fixed
|
||||
- DRON-97 remove use of request animation frame to prevent high CPU on tab refocus events.
|
||||
|
||||
## [2.0.3]
|
||||
### Fixed
|
||||
- DONE-91 handle extra slashes in url. [#3009](https://github.com/drone/drone/pull/3099).
|
||||
|
||||
## [2.0.2]
|
||||
### Added
|
||||
- Merge remote-tracking branch 'origin/master'
|
||||
- prevent repository list short circuit in UI
|
||||
- remove deprecated steps from building file [#3097](https://github.com/drone/drone/pull/3097)
|
||||
- adding depends_on, image and detached fields to step [#3072](https://github.com/drone/drone/pull/3072)
|
||||
- Add ctx.build.debug boolean [#3082](https://github.com/drone/drone/pull/3082)
|
||||
- Bump github.com/google/go-jsonnet to v0.17.0 [#3084](https://github.com/drone/drone/pull/3084)
|
||||
- bump go-scm v1.15.1 [#3096](https://github.com/drone/drone/pull/3096)
|
||||
- bitbucket server build issue [#3092](https://github.com/drone/drone/pull/3092)
|
||||
- update scm version [#3091](https://github.com/drone/drone/pull/3091)
|
||||
- Limit graceful shutdown duration [#3093](https://github.com/drone/drone/pull/3093)
|
||||
- bump user interface
|
||||
- bump ui version
|
||||
- ignore skip directive for promote and rollback events
|
||||
- new feature: maximum open DB connections is configurable[#3089](https://github.com/drone/drone/pull/3089)
|
||||
- jsonnet additional parameters [#3087](https://github.com/drone/drone/pull/3087)
|
||||
- hide login button if user already authenticated
|
||||
- new feature: configuration templates [#3081](https://github.com/drone/drone/pull/3081)
|
||||
|
||||
### Fixed
|
||||
- various typos [#3088](https://github.com/drone/drone/pull/3088)
|
||||
- handle error properly if template doesn't exist [#3095](https://github.com/drone/drone/pull/3093)
|
||||
- oss build issue [#3086](https://github.com/drone/drone/pull/3086)
|
||||
- graceful shutdown [#3083](https://github.com/drone/drone/pull/3083)
|
||||
|
||||
## [2.0.1]
|
||||
### Added
|
||||
- support for configuring the internal yaml cache size.
|
||||
|
||||
## [2.0.0]
|
||||
### Added
|
||||
- feature flags for mixed-mode database encryption.
|
||||
|
||||
### Changed
|
||||
- user-interface re-design
|
||||
|
||||
### Breaking
|
||||
- removed deprecated kubernetes integration in favor of official kubernetes runner.
|
||||
- removed deprecated nomad integration in favor of official nomad runner.
|
||||
|
||||
## [1.10.1]
|
||||
### Added
|
||||
- support for repository-level concurrency limits.
|
||||
- support for gitlab and github internal visibility on initial sync.
|
||||
|
||||
### Fixed
|
||||
- create machine user with a custom API token.
|
||||
|
||||
## [1.10.0]
|
||||
### Added
|
||||
- support for starlark scripts in core.
|
||||
- support for executing pipelines in debug mode.
|
||||
|
||||
## [1.9.2]
|
||||
### Added
|
||||
- update go-scm dependency to fix
|
||||
|
||||
## [1.9.1]
|
||||
### Added
|
||||
- support for increasing the http request timeout for extensions. [#2998](https://github.com/drone/drone/pull/2998).
|
||||
- support for skipping a pipeline if the validation extension returns an ErrSkip.
|
||||
- support for blocking a pipeline if the validation extension returns an ErrBlock.
|
||||
|
||||
### Fixed
|
||||
- rollback endpoint should be available to users with write permission.
|
||||
- retrying a build should re-use custom build parameters from parent build.
|
||||
|
||||
## [1.9.0] - 2020-07-12
|
||||
### Added
|
||||
- ui support for deployment list and summary.
|
||||
- ui support for promoting and rolling back builds.
|
||||
- feature flag to use static secret when signing webhooks, from @chiraggadasc.
|
||||
|
||||
### Fixed
|
||||
- ui branch list improperly capped.
|
||||
|
||||
### Changed
|
||||
- upgrade drone/envsubst dependency
|
||||
- upgrade drone/go-scm dependency
|
||||
|
||||
## [1.8.1] - 2020-06-23
|
||||
### Fixed
|
||||
- support for gitea api pagination, repository sync hanging.
|
||||
|
||||
## [1.8.0] - 2020-06-10
|
||||
### Added
|
||||
- re-assigned repository ownership when deactivating a user.
|
||||
- re-assigned repository ownership when deleting a user.
|
||||
- de-activate a repository when deleting a user if re-assignment fails.
|
||||
- de-activate a repository when deactivating a user if re-assignment fails.
|
||||
- routine to cleanup builds stuck in a pending state.
|
||||
- routine to cleanup builds stuck in a running state.
|
||||
- private mode setting requires authentication to view public repositories.
|
||||
|
||||
### Fixed
|
||||
- canceling a build emits a sql.ErrNoRows error.
|
||||
- custom token is ignored when creating a user account via the API.
|
||||
- machine accounts with sufficient permissions can create builds via the API.
|
||||
|
||||
### Changed
|
||||
- upgraded Go toolchain to version 1.14.4.
|
||||
|
||||
## [1.7.0] - 2020-03-27
|
||||
### Added
|
||||
- endpoint to display the latest build by branch. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to display the latest build by pull request. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to display the latest build by environment. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete a branch from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete a pull request from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- endpoint to delete an environment from the index. [#2940](https://github.com/drone/drone/pull/2940).
|
||||
- page to view the latest build per branch.
|
||||
|
||||
### Fixed
|
||||
- sync routine not executing asynchronously, being cancelled by http context.
|
||||
- sync routine should ignore gitlab subrepositories
|
||||
- convert deploy events in 0.8 yaml to promote events.
|
||||
- do not execute cron job for disabled repositories. [#2931](https://github.com/drone/drone/issues/2931).
|
||||
- remove trailing slash from gitea url to prevent oauth2 token refresh errors, by [@cmj0121](https://github.com/cmj0121). [#2920](https://github.com/drone/drone/issues/2920).
|
||||
- disable font ligatures in build log output. [drone/drone-ui#322](https://github.com/drone/drone-ui/pull/322).
|
||||
- missing am/pm in timestamps
|
||||
|
||||
## [1.6.5] - 2020-01-29
|
||||
### Changed
|
||||
- update version of go-scm
|
||||
- update alpine version in docker images
|
||||
- use ticker for cron jobs for more accurate timing
|
||||
|
||||
## [1.6.4] - 2019-12-30
|
||||
### Added
|
||||
- optionally enable pprof endpoints for profiling, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.3] - 2019-12-10
|
||||
### Fixed
|
||||
- disable caching generated yaml files by commit sha, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Added
|
||||
- support for bitbucket skipverify, by [@toni-moreno](https://github.com/toni-moreno).
|
||||
- support for gitea skipverify, by [@toni-moreno](https://github.com/toni-moreno).
|
||||
|
||||
## [1.6.2] - 2019-11-08
|
||||
### Added
|
||||
- support for loading license contents from env, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- regression not converting legacy pipeline when using new runners, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.1] - 2019-10-17
|
||||
### Added
|
||||
- updated autocert library in support of acme v2 protocol, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- fixed nil pointer when manually adding user from api, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.6.0] - 2019-10-04
|
||||
### Added
|
||||
- added nsswitch to docker images
|
||||
- option to auto-cancel pending builds when newer build enqueued, by [@bradrydzewski](https://github.com/bradrydzewski). [#1980](https://github.com/drone/drone/issues/1980).
|
||||
- endpoint to list all repositories in the database, by [@bradrydzewski](https://github.com/bradrydzewski). [#2785](https://github.com/drone/drone/issues/2785).
|
||||
|
||||
### Fixed
|
||||
- improve sync to handle duplicate repository names with different unique identifiers, by [@bradrydzewski](https://github.com/bradrydzewski). [#2658](https://github.com/drone/drone/issues/2658). _You can revert to the previous sync logic with DRONE_DATABASE_LEGACY_BATCH=true_.
|
||||
|
||||
## [1.5.1] - 2019-09-30
|
||||
### Added
|
||||
- allow organization admins access to organization secret endpoints, by [@bradrydzewski](https://github.com/bradrydzewski). [#2838](https://github.com/drone/drone/issues/2838).
|
||||
|
||||
### Fixed
|
||||
- fix invalid deep links in UI for github enterprise, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ensure correct casing when manually adding user, by [@bradrydzewski](https://github.com/bradrydzewski). [#2766](https://github.com/drone/drone/issues/2766).
|
||||
|
||||
## [1.5.0] - 2019-09-28
|
||||
### Added
|
||||
- endpoint to execute a cron pipeline on-demand, by [@bradrydzewski](https://github.com/bradrydzewski). [#2781](https://github.com/drone/drone/issues/2781).
|
||||
- endpoint to list builds by branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#1495](https://github.com/drone/drone/issues/1495).
|
||||
- ignore skip comments when cron event, by [@bradrydzewski](https://github.com/bradrydzewski). [#2835](https://github.com/drone/drone/issues/2835).
|
||||
- support for admission extensions, by [@bradrydzewski](https://github.com/bradrydzewski). [#2043](https://github.com/drone/drone/issues/2043).
|
||||
- endpoint to provide link to git resources, by [@bradrydzewski](https://github.com/bradrydzewski). [#2843](https://github.com/drone/drone/issues/2843).
|
||||
- improve bitbucket status display text on new pull request screen, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
- missing cron job name in user interface, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- log lines not properly wrapping in user interface, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
[#309](https://github.com/drone/drone-ui/issues/309).
|
||||
|
||||
### Breaking
|
||||
- the server now runs in multi-machine mode by default. In order to run the server in single-machine mode (agents disabled) you must set DRONE_AGENTS_DISABLED=true.
|
||||
|
||||
## [1.4.0] - 2019-09-12
|
||||
### Added
|
||||
- upgrade to Go 1.13 to resolve arm segfault, by [@KN4CK3R](https://github.com/KN4CK3R). [#2823](https://github.com/drone/drone/issues/2823).
|
||||
- configure default visibility, by [@JordanSussman](https://github.com/JordanSussman). [#2824](https://github.com/drone/drone/issues/2824).
|
||||
- configure default trusted flag, by [@vyckou](https://github.com/vyckou).
|
||||
- support for validation plugins, by [@bradrydzewski](https://github.com/bradrydzewski). [#2266](https://github.com/drone/drone/issues/2266).
|
||||
- support for conversion plugins, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- support for cron event type, by [@bradrydzewski](https://github.com/bradrydzewski). [#2705](https://github.com/drone/drone/issues/2705).
|
||||
- support for rollback event, by [@bradrydzewski](https://github.com/bradrydzewski). [#2695](https://github.com/drone/drone/issues/2695).
|
||||
- support for lets encrypt email, by [@bradrydzewski](https://github.com/bradrydzewski). [#2505](https://github.com/drone/drone/issues/2505).
|
||||
|
||||
### Removed
|
||||
- Support for basic auth as an option for Gitea, by [@techknowlogick](https://giteahub.com/techknowlogick). [#2721](https://github.com/drone/drone/issues/2721)
|
||||
|
||||
### Fixed
|
||||
- copy cron job name when restarting a cron job, by [@bradrydzewski](https://github.com/bradrydzewski). [#2760](https://github.com/drone/drone/issues/2760).
|
||||
|
||||
## [1.3.1] - 2019-08-26
|
||||
### Added
|
||||
- support for the GitHub deployment status API, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
## [1.3.0] - 2019-08-20
|
||||
### Added
|
||||
- support for storing logs in Azure Cloud Storage, by [@Lucretius](https://github.com/Lucretius). [#2788](https://github.com/drone/drone/pull/2788)
|
||||
- support for windows server 1903, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- button to view the full log file, by [@dramich](https://github.com/dramich). [drone/drone-ui#287](https://github.com/drone/drone-ui/pull/287).
|
||||
|
||||
### Fixed
|
||||
- read gogs sha from webhook, by [@marcotuna](https://github.com/marcotuna).
|
||||
- create bind volume on host if not exists, by [@bradrydzewski](https://github.com/bradrydzewski). [#2725](https://github.com/drone/drone/issues/2725).
|
||||
- preserve whitespace in build logs, by [@geek1011](https://github.com/geek1011). [drone/drone-ui#294](https://github.com/drone/drone-ui/pull/294).
|
||||
- enable log file download on firefox, by [@bobmanary](https://github.com/bobmanary). [drone/drone-ui#303](https://github.com/drone/drone-ui/pull/303)
|
||||
|
||||
### Security
|
||||
- upgraded to Go 1.12.9 due to CVE-2019-9512 and CVE-2019-9514
|
||||
|
||||
## [1.2.3] - 2019-07-30
|
||||
### Added
|
||||
|
||||
- disable github status for cron jobs
|
||||
- support for action in conditionals, by [@bradrydzewski](https://github.com/bradrydzewski). [#2685](https://github.com/drone/drone/issues/2685).
|
||||
|
||||
### Fixed
|
||||
|
||||
- improve cancel logic for dangling stages, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- improve error when kubernetes malforms the port configuration, by [@bradrydzewski](https://github.com/bradrydzewski). [#2742](https://github.com/drone/drone/issues/2742).
|
||||
- copy parameters from parent build when promoting, by [@bradrydzewski](https://github.com/bradrydzewski). [#2748](https://github.com/drone/drone/issues/2748).
|
||||
|
||||
## [1.2.2] - 2019-07-29
|
||||
### Added
|
||||
|
||||
- support for legacy environment variables
|
||||
- support for legacy workspace based on repository name
|
||||
- support for github deployment hooks
|
||||
- provide base sha for github pull requests
|
||||
- option to filter webhooks by event and type
|
||||
- upgrade drone-yaml to v1.2.2
|
||||
- upgrade drone-runtime to v1.0.7
|
||||
|
||||
### Fixed
|
||||
|
||||
- error when manually creating an empty user, by [@bradrydzewski](https://github.com/bradrydzewski). [#2738](https://github.com/drone/drone/issues/2738).
|
||||
|
||||
## [1.2.1] - 2019-06-11
|
||||
### Added
|
||||
|
||||
- support for legacy tokens to ease upgrade path, by [@bradrydzewski](https://github.com/bradrydzewski). [#2713](https://github.com/drone/drone/issues/2713).
|
||||
- include repository name and id in batch update error message, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
|
||||
### Fixed
|
||||
|
||||
- fix inconsistent base64 encoding and decoding of encrypted secrets, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-yaml to version 1.1.2 for improved 0.8 to 1.0 yaml marshal escaping.
|
||||
- update drone-yaml to version 1.1.3 for improved 0.8 to 1.0 workspace conversion.
|
||||
|
||||
## [1.2.0] - 2019-05-30
|
||||
### Added
|
||||
|
||||
- endpoint to trigger new build for default branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- endpoint to trigger new build for branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- endpoint to trigger new build for branch and sha, by [@bradrydzewski](https://github.com/bradrydzewski). [#2679](https://github.com/drone/drone/issues/2679).
|
||||
- enable optional prometheus metrics guest access, by [@janberktold](https://github.com/janberktold)
|
||||
- fallback to database when logs not found in s3, by [@bradrydzewski](https://github.com/bradrydzewski). [#2689](https://github.com/drone/drone/issues/2689).
|
||||
- support for custom stage definitions and runners, by [@bradrydzewski](https://github.com/bradrydzewski). [#2680](https://github.com/drone/drone/issues/2680).
|
||||
- update drone-yaml to version 1.1.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- retrieve latest build by branch, by [@tboerger](https://github.com/tboerger).
|
||||
- copy the fork value when restarting a build, by [@bradrydzewski](https://github.com/bradrydzewski). [#2708](https://github.com/drone/drone/issues/2708).
|
||||
- make healthz available without redirect, by [@bradrydzewski](https://github.com/bradrydzewski). [#2706](https://github.com/drone/drone/issues/2706).
|
||||
|
||||
## [1.1.0] - 2019-04-23
|
||||
### Added
|
||||
|
||||
- specify a user for the pipeline step, by [@bradrydzewski](https://github.com/bradrydzewski). [#2651](https://github.com/drone/drone/issues/2651).
|
||||
- support for Gitea oauth2, by [@techknowlogick](https://github.com/techknowlogick). [#2622](https://github.com/drone/drone/pull/2622).
|
||||
- ping the docker daemon before starting the agent, by [@bradrydzewski](https://github.com/bradrydzewski). [#2495](https://github.com/drone/drone/issues/2495).
|
||||
- support for Cron job name in Yaml trigger block, by [@bradrydzewski](https://github.com/bradrydzewski). [#2628](https://github.com/drone/drone/issues/2628).
|
||||
- support for Cron job name in Yaml when block, by [@bradrydzewski](https://github.com/bradrydzewski). [#2628](https://github.com/drone/drone/issues/2628).
|
||||
- sqlite username column changed to case-insensitive, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- endpoint to purge repository from database, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- support for per-organization secrets, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- include system metadata in global webhooks, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ability to customize cookie secure flag, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-yaml from version 1.0.6 to 1.0.8.
|
||||
- update drone-runtime from version 1.0.4 to 1.0.6.
|
||||
- update go-scm from version 1.0.3 to 1.0.4.
|
||||
|
||||
### Fixed
|
||||
|
||||
- fixed error in mysql table creation syntax, from [@xuyang2](https://github.com/xuyang2). [#2677](https://github.com/drone/drone/pull/2677).
|
||||
- fixed stuck builds when upstream dependency is skipped, from [@bradrydzewski](https://github.com/bradrydzewski). [#2634](https://github.com/drone/drone/issues/2634).
|
||||
- fixed issue running steps with dependencies on failure, from [@bradrydzewski](https://github.com/bradrydzewski). [#2667](https://github.com/drone/drone/issues/2667).
|
||||
|
||||
## [1.0.1] - 2019-04-10
|
||||
### Added
|
||||
|
||||
- pass stage environment variables to pipeline steps, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update go-scm to version 1.3.0, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- update drone-runtime to version to 1.0.4, by [@bradrydzewski](https://github.com/bradrydzewski).
|
||||
- ping docker daemon before agent starts to ensure connectivity, by [@bradrydzewski](https://github.com/bradrydzewski).
|
@ -0,0 +1,89 @@
|
||||
Copyright 2019 Drone.IO, Inc.
|
||||
|
||||
The Drone Community Edition is licensed under the Apache License,
|
||||
Version 2.0 (the "Apache License"). You may obtain a copy of the
|
||||
Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Drone Enterprise Edition is licensed under the Drone
|
||||
Non-Commercial License (the "Non-Commercial License"). A copy of
|
||||
the Non-Commercial License is provided below.
|
||||
|
||||
The source files in this repository have a header indicating
|
||||
which license they are under. The BUILDING_OSS file provides
|
||||
instructions for creating the Community Edition distribution
|
||||
subject to the terms of the Apache License.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Drone Non-Commercial License
|
||||
|
||||
Contributor: Drone.IO, Inc.
|
||||
|
||||
Source Code: https://github.com/harness/drone
|
||||
|
||||
This license lets you use and share this software for free,
|
||||
with a trial-length time limit on commercial use. Specifically:
|
||||
|
||||
If you follow the rules below, you may do everything with this
|
||||
software that would otherwise infringe either the contributor's
|
||||
copyright in it, any patent claim the contributor can license
|
||||
that covers this software as of the contributor's latest
|
||||
contribution, or both.
|
||||
|
||||
1. You must limit use of this software in any manner primarily
|
||||
intended for or directed toward commercial advantage or
|
||||
private monetary compensation to a trial period of 32
|
||||
consecutive calendar days. This limit does not apply to use in
|
||||
developing feedback, modifications, or extensions that you
|
||||
contribute back to those giving this license.
|
||||
|
||||
2. Ensure everyone who gets a copy of this software from you, in
|
||||
source code or any other form, gets the text of this license
|
||||
and the contributor and source code lines above.
|
||||
|
||||
3. Do not make any legal claim against anyone for infringing any
|
||||
patent claim they would infringe by using this software alone,
|
||||
accusing this software, with or without changes, alone or as
|
||||
part of a larger application.
|
||||
|
||||
You are excused for unknowingly breaking rule 1 if you stop
|
||||
doing anything requiring this license within 30 days of
|
||||
learning you broke the rule.
|
||||
|
||||
**This software comes as is, without any warranty at all. As far
|
||||
as the law allows, the contributor will not be liable for any
|
||||
damages related to this software or this license, for any kind of
|
||||
legal claim.**
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Waiver: Individual and Small Business
|
||||
|
||||
Contributor waives the terms of rule 1 for companies meeting all
|
||||
the following criteria, counting all subsidiaries and affiliated
|
||||
entities as one:
|
||||
|
||||
1. worldwide annual gross revenue under $5 million US dollars,
|
||||
per generally accepted accounting principles
|
||||
|
||||
2. less than $5 million US dollars in all-time aggregate debt and
|
||||
equity financing
|
||||
|
||||
Contributor will not revoke this waiver, but may change terms for
|
||||
future versions of the software.
|
||||
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Waiver: Low Usage
|
||||
|
||||
Contributor waives the terms of rule 1 for companies meeting all
|
||||
the following criteria, counting all subsidiaries and affiliated
|
||||
entities as one:
|
||||
|
||||
1. less than 5,000 total pipelines executed using this software
|
||||
in the immediately preceding, year-long period
|
||||
|
||||
Contributor will not revoke this waiver, but may change terms for
|
||||
future versions of the software.
|
@ -0,0 +1,14 @@
|
||||
Drone
|
||||
Copyright 2019 Drone.IO, Inc
|
||||
|
||||
This product includes software developed at Drone.IO, Inc.
|
||||
(http://drone.io/).
|
||||
|
||||
This product includes software developed by Docker, Inc.
|
||||
(https://www.docker.com/).
|
||||
|
||||
This product includes software developed by Canonical Ltd.
|
||||
(https://www.canonical.com/).
|
||||
|
||||
This product includes software developed at CoreOS, Inc.
|
||||
(http://www.coreos.com/).
|
@ -0,0 +1,129 @@
|
||||
# https://taskfile.org
|
||||
|
||||
version: '2'
|
||||
|
||||
tasks:
|
||||
install:
|
||||
dir: cmd/drone-server
|
||||
cmds: [ go install -v ]
|
||||
env:
|
||||
GO111MODULE: on
|
||||
|
||||
build:
|
||||
cmds:
|
||||
- task: build-base
|
||||
vars: { name: server }
|
||||
|
||||
build-base:
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: amd64
|
||||
CGO_ENABLED: '0'
|
||||
GO111MODULE: 'on'
|
||||
cmds:
|
||||
- cmd: >
|
||||
go build -o release/linux/amd64/drone-{{.name}}
|
||||
github.com/drone/drone/cmd/drone-{{.name}}
|
||||
|
||||
cleanup:
|
||||
cmds:
|
||||
- rm -rf release
|
||||
|
||||
docker:
|
||||
cmds:
|
||||
- task: docker-base
|
||||
vars: { name: server, image: drone/drone }
|
||||
|
||||
docker-base:
|
||||
vars:
|
||||
GIT_BRANCH:
|
||||
sh: git rev-parse --abbrev-ref HEAD
|
||||
cmds:
|
||||
- cmd: docker rmi {{.image}}
|
||||
ignore_error: true
|
||||
- cmd: docker rmi {{.image}}:{{.GIT_BRANCH}}
|
||||
ignore_error: true
|
||||
- cmd: >
|
||||
docker build --rm
|
||||
-f docker/Dockerfile.{{.name}}.linux.amd64
|
||||
-t {{.image}} .
|
||||
- cmd: >
|
||||
docker tag {{.image}} {{.image}}:{{.GIT_BRANCH}}
|
||||
|
||||
test:
|
||||
cmds:
|
||||
- go test ./...
|
||||
env:
|
||||
GO111MODULE: 'on'
|
||||
|
||||
test-mysql:
|
||||
env:
|
||||
DRONE_DATABASE_DRIVER: mysql
|
||||
DRONE_DATABASE_DATASOURCE: root@tcp(localhost:3306)/test?parseTime=true
|
||||
GO111MODULE: 'on'
|
||||
cmds:
|
||||
- cmd: docker kill mysql
|
||||
silent: true
|
||||
ignore_error: true
|
||||
- cmd: >
|
||||
docker run
|
||||
-p 3306:3306
|
||||
--env MYSQL_DATABASE=test
|
||||
--env MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
--name mysql
|
||||
--detach
|
||||
--rm
|
||||
mysql:5.7
|
||||
--character-set-server=utf8mb4
|
||||
--collation-server=utf8mb4_unicode_ci
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/batch
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/batch2
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/build
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/card
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/cron
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/logs
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/perm
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/repos
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/secret
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/step
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/template
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/user
|
||||
- cmd: docker kill mysql
|
||||
|
||||
test-postgres:
|
||||
env:
|
||||
DRONE_DATABASE_DRIVER: postgres
|
||||
DRONE_DATABASE_DATASOURCE: host=localhost user=postgres password=postgres dbname=postgres sslmode=disable
|
||||
GO111MODULE: 'on'
|
||||
cmds:
|
||||
- cmd: docker kill postgres
|
||||
ignore_error: true
|
||||
silent: false
|
||||
- silent: false
|
||||
cmd: >
|
||||
docker run
|
||||
-p 5432:5432
|
||||
--env POSTGRES_PASSWORD=postgres
|
||||
--env POSTGRES_USER=postgres
|
||||
--name postgres
|
||||
--detach
|
||||
--rm
|
||||
postgres:9-alpine
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/batch
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/batch2
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/build
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/card
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/cron
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/logs
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/perm
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/repos
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/secret
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/secret/global
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/stage
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/step
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/template
|
||||
- cmd: go test -count=1 github.com/drone/drone/store/user
|
||||
- cmd: docker kill postgres
|
||||
silent: true
|
@ -0,0 +1,123 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/logger"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var errMissingToken = errors.New("You must provide the machine account token")
|
||||
|
||||
// New returns a new account bootstrapper.
|
||||
func New(users core.UserStore) *Bootstrapper {
|
||||
return &Bootstrapper{
|
||||
users: users,
|
||||
}
|
||||
}
|
||||
|
||||
// Bootstrapper bootstraps the system with the initial account.
|
||||
type Bootstrapper struct {
|
||||
users core.UserStore
|
||||
}
|
||||
|
||||
// Bootstrap creates the user account. If the account already exists,
|
||||
// no account is created, and a nil error is returned.
|
||||
func (b *Bootstrapper) Bootstrap(ctx context.Context, user *core.User) error {
|
||||
if user.Login == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log := logrus.WithFields(
|
||||
logrus.Fields{
|
||||
"login": user.Login,
|
||||
"admin": user.Admin,
|
||||
"machine": user.Machine,
|
||||
"token": user.Hash,
|
||||
},
|
||||
)
|
||||
|
||||
log.Debugln("bootstrap: create account")
|
||||
|
||||
existingUser, err := b.users.FindLogin(ctx, user.Login)
|
||||
if err == nil {
|
||||
ctx = logger.WithContext(ctx, log)
|
||||
return b.update(ctx, user, existingUser)
|
||||
}
|
||||
|
||||
if user.Machine && user.Hash == "" {
|
||||
log.Errorln("bootstrap: cannot create account, missing token")
|
||||
return errMissingToken
|
||||
}
|
||||
|
||||
user.Active = true
|
||||
user.Created = time.Now().Unix()
|
||||
user.Updated = time.Now().Unix()
|
||||
if user.Hash == "" {
|
||||
user.Hash = uniuri.NewLen(32)
|
||||
}
|
||||
|
||||
err = b.users.Create(ctx, user)
|
||||
if err != nil {
|
||||
log = log.WithError(err)
|
||||
log.Errorln("bootstrap: cannot create account")
|
||||
return err
|
||||
}
|
||||
|
||||
log = log.WithField("token", user.Hash)
|
||||
log.Infoln("bootstrap: account created")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Bootstrapper) update(ctx context.Context, src, dst *core.User) error {
|
||||
log := logger.FromContext(ctx)
|
||||
log.Debugln("bootstrap: updating account")
|
||||
var updated bool
|
||||
if src.Hash != dst.Hash && src.Hash != "" {
|
||||
log.Infoln("bootstrap: found updated user token")
|
||||
dst.Hash = src.Hash
|
||||
updated = true
|
||||
}
|
||||
if src.Machine != dst.Machine {
|
||||
log.Infoln("bootstrap: found updated machine flag")
|
||||
dst.Machine = src.Machine
|
||||
updated = true
|
||||
}
|
||||
if src.Admin != dst.Admin {
|
||||
log.Infoln("bootstrap: found updated admin flag")
|
||||
dst.Admin = src.Admin
|
||||
updated = true
|
||||
}
|
||||
if !updated {
|
||||
log.Debugln("bootstrap: account already up-to-date")
|
||||
return nil
|
||||
}
|
||||
dst.Updated = time.Now().Unix()
|
||||
err := b.users.Update(ctx, dst)
|
||||
if err != nil {
|
||||
log = log.WithError(err)
|
||||
log.Errorln("bootstrap: cannot update account")
|
||||
return err
|
||||
}
|
||||
log.Infoln("bootstrap: account successfully updated")
|
||||
return nil
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/mock"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var noContext = context.TODO()
|
||||
|
||||
func init() {
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
}
|
||||
|
||||
func TestBootstrap(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: true,
|
||||
Admin: true,
|
||||
Hash: uniuri.NewLen(32),
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(nil, sql.ErrNoRows)
|
||||
store.EXPECT().Create(gomock.Any(), dummyUser).Return(nil)
|
||||
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_GenerateHash(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: false,
|
||||
Admin: true,
|
||||
Hash: "",
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(nil, sql.ErrNoRows)
|
||||
store.EXPECT().Create(gomock.Any(), dummyUser).Return(nil)
|
||||
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if got, want := len(dummyUser.Hash), 32; got != want {
|
||||
t.Errorf("Want generated hash length %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_Empty(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "",
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_Exists_WithoutUpdates(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: true,
|
||||
Admin: true,
|
||||
Hash: uniuri.NewLen(32),
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(dummyUser, nil)
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_Exists_WithUpdates(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: true,
|
||||
Admin: true,
|
||||
Hash: uniuri.NewLen(32),
|
||||
}
|
||||
existingUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: false,
|
||||
Admin: false,
|
||||
Hash: uniuri.NewLen(32),
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(existingUser, nil)
|
||||
store.EXPECT().Update(gomock.Any(), existingUser).Return(nil)
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_MissingTokenError(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: true,
|
||||
Admin: true,
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(nil, sql.ErrNoRows)
|
||||
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != errMissingToken {
|
||||
t.Errorf("Expect missing token error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrap_CreateError(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
dummyUser := &core.User{
|
||||
Login: "octocat",
|
||||
Machine: true,
|
||||
Admin: true,
|
||||
Hash: uniuri.NewLen(32),
|
||||
}
|
||||
|
||||
store := mock.NewMockUserStore(controller)
|
||||
store.EXPECT().FindLogin(gomock.Any(), dummyUser.Login).Return(nil, sql.ErrNoRows)
|
||||
store.EXPECT().Create(gomock.Any(), dummyUser).Return(sql.ErrConnDone)
|
||||
|
||||
err := New(store).Bootstrap(noContext, dummyUser)
|
||||
if err != sql.ErrConnDone {
|
||||
t.Errorf("Expect error creating user")
|
||||
}
|
||||
}
|
@ -0,0 +1,644 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dchest/uniuri"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// IMPORTANT please do not add new configuration parameters unless it has
|
||||
// been discussed on the mailing list. We are attempting to reduce the
|
||||
// number of configuration parameters, and may reject pull requests that
|
||||
// introduce new parameters. (mailing list https://community.harness.io)
|
||||
|
||||
// default runner hostname.
|
||||
var hostname string
|
||||
|
||||
func init() {
|
||||
hostname, _ = os.Hostname()
|
||||
if hostname == "" {
|
||||
hostname = "localhost"
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// Config provides the system configuration.
|
||||
Config struct {
|
||||
License string `envconfig:"DRONE_LICENSE"`
|
||||
|
||||
Authn Authentication
|
||||
Agent Agent
|
||||
AzureBlob AzureBlob
|
||||
Convert Convert
|
||||
Cleanup Cleanup
|
||||
Cron Cron
|
||||
Cloning Cloning
|
||||
Database Database
|
||||
Datadog Datadog
|
||||
Docker Docker
|
||||
HTTP HTTP
|
||||
Jsonnet Jsonnet
|
||||
Starlark Starlark
|
||||
Logging Logging
|
||||
Prometheus Prometheus
|
||||
Proxy Proxy
|
||||
Redis Redis
|
||||
Registration Registration
|
||||
Registries Registries
|
||||
Repository Repository
|
||||
Runner Runner
|
||||
RPC RPC
|
||||
S3 S3
|
||||
Secrets Secrets
|
||||
Server Server
|
||||
Session Session
|
||||
Status Status
|
||||
Users Users
|
||||
Validate Validate
|
||||
Webhook Webhook
|
||||
Yaml Yaml
|
||||
|
||||
// Remote configurations
|
||||
Bitbucket Bitbucket
|
||||
Gitea Gitea
|
||||
Github Github
|
||||
GitLab GitLab
|
||||
Gogs Gogs
|
||||
Stash Stash
|
||||
Gitee Gitee
|
||||
}
|
||||
|
||||
// Cloning provides the cloning configuration.
|
||||
Cloning struct {
|
||||
AlwaysAuth bool `envconfig:"DRONE_GIT_ALWAYS_AUTH"`
|
||||
Username string `envconfig:"DRONE_GIT_USERNAME"`
|
||||
Password string `envconfig:"DRONE_GIT_PASSWORD"`
|
||||
Image string `envconfig:"DRONE_GIT_IMAGE"`
|
||||
Pull string `envconfig:"DRONE_GIT_IMAGE_PULL" default:"IfNotExists"`
|
||||
}
|
||||
|
||||
Cleanup struct {
|
||||
Disabled bool `envconfig:"DRONE_CLEANUP_DISABLED"`
|
||||
Interval time.Duration `envconfig:"DRONE_CLEANUP_INTERVAL" default:"24h"`
|
||||
Running time.Duration `envconfig:"DRONE_CLEANUP_DEADLINE_RUNNING" default:"24h"`
|
||||
Pending time.Duration `envconfig:"DRONE_CLEANUP_DEADLINE_PENDING" default:"24h"`
|
||||
Buffer time.Duration `envconfig:"DRONE_CLEANUP_BUFFER" default:"30m"`
|
||||
}
|
||||
|
||||
// Cron provides the cron configuration.
|
||||
Cron struct {
|
||||
Disabled bool `envconfig:"DRONE_CRON_DISABLED"`
|
||||
Interval time.Duration `envconfig:"DRONE_CRON_INTERVAL" default:"30m"`
|
||||
}
|
||||
|
||||
// Database provides the database configuration.
|
||||
Database struct {
|
||||
Driver string `envconfig:"DRONE_DATABASE_DRIVER" default:"sqlite3"`
|
||||
Datasource string `envconfig:"DRONE_DATABASE_DATASOURCE" default:"core.sqlite"`
|
||||
Secret string `envconfig:"DRONE_DATABASE_SECRET"`
|
||||
MaxConnections int `envconfig:"DRONE_DATABASE_MAX_CONNECTIONS" default:"0"`
|
||||
|
||||
// Feature flag
|
||||
LegacyBatch bool `envconfig:"DRONE_DATABASE_LEGACY_BATCH"`
|
||||
|
||||
// Feature flag
|
||||
EncryptUserTable bool `envconfig:"DRONE_DATABASE_ENCRYPT_USER_TABLE"`
|
||||
EncryptMixedContent bool `envconfig:"DRONE_DATABASE_ENCRYPT_MIXED_MODE"`
|
||||
}
|
||||
|
||||
// Docker provides docker configuration
|
||||
Docker struct {
|
||||
Config string `envconfig:"DRONE_DOCKER_CONFIG"`
|
||||
}
|
||||
|
||||
// Datadog provides datadog configuration
|
||||
Datadog struct {
|
||||
Enabled bool `envconfig:"DRONE_DATADOG_ENABLED"`
|
||||
Endpoint string `envconfig:"DRONE_DATADOG_ENDPOINT"`
|
||||
Token string `envconfig:"DRONE_DATADOG_TOKEN"`
|
||||
}
|
||||
|
||||
// Jsonnet configures the jsonnet plugin
|
||||
Jsonnet struct {
|
||||
Enabled bool `envconfig:"DRONE_JSONNET_ENABLED"`
|
||||
ImportLimit int `envconfig:"DRONE_JSONNET_IMPORT_LIMIT" default:"0"`
|
||||
}
|
||||
|
||||
// Starlark configures the starlark plugin
|
||||
Starlark struct {
|
||||
Enabled bool `envconfig:"DRONE_STARLARK_ENABLED"`
|
||||
StepLimit uint64 `envconfig:"DRONE_STARLARK_STEP_LIMIT"`
|
||||
SizeLimit uint64 `envconfig:"DRONE_STARLARK_SIZE_LIMIT" default:"0"`
|
||||
}
|
||||
|
||||
// License provides license configuration
|
||||
License struct {
|
||||
Key string `envconfig:"DRONE_LICENSE"`
|
||||
Endpoint string `envconfig:"DRONE_LICENSE_ENDPOINT"`
|
||||
}
|
||||
|
||||
// Logging provides the logging configuration.
|
||||
Logging struct {
|
||||
Debug bool `envconfig:"DRONE_LOGS_DEBUG"`
|
||||
Trace bool `envconfig:"DRONE_LOGS_TRACE"`
|
||||
Color bool `envconfig:"DRONE_LOGS_COLOR"`
|
||||
Pretty bool `envconfig:"DRONE_LOGS_PRETTY"`
|
||||
Text bool `envconfig:"DRONE_LOGS_TEXT"`
|
||||
}
|
||||
|
||||
// Prometheus provides the prometheus configuration.
|
||||
Prometheus struct {
|
||||
EnableAnonymousAccess bool `envconfig:"DRONE_PROMETHEUS_ANONYMOUS_ACCESS" default:"false"`
|
||||
}
|
||||
|
||||
// Redis provides the redis configuration.
|
||||
Redis struct {
|
||||
ConnectionString string `envconfig:"DRONE_REDIS_CONNECTION"`
|
||||
Addr string `envconfig:"DRONE_REDIS_ADDR"`
|
||||
Password string `envconfig:"DRONE_REDIS_PASSWORD"`
|
||||
DB int `envconfig:"DRONE_REDIS_DB"`
|
||||
}
|
||||
|
||||
// Repository provides the repository configuration.
|
||||
Repository struct {
|
||||
Filter []string `envconfig:"DRONE_REPOSITORY_FILTER"`
|
||||
Visibility string `envconfig:"DRONE_REPOSITORY_VISIBILITY"`
|
||||
Trusted bool `envconfig:"DRONE_REPOSITORY_TRUSTED"`
|
||||
|
||||
// THIS SETTING IS INTERNAL USE ONLY AND SHOULD
|
||||
// NOT BE USED OR RELIED UPON IN PRODUCTION.
|
||||
Ignore []string `envconfig:"DRONE_REPOSITORY_IGNORE"`
|
||||
}
|
||||
|
||||
// Registries provides the registry configuration.
|
||||
Registries struct {
|
||||
Endpoint string `envconfig:"DRONE_REGISTRY_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_REGISTRY_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_REGISTRY_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Secrets provides the secret configuration.
|
||||
Secrets struct {
|
||||
Endpoint string `envconfig:"DRONE_SECRET_ENDPOINT"`
|
||||
Password string `envconfig:"DRONE_SECRET_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_SECRET_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// RPC provides the rpc configuration.
|
||||
RPC struct {
|
||||
Server string `envconfig:"DRONE_RPC_SERVER"`
|
||||
Secret string `envconfig:"DRONE_RPC_SECRET"`
|
||||
Debug bool `envconfig:"DRONE_RPC_DEBUG"`
|
||||
Host string `envconfig:"DRONE_RPC_HOST"`
|
||||
Proto string `envconfig:"DRONE_RPC_PROTO"`
|
||||
// Hosts map[string]string `envconfig:"DRONE_RPC_EXTRA_HOSTS"`
|
||||
}
|
||||
|
||||
Agent struct {
|
||||
Disabled bool `envconfig:"DRONE_AGENTS_DISABLED"`
|
||||
}
|
||||
|
||||
// Runner provides the runner configuration.
|
||||
Runner struct {
|
||||
Local bool `envconfig:"DRONE_RUNNER_LOCAL"`
|
||||
Image string `envconfig:"DRONE_RUNNER_IMAGE" default:"drone/controller:1"`
|
||||
Platform string `envconfig:"DRONE_RUNNER_PLATFORM" default:"linux/amd64"`
|
||||
OS string `envconfig:"DRONE_RUNNER_OS"`
|
||||
Arch string `envconfig:"DRONE_RUNNER_ARCH"`
|
||||
Kernel string `envconfig:"DRONE_RUNNER_KERNEL"`
|
||||
Variant string `envconfig:"DRONE_RUNNER_VARIANT"`
|
||||
Machine string `envconfig:"DRONE_RUNNER_NAME"`
|
||||
Capacity int `envconfig:"DRONE_RUNNER_CAPACITY" default:"2"`
|
||||
Labels map[string]string `envconfig:"DRONE_RUNNER_LABELS"`
|
||||
Volumes []string `envconfig:"DRONE_RUNNER_VOLUMES"`
|
||||
Networks []string `envconfig:"DRONE_RUNNER_NETWORKS"`
|
||||
Devices []string `envconfig:"DRONE_RUNNER_DEVICES"`
|
||||
Privileged []string `envconfig:"DRONE_RUNNER_PRIVILEGED_IMAGES"`
|
||||
Environ map[string]string `envconfig:"DRONE_RUNNER_ENVIRON"`
|
||||
Limits struct {
|
||||
MemSwapLimit Bytes `envconfig:"DRONE_LIMIT_MEM_SWAP"`
|
||||
MemLimit Bytes `envconfig:"DRONE_LIMIT_MEM"`
|
||||
ShmSize Bytes `envconfig:"DRONE_LIMIT_SHM_SIZE"`
|
||||
CPUQuota int64 `envconfig:"DRONE_LIMIT_CPU_QUOTA"`
|
||||
CPUShares int64 `envconfig:"DRONE_LIMIT_CPU_SHARES"`
|
||||
CPUSet string `envconfig:"DRONE_LIMIT_CPU_SET"`
|
||||
}
|
||||
}
|
||||
|
||||
// Server provides the server configuration.
|
||||
Server struct {
|
||||
Addr string `envconfig:"-"`
|
||||
Host string `envconfig:"DRONE_SERVER_HOST" default:"localhost:8080"`
|
||||
Port string `envconfig:"DRONE_SERVER_PORT" default:":8080"`
|
||||
Proto string `envconfig:"DRONE_SERVER_PROTO" default:"http"`
|
||||
Pprof bool `envconfig:"DRONE_PPROF_ENABLED"`
|
||||
Acme bool `envconfig:"DRONE_TLS_AUTOCERT"`
|
||||
Email string `envconfig:"DRONE_TLS_EMAIL"`
|
||||
Cert string `envconfig:"DRONE_TLS_CERT"`
|
||||
Key string `envconfig:"DRONE_TLS_KEY"`
|
||||
}
|
||||
|
||||
// Proxy provides proxy server configuration.
|
||||
Proxy struct {
|
||||
Addr string `envconfig:"-"`
|
||||
Host string `envconfig:"DRONE_SERVER_PROXY_HOST"`
|
||||
Proto string `envconfig:"DRONE_SERVER_PROXY_PROTO"`
|
||||
}
|
||||
|
||||
// Registration configuration.
|
||||
Registration struct {
|
||||
Closed bool `envconfig:"DRONE_REGISTRATION_CLOSED"`
|
||||
}
|
||||
|
||||
// Authentication Controller configuration
|
||||
Authentication struct {
|
||||
Endpoint string `envconfig:"DRONE_ADMISSION_PLUGIN_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_ADMISSION_PLUGIN_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_ADMISSION_PLUGIN_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Session provides the session configuration.
|
||||
Session struct {
|
||||
Timeout time.Duration `envconfig:"DRONE_COOKIE_TIMEOUT" default:"720h"`
|
||||
Secret string `envconfig:"DRONE_COOKIE_SECRET"`
|
||||
Secure bool `envconfig:"DRONE_COOKIE_SECURE"`
|
||||
}
|
||||
|
||||
// Status provides status configurations.
|
||||
Status struct {
|
||||
Disabled bool `envconfig:"DRONE_STATUS_DISABLED"`
|
||||
Name string `envconfig:"DRONE_STATUS_NAME"`
|
||||
}
|
||||
|
||||
// Users provides the user configuration.
|
||||
Users struct {
|
||||
Create UserCreate `envconfig:"DRONE_USER_CREATE"`
|
||||
Filter []string `envconfig:"DRONE_USER_FILTER"`
|
||||
MinAge time.Duration `envconfig:"DRONE_MIN_AGE"`
|
||||
}
|
||||
|
||||
// Webhook provides the webhook configuration.
|
||||
Webhook struct {
|
||||
Events []string `envconfig:"DRONE_WEBHOOK_EVENTS"`
|
||||
Endpoint []string `envconfig:"DRONE_WEBHOOK_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_WEBHOOK_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_WEBHOOK_SKIP_VERIFY"`
|
||||
}
|
||||
|
||||
// Yaml provides the yaml webhook configuration.
|
||||
Yaml struct {
|
||||
Endpoint string `envconfig:"DRONE_YAML_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_YAML_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_YAML_SKIP_VERIFY"`
|
||||
Timeout time.Duration `envconfig:"DRONE_YAML_TIMEOUT" default:"1m"`
|
||||
}
|
||||
|
||||
// Convert provides the converter webhook configuration.
|
||||
Convert struct {
|
||||
Extension string `envconfig:"DRONE_CONVERT_PLUGIN_EXTENSION"`
|
||||
Endpoint string `envconfig:"DRONE_CONVERT_PLUGIN_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_CONVERT_PLUGIN_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_CONVERT_PLUGIN_SKIP_VERIFY"`
|
||||
CacheSize int `envconfig:"DRONE_CONVERT_PLUGIN_CACHE_SIZE" default:"10"`
|
||||
Timeout time.Duration `envconfig:"DRONE_CONVERT_TIMEOUT" default:"1m"`
|
||||
|
||||
// this flag can be removed once we solve for
|
||||
// https://github.com/harness/drone/pull/2994#issuecomment-795955312
|
||||
Multi bool `envconfig:"DRONE_CONVERT_MULTI"`
|
||||
}
|
||||
|
||||
// Validate provides the validation webhook configuration.
|
||||
Validate struct {
|
||||
Endpoint string `envconfig:"DRONE_VALIDATE_PLUGIN_ENDPOINT"`
|
||||
Secret string `envconfig:"DRONE_VALIDATE_PLUGIN_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_VALIDATE_PLUGIN_SKIP_VERIFY"`
|
||||
Timeout time.Duration `envconfig:"DRONE_VALIDATE_TIMEOUT" default:"1m"`
|
||||
}
|
||||
|
||||
//
|
||||
// Source code management.
|
||||
//
|
||||
|
||||
// Bitbucket provides the bitbucket client configuration.
|
||||
Bitbucket struct {
|
||||
ClientID string `envconfig:"DRONE_BITBUCKET_CLIENT_ID"`
|
||||
ClientSecret string `envconfig:"DRONE_BITBUCKET_CLIENT_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_BITBUCKET_SKIP_VERIFY"`
|
||||
Debug bool `envconfig:"DRONE_BITBUCKET_DEBUG"`
|
||||
}
|
||||
|
||||
// Gitea provides the gitea client configuration.
|
||||
Gitea struct {
|
||||
Server string `envconfig:"DRONE_GITEA_SERVER"`
|
||||
ClientID string `envconfig:"DRONE_GITEA_CLIENT_ID"`
|
||||
ClientSecret string `envconfig:"DRONE_GITEA_CLIENT_SECRET"`
|
||||
RedirectURL string `envconfig:"DRONE_GITEA_REDIRECT_URL"`
|
||||
SkipVerify bool `envconfig:"DRONE_GITEA_SKIP_VERIFY"`
|
||||
Scope []string `envconfig:"DRONE_GITEA_SCOPE" default:"repo,repo:status,user:email,read:org"`
|
||||
Debug bool `envconfig:"DRONE_GITEA_DEBUG"`
|
||||
}
|
||||
|
||||
// Github provides the github client configuration.
|
||||
Github struct {
|
||||
Server string `envconfig:"DRONE_GITHUB_SERVER" default:"https://github.com"`
|
||||
APIServer string `envconfig:"DRONE_GITHUB_API_SERVER"`
|
||||
ClientID string `envconfig:"DRONE_GITHUB_CLIENT_ID"`
|
||||
ClientSecret string `envconfig:"DRONE_GITHUB_CLIENT_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_GITHUB_SKIP_VERIFY"`
|
||||
Scope []string `envconfig:"DRONE_GITHUB_SCOPE" default:"repo,repo:status,user:email,read:org"`
|
||||
RateLimit int `envconfig:"DRONE_GITHUB_USER_RATELIMIT"`
|
||||
Debug bool `envconfig:"DRONE_GITHUB_DEBUG"`
|
||||
}
|
||||
|
||||
// Gitee providers the gitee client configuration.
|
||||
Gitee struct {
|
||||
Server string `envconfig:"DRONE_GITEE_SERVER" default:"https://gitee.com"`
|
||||
APIServer string `envconfig:"DRONE_GITEE_API_SERVER" default:"https://gitee.com/api/v5"`
|
||||
ClientID string `envconfig:"DRONE_GITEE_CLIENT_ID"`
|
||||
ClientSecret string `envconfig:"DRONE_GITEE_CLIENT_SECRET"`
|
||||
RedirectURL string `envconfig:"DRONE_GITEE_REDIRECT_URL"`
|
||||
SkipVerify bool `envconfig:"DRONE_GITEE_SKIP_VERIFY"`
|
||||
Scope []string `envconfig:"DRONE_GITEE_SCOPE" default:"user_info,projects,pull_requests,hook"`
|
||||
Debug bool `envconfig:"DRONE_GITEE_DEBUG"`
|
||||
}
|
||||
|
||||
// GitLab provides the gitlab client configuration.
|
||||
GitLab struct {
|
||||
Server string `envconfig:"DRONE_GITLAB_SERVER" default:"https://gitlab.com"`
|
||||
ClientID string `envconfig:"DRONE_GITLAB_CLIENT_ID"`
|
||||
ClientSecret string `envconfig:"DRONE_GITLAB_CLIENT_SECRET"`
|
||||
SkipVerify bool `envconfig:"DRONE_GITLAB_SKIP_VERIFY"`
|
||||
Debug bool `envconfig:"DRONE_GITLAB_DEBUG"`
|
||||
}
|
||||
|
||||
// Gogs provides the gogs client configuration.
|
||||
Gogs struct {
|
||||
Server string `envconfig:"DRONE_GOGS_SERVER"`
|
||||
SkipVerify bool `envconfig:"DRONE_GOGS_SKIP_VERIFY"`
|
||||
Debug bool `envconfig:"DRONE_GOGS_DEBUG"`
|
||||
}
|
||||
|
||||
// Stash provides the stash client configuration.
|
||||
Stash struct {
|
||||
Server string `envconfig:"DRONE_STASH_SERVER"`
|
||||
ConsumerKey string `envconfig:"DRONE_STASH_CONSUMER_KEY"`
|
||||
ConsumerSecret string `envconfig:"DRONE_STASH_CONSUMER_SECRET"`
|
||||
PrivateKey string `envconfig:"DRONE_STASH_PRIVATE_KEY"`
|
||||
SkipVerify bool `envconfig:"DRONE_STASH_SKIP_VERIFY"`
|
||||
Debug bool `envconfig:"DRONE_STASH_DEBUG"`
|
||||
}
|
||||
|
||||
// S3 provides the storage configuration.
|
||||
S3 struct {
|
||||
Bucket string `envconfig:"DRONE_S3_BUCKET"`
|
||||
Prefix string `envconfig:"DRONE_S3_PREFIX"`
|
||||
Endpoint string `envconfig:"DRONE_S3_ENDPOINT"`
|
||||
PathStyle bool `envconfig:"DRONE_S3_PATH_STYLE"`
|
||||
}
|
||||
|
||||
//AzureBlob providers the storage configuration.
|
||||
AzureBlob struct {
|
||||
ContainerName string `envconfig:"DRONE_AZURE_BLOB_CONTAINER_NAME"`
|
||||
StorageAccountName string `envconfig:"DRONE_AZURE_STORAGE_ACCOUNT_NAME"`
|
||||
StorageAccessKey string `envconfig:"DRONE_AZURE_STORAGE_ACCESS_KEY"`
|
||||
}
|
||||
|
||||
// HTTP provides http configuration.
|
||||
HTTP struct {
|
||||
AllowedHosts []string `envconfig:"DRONE_HTTP_ALLOWED_HOSTS"`
|
||||
HostsProxyHeaders []string `envconfig:"DRONE_HTTP_PROXY_HEADERS"`
|
||||
SSLRedirect bool `envconfig:"DRONE_HTTP_SSL_REDIRECT"`
|
||||
SSLTemporaryRedirect bool `envconfig:"DRONE_HTTP_SSL_TEMPORARY_REDIRECT"`
|
||||
SSLHost string `envconfig:"DRONE_HTTP_SSL_HOST"`
|
||||
SSLProxyHeaders map[string]string `envconfig:"DRONE_HTTP_SSL_PROXY_HEADERS"`
|
||||
STSSeconds int64 `envconfig:"DRONE_HTTP_STS_SECONDS"`
|
||||
STSIncludeSubdomains bool `envconfig:"DRONE_HTTP_STS_INCLUDE_SUBDOMAINS"`
|
||||
STSPreload bool `envconfig:"DRONE_HTTP_STS_PRELOAD"`
|
||||
ForceSTSHeader bool `envconfig:"DRONE_HTTP_STS_FORCE_HEADER"`
|
||||
BrowserXSSFilter bool `envconfig:"DRONE_HTTP_BROWSER_XSS_FILTER" default:"true"`
|
||||
FrameDeny bool `envconfig:"DRONE_HTTP_FRAME_DENY" default:"true"`
|
||||
ContentTypeNosniff bool `envconfig:"DRONE_HTTP_CONTENT_TYPE_NO_SNIFF"`
|
||||
ContentSecurityPolicy string `envconfig:"DRONE_HTTP_CONTENT_SECURITY_POLICY"`
|
||||
ReferrerPolicy string `envconfig:"DRONE_HTTP_REFERRER_POLICY"`
|
||||
}
|
||||
)
|
||||
|
||||
// Environ returns the settings from the environment.
|
||||
func Environ() (Config, error) {
|
||||
cfg := Config{}
|
||||
err := envconfig.Process("", &cfg)
|
||||
defaultAddress(&cfg)
|
||||
defaultProxy(&cfg)
|
||||
defaultRunner(&cfg)
|
||||
defaultSession(&cfg)
|
||||
defaultCallback(&cfg)
|
||||
configureGithub(&cfg)
|
||||
if err := kubernetesServiceConflict(&cfg); err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
// String returns the configuration in string format.
|
||||
func (c *Config) String() string {
|
||||
out, _ := yaml.Marshal(c)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// IsGitHub returns true if the GitHub integration
|
||||
// is activated.
|
||||
func (c *Config) IsGitHub() bool {
|
||||
return c.Github.ClientID != ""
|
||||
}
|
||||
|
||||
// IsGitHubEnterprise returns true if the GitHub
|
||||
// integration is activated.
|
||||
func (c *Config) IsGitHubEnterprise() bool {
|
||||
return c.IsGitHub() && !strings.HasPrefix(c.Github.Server, "https://github.com")
|
||||
}
|
||||
|
||||
// IsGitLab returns true if the GitLab integration
|
||||
// is activated.
|
||||
func (c *Config) IsGitLab() bool {
|
||||
return c.GitLab.ClientID != ""
|
||||
}
|
||||
|
||||
// IsGogs returns true if the Gogs integration
|
||||
// is activated.
|
||||
func (c *Config) IsGogs() bool {
|
||||
return c.Gogs.Server != ""
|
||||
}
|
||||
|
||||
// IsGitea returns true if the Gitea integration
|
||||
// is activated.
|
||||
func (c *Config) IsGitea() bool {
|
||||
return c.Gitea.Server != ""
|
||||
}
|
||||
|
||||
// IsGitee returns true if the Gitee integration
|
||||
// is activated.
|
||||
func (c *Config) IsGitee() bool {
|
||||
return c.Gitee.ClientID != ""
|
||||
}
|
||||
|
||||
// IsBitbucket returns true if the Bitbucket Cloud
|
||||
// integration is activated.
|
||||
func (c *Config) IsBitbucket() bool {
|
||||
return c.Bitbucket.ClientID != ""
|
||||
}
|
||||
|
||||
// IsStash returns true if the Atlassian Stash
|
||||
// integration is activated.
|
||||
func (c *Config) IsStash() bool {
|
||||
return c.Stash.Server != ""
|
||||
}
|
||||
|
||||
func cleanHostname(hostname string) string {
|
||||
hostname = strings.ToLower(hostname)
|
||||
hostname = strings.TrimPrefix(hostname, "http://")
|
||||
hostname = strings.TrimPrefix(hostname, "https://")
|
||||
|
||||
return hostname
|
||||
}
|
||||
|
||||
func defaultAddress(c *Config) {
|
||||
if c.Server.Key != "" || c.Server.Cert != "" || c.Server.Acme {
|
||||
c.Server.Port = ":443"
|
||||
c.Server.Proto = "https"
|
||||
}
|
||||
c.Server.Host = cleanHostname(c.Server.Host)
|
||||
c.Server.Addr = c.Server.Proto + "://" + c.Server.Host
|
||||
}
|
||||
|
||||
func defaultProxy(c *Config) {
|
||||
if c.Proxy.Host == "" {
|
||||
c.Proxy.Host = c.Server.Host
|
||||
} else {
|
||||
c.Proxy.Host = cleanHostname(c.Proxy.Host)
|
||||
}
|
||||
if c.Proxy.Proto == "" {
|
||||
c.Proxy.Proto = c.Server.Proto
|
||||
}
|
||||
c.Proxy.Addr = c.Proxy.Proto + "://" + c.Proxy.Host
|
||||
}
|
||||
|
||||
func defaultCallback(c *Config) {
|
||||
if c.RPC.Host == "" {
|
||||
c.RPC.Host = c.Server.Host
|
||||
}
|
||||
if c.RPC.Proto == "" {
|
||||
c.RPC.Proto = c.Server.Proto
|
||||
}
|
||||
}
|
||||
|
||||
func defaultRunner(c *Config) {
|
||||
if c.Runner.Machine == "" {
|
||||
c.Runner.Machine = hostname
|
||||
}
|
||||
parts := strings.Split(c.Runner.Platform, "/")
|
||||
if len(parts) == 2 && c.Runner.OS == "" {
|
||||
c.Runner.OS = parts[0]
|
||||
}
|
||||
if len(parts) == 2 && c.Runner.Arch == "" {
|
||||
c.Runner.Arch = parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
func defaultSession(c *Config) {
|
||||
if c.Session.Secret == "" {
|
||||
c.Session.Secret = uniuri.NewLen(32)
|
||||
}
|
||||
}
|
||||
|
||||
func configureGithub(c *Config) {
|
||||
if c.Github.APIServer != "" {
|
||||
return
|
||||
}
|
||||
if c.Github.Server == "https://github.com" {
|
||||
c.Github.APIServer = "https://api.github.com"
|
||||
} else {
|
||||
c.Github.APIServer = strings.TrimSuffix(c.Github.Server, "/") + "/api/v3"
|
||||
}
|
||||
}
|
||||
|
||||
func kubernetesServiceConflict(c *Config) error {
|
||||
if strings.HasPrefix(c.Server.Port, "tcp://") {
|
||||
return errors.New("Invalid port configuration. See https://community.harness.io/t/drone-server-changing-ports-protocol/11400")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bytes stores number bytes (e.g. megabytes)
|
||||
type Bytes int64
|
||||
|
||||
// Decode implements a decoder that parses a string representation
|
||||
// of bytes into the number of bytes it represents.
|
||||
func (b *Bytes) Decode(value string) error {
|
||||
v, err := humanize.ParseBytes(value)
|
||||
*b = Bytes(v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Int64 returns the int64 value of the Byte.
|
||||
func (b *Bytes) Int64() int64 {
|
||||
return int64(*b)
|
||||
}
|
||||
|
||||
// String returns the string value of the Byte.
|
||||
func (b *Bytes) String() string {
|
||||
return fmt.Sprint(*b)
|
||||
}
|
||||
|
||||
// UserCreate stores account information used to bootstrap
|
||||
// the admin user account when the system initializes.
|
||||
type UserCreate struct {
|
||||
Username string
|
||||
Machine bool
|
||||
Admin bool
|
||||
Token string
|
||||
}
|
||||
|
||||
// Decode implements a decoder that extracts user information
|
||||
// from the environment variable string.
|
||||
func (u *UserCreate) Decode(value string) error {
|
||||
for _, param := range strings.Split(value, ",") {
|
||||
parts := strings.Split(param, ":")
|
||||
if len(parts) != 2 {
|
||||
continue
|
||||
}
|
||||
key := parts[0]
|
||||
val := parts[1]
|
||||
switch key {
|
||||
case "username":
|
||||
u.Username = val
|
||||
case "token":
|
||||
u.Token = val
|
||||
case "machine":
|
||||
u.Machine = val == "true"
|
||||
case "admin":
|
||||
u.Admin = val == "true"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test_cleanHostname(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hostname string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "no prefix",
|
||||
hostname: "drone.io",
|
||||
want: "drone.io",
|
||||
},
|
||||
{
|
||||
name: "http prefix",
|
||||
hostname: "http://drone.io",
|
||||
want: "drone.io",
|
||||
},
|
||||
{
|
||||
name: "https prefix",
|
||||
hostname: "https://drone.io",
|
||||
want: "drone.io",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := cleanHostname(tt.hostname); got != tt.want {
|
||||
t.Errorf("cleanHostname() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,286 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/go-scm/scm"
|
||||
"github.com/drone/go-scm/scm/driver/bitbucket"
|
||||
"github.com/drone/go-scm/scm/driver/gitea"
|
||||
"github.com/drone/go-scm/scm/driver/gitee"
|
||||
"github.com/drone/go-scm/scm/driver/github"
|
||||
"github.com/drone/go-scm/scm/driver/gitlab"
|
||||
"github.com/drone/go-scm/scm/driver/gogs"
|
||||
"github.com/drone/go-scm/scm/driver/stash"
|
||||
"github.com/drone/go-scm/scm/transport/oauth1"
|
||||
"github.com/drone/go-scm/scm/transport/oauth2"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the scm client.
|
||||
var clientSet = wire.NewSet(
|
||||
provideClient,
|
||||
)
|
||||
|
||||
// provideBitbucketClient is a Wire provider function that
|
||||
// returns a Source Control Management client based on the
|
||||
// environment configuration.
|
||||
func provideClient(config config.Config) *scm.Client {
|
||||
switch {
|
||||
case config.Bitbucket.ClientID != "":
|
||||
return provideBitbucketClient(config)
|
||||
case config.Github.ClientID != "":
|
||||
return provideGithubClient(config)
|
||||
case config.Gitee.ClientID != "":
|
||||
return provideGiteeClient(config)
|
||||
case config.Gitea.Server != "":
|
||||
return provideGiteaClient(config)
|
||||
case config.GitLab.ClientID != "":
|
||||
return provideGitlabClient(config)
|
||||
case config.Gogs.Server != "":
|
||||
return provideGogsClient(config)
|
||||
case config.Stash.ConsumerKey != "":
|
||||
return provideStashClient(config)
|
||||
}
|
||||
logrus.Fatalln("main: source code management system not configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
// provideBitbucketClient is a Wire provider function that
|
||||
// returns a Bitbucket Cloud client based on the environment
|
||||
// configuration.
|
||||
func provideBitbucketClient(config config.Config) *scm.Client {
|
||||
client := bitbucket.NewDefault()
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Source: &oauth2.Refresher{
|
||||
ClientID: config.Bitbucket.ClientID,
|
||||
ClientSecret: config.Bitbucket.ClientSecret,
|
||||
Endpoint: "https://bitbucket.org/site/oauth2/access_token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
},
|
||||
},
|
||||
}
|
||||
if config.Bitbucket.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideGithubClient is a Wire provider function that returns
|
||||
// a GitHub client based on the environment configuration.
|
||||
func provideGithubClient(config config.Config) *scm.Client {
|
||||
client, err := github.New(config.Github.APIServer)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the GitHub client")
|
||||
}
|
||||
if config.Github.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Base: defaultTransport(config.Github.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideGiteeClient is a Wire provider function that returns
|
||||
// a Gitee client based on the environment configuration.
|
||||
func provideGiteeClient(config config.Config) *scm.Client {
|
||||
client, err := gitee.New(config.Gitee.APIServer)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the Gitee client")
|
||||
}
|
||||
if config.Gitee.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Scheme: oauth2.SchemeBearer,
|
||||
Source: &oauth2.Refresher{
|
||||
ClientID: config.Gitee.ClientID,
|
||||
ClientSecret: config.Gitee.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.Gitee.Server, "/") + "/oauth/token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
},
|
||||
Base: defaultTransport(config.Gitee.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideGiteaClient is a Wire provider function that returns
|
||||
// a Gitea client based on the environment configuration.
|
||||
func provideGiteaClient(config config.Config) *scm.Client {
|
||||
client, err := gitea.New(config.Gitea.Server)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the Gitea client")
|
||||
}
|
||||
if config.Gitea.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Scheme: oauth2.SchemeBearer,
|
||||
Source: &oauth2.Refresher{
|
||||
ClientID: config.Gitea.ClientID,
|
||||
ClientSecret: config.Gitea.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.Gitea.Server, "/") + "/login/oauth/access_token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
},
|
||||
Base: defaultTransport(config.Gitea.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideGitlabClient is a Wire provider function that returns
|
||||
// a GitLab client based on the environment configuration.
|
||||
func provideGitlabClient(config config.Config) *scm.Client {
|
||||
logrus.WithField("server", config.GitLab.Server).
|
||||
WithField("client", config.GitLab.ClientID).
|
||||
WithField("skip_verify", config.GitLab.SkipVerify).
|
||||
Debugln("main: creating the GitLab client")
|
||||
|
||||
client, err := gitlab.New(config.GitLab.Server)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the GitLab client")
|
||||
}
|
||||
if config.GitLab.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Scheme: oauth2.SchemeBearer,
|
||||
Source: &oauth2.Refresher{
|
||||
ClientID: config.GitLab.ClientID,
|
||||
ClientSecret: config.GitLab.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.GitLab.Server, "/") + "/oauth/token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
},
|
||||
Base: defaultTransport(config.GitLab.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideGogsClient is a Wire provider function that returns
|
||||
// a Gogs client based on the environment configuration.
|
||||
func provideGogsClient(config config.Config) *scm.Client {
|
||||
logrus.WithField("server", config.Gogs.Server).
|
||||
WithField("skip_verify", config.Gogs.SkipVerify).
|
||||
Debugln("main: creating the Gogs client")
|
||||
|
||||
client, err := gogs.New(config.Gogs.Server)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the Gogs client")
|
||||
}
|
||||
if config.Gogs.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Scheme: oauth2.SchemeToken,
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Base: defaultTransport(config.Gogs.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// provideStashClient is a Wire provider function that returns
|
||||
// a Stash client based on the environment configuration.
|
||||
func provideStashClient(config config.Config) *scm.Client {
|
||||
logrus.WithField("server", config.Stash.Server).
|
||||
WithField("skip_verify", config.Stash.SkipVerify).
|
||||
Debugln("main: creating the Stash client")
|
||||
|
||||
privateKey, err := parsePrivateKeyFile(config.Stash.PrivateKey)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot parse the Stash Private Key")
|
||||
}
|
||||
client, err := stash.New(config.Stash.Server)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot create the Stash client")
|
||||
}
|
||||
if config.Stash.Debug {
|
||||
client.DumpResponse = httputil.DumpResponse
|
||||
}
|
||||
client.Client = &http.Client{
|
||||
Transport: &oauth1.Transport{
|
||||
ConsumerKey: config.Stash.ConsumerKey,
|
||||
PrivateKey: privateKey,
|
||||
Source: oauth1.ContextTokenSource(),
|
||||
Base: defaultTransport(config.Stash.SkipVerify),
|
||||
},
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// defaultClient provides a default http.Client. If skipverify
|
||||
// is true, the default transport will skip ssl verification.
|
||||
func defaultClient(skipverify bool) *http.Client {
|
||||
client := &http.Client{}
|
||||
client.Transport = defaultTransport(skipverify)
|
||||
return client
|
||||
}
|
||||
|
||||
// defaultTransport provides a default http.Transport. If
|
||||
// skipverify is true, the transport will skip ssl verification.
|
||||
func defaultTransport(skipverify bool) http.RoundTripper {
|
||||
return &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: skipverify,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// parsePrivateKeyFile is a helper function that parses an
|
||||
// RSA Private Key file encoded in PEM format.
|
||||
func parsePrivateKeyFile(path string) (*rsa.PrivateKey, error) {
|
||||
d, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parsePrivateKey(d)
|
||||
}
|
||||
|
||||
// parsePrivateKey is a helper function that parses an RSA
|
||||
// Private Key encoded in PEM format.
|
||||
func parsePrivateKey(data []byte) (*rsa.PrivateKey, error) {
|
||||
p, _ := pem.Decode(data)
|
||||
return x509.ParsePKCS1PrivateKey(p.Bytes)
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// Copyright 2021 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/service/redisdb"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// wire set for loading the external services.
|
||||
var externalSet = wire.NewSet(
|
||||
provideRedisClient,
|
||||
)
|
||||
|
||||
func provideRedisClient(config config.Config) (rdb redisdb.RedisDB, err error) {
|
||||
return redisdb.New(config)
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/service/license"
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the license.
|
||||
var licenseSet = wire.NewSet(
|
||||
provideLicense,
|
||||
license.NewService,
|
||||
)
|
||||
|
||||
// provideLicense is a Wire provider function that returns a
|
||||
// license loaded from a license file.
|
||||
func provideLicense(client *scm.Client, config config.Config) *core.License {
|
||||
l, err := license.Load(config.License)
|
||||
if config.License == "" {
|
||||
l = license.Trial(client.Driver.String())
|
||||
} else if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: invalid or expired license")
|
||||
}
|
||||
logrus.WithFields(
|
||||
logrus.Fields{
|
||||
"kind": l.Kind,
|
||||
"expires": l.Expires,
|
||||
"repo.limit": l.Repos,
|
||||
"user.limit": l.Users,
|
||||
"build.limit": l.Builds,
|
||||
},
|
||||
).Debugln("main: license loaded")
|
||||
return l
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/go-login/login"
|
||||
"github.com/drone/go-login/login/bitbucket"
|
||||
"github.com/drone/go-login/login/gitea"
|
||||
"github.com/drone/go-login/login/gitee"
|
||||
"github.com/drone/go-login/login/github"
|
||||
"github.com/drone/go-login/login/gitlab"
|
||||
"github.com/drone/go-login/login/gogs"
|
||||
"github.com/drone/go-login/login/stash"
|
||||
"github.com/drone/go-scm/scm/transport/oauth2"
|
||||
"strings"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the authenticator.
|
||||
var loginSet = wire.NewSet(
|
||||
provideLogin,
|
||||
provideRefresher,
|
||||
)
|
||||
|
||||
// provideLogin is a Wire provider function that returns an
|
||||
// authenticator based on the environment configuration.
|
||||
func provideLogin(config config.Config) login.Middleware {
|
||||
switch {
|
||||
case config.Bitbucket.ClientID != "":
|
||||
return provideBitbucketLogin(config)
|
||||
case config.Github.ClientID != "":
|
||||
return provideGithubLogin(config)
|
||||
case config.Gitee.ClientID != "":
|
||||
return provideGiteeLogin(config)
|
||||
case config.Gitea.Server != "":
|
||||
return provideGiteaLogin(config)
|
||||
case config.GitLab.ClientID != "":
|
||||
return provideGitlabLogin(config)
|
||||
case config.Gogs.Server != "":
|
||||
return provideGogsLogin(config)
|
||||
case config.Stash.ConsumerKey != "":
|
||||
return provideStashLogin(config)
|
||||
}
|
||||
logrus.Fatalln("main: source code management system not configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
// provideBitbucketLogin is a Wire provider function that
|
||||
// returns a Bitbucket Cloud authenticator based on the
|
||||
// environment configuration.
|
||||
func provideBitbucketLogin(config config.Config) login.Middleware {
|
||||
if config.Bitbucket.ClientID == "" {
|
||||
return nil
|
||||
}
|
||||
return &bitbucket.Config{
|
||||
ClientID: config.Bitbucket.ClientID,
|
||||
ClientSecret: config.Bitbucket.ClientSecret,
|
||||
RedirectURL: config.Server.Addr + "/login",
|
||||
}
|
||||
}
|
||||
|
||||
// provideGithubLogin is a Wire provider function that returns
|
||||
// a GitHub authenticator based on the environment configuration.
|
||||
func provideGithubLogin(config config.Config) login.Middleware {
|
||||
if config.Github.ClientID == "" {
|
||||
return nil
|
||||
}
|
||||
return &github.Config{
|
||||
ClientID: config.Github.ClientID,
|
||||
ClientSecret: config.Github.ClientSecret,
|
||||
Scope: config.Github.Scope,
|
||||
Server: config.Github.Server,
|
||||
Client: defaultClient(config.Github.SkipVerify),
|
||||
Logger: logrus.StandardLogger(),
|
||||
}
|
||||
}
|
||||
|
||||
// provideGiteeLogin is a Wire provider function that returns
|
||||
// a Gitee authenticator based on the environment configuration.
|
||||
func provideGiteeLogin(config config.Config) login.Middleware {
|
||||
if config.Gitee.ClientID == "" {
|
||||
return nil
|
||||
}
|
||||
redirectURL := config.Gitee.RedirectURL
|
||||
if redirectURL == "" {
|
||||
redirectURL = config.Server.Addr + "/login"
|
||||
}
|
||||
return &gitee.Config{
|
||||
ClientID: config.Gitee.ClientID,
|
||||
ClientSecret: config.Gitee.ClientSecret,
|
||||
RedirectURL: redirectURL,
|
||||
Server: config.Gitee.Server,
|
||||
Scope: config.Gitee.Scope,
|
||||
Client: defaultClient(config.Gitee.SkipVerify),
|
||||
}
|
||||
}
|
||||
|
||||
// provideGiteaLogin is a Wire provider function that returns
|
||||
// a Gitea authenticator based on the environment configuration.
|
||||
func provideGiteaLogin(config config.Config) login.Middleware {
|
||||
if config.Gitea.Server == "" {
|
||||
return nil
|
||||
}
|
||||
redirectURL := config.Gitea.RedirectURL
|
||||
if redirectURL == "" {
|
||||
redirectURL = config.Server.Addr + "/login"
|
||||
}
|
||||
return &gitea.Config{
|
||||
ClientID: config.Gitea.ClientID,
|
||||
ClientSecret: config.Gitea.ClientSecret,
|
||||
Server: config.Gitea.Server,
|
||||
Client: defaultClient(config.Gitea.SkipVerify),
|
||||
Logger: logrus.StandardLogger(),
|
||||
RedirectURL: redirectURL,
|
||||
Scope: config.Gitea.Scope,
|
||||
}
|
||||
}
|
||||
|
||||
// provideGitlabLogin is a Wire provider function that returns
|
||||
// a GitLab authenticator based on the environment configuration.
|
||||
func provideGitlabLogin(config config.Config) login.Middleware {
|
||||
if config.GitLab.ClientID == "" {
|
||||
return nil
|
||||
}
|
||||
return &gitlab.Config{
|
||||
ClientID: config.GitLab.ClientID,
|
||||
ClientSecret: config.GitLab.ClientSecret,
|
||||
RedirectURL: config.Server.Addr + "/login",
|
||||
Server: config.GitLab.Server,
|
||||
Client: defaultClient(config.GitLab.SkipVerify),
|
||||
}
|
||||
}
|
||||
|
||||
// provideGogsLogin is a Wire provider function that returns
|
||||
// a Gogs authenticator based on the environment configuration.
|
||||
func provideGogsLogin(config config.Config) login.Middleware {
|
||||
if config.Gogs.Server == "" {
|
||||
return nil
|
||||
}
|
||||
return &gogs.Config{
|
||||
Label: "drone",
|
||||
Login: "/login/form",
|
||||
Server: config.Gogs.Server,
|
||||
Client: defaultClient(config.Gogs.SkipVerify),
|
||||
}
|
||||
}
|
||||
|
||||
// provideStashLogin is a Wire provider function that returns
|
||||
// a Stash authenticator based on the environment configuration.
|
||||
func provideStashLogin(config config.Config) login.Middleware {
|
||||
if config.Stash.ConsumerKey == "" {
|
||||
return nil
|
||||
}
|
||||
privateKey, err := stash.ParsePrivateKeyFile(config.Stash.PrivateKey)
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("main: cannot parse Private Key file")
|
||||
}
|
||||
return &stash.Config{
|
||||
Address: config.Stash.Server,
|
||||
ConsumerKey: config.Stash.ConsumerKey,
|
||||
ConsumerSecret: config.Stash.ConsumerSecret,
|
||||
PrivateKey: privateKey,
|
||||
CallbackURL: config.Server.Addr + "/login",
|
||||
Client: defaultClient(config.Stash.SkipVerify),
|
||||
}
|
||||
}
|
||||
|
||||
// provideRefresher is a Wire provider function that returns
|
||||
// an oauth token refresher for Bitbucket and Gitea
|
||||
func provideRefresher(config config.Config) *oauth2.Refresher {
|
||||
switch {
|
||||
case config.Bitbucket.ClientID != "":
|
||||
return &oauth2.Refresher{
|
||||
ClientID: config.Bitbucket.ClientID,
|
||||
ClientSecret: config.Bitbucket.ClientSecret,
|
||||
Endpoint: "https://bitbucket.org/site/oauth2/access_token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Client: defaultClient(config.Bitbucket.SkipVerify),
|
||||
}
|
||||
case config.Gitea.ClientID != "":
|
||||
return &oauth2.Refresher{
|
||||
ClientID: config.Gitea.ClientID,
|
||||
ClientSecret: config.Gitea.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.Gitea.Server, "/") + "/login/oauth/access_token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Client: defaultClient(config.Gitea.SkipVerify),
|
||||
}
|
||||
case config.GitLab.ClientID != "":
|
||||
return &oauth2.Refresher{
|
||||
ClientID: config.GitLab.ClientID,
|
||||
ClientSecret: config.GitLab.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.GitLab.Server, "/") + "/oauth/token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Client: defaultClient(config.GitLab.SkipVerify),
|
||||
}
|
||||
case config.Gitee.ClientID != "":
|
||||
return &oauth2.Refresher{
|
||||
ClientID: config.Gitee.ClientID,
|
||||
ClientSecret: config.Gitee.ClientSecret,
|
||||
Endpoint: strings.TrimSuffix(config.Gitee.Server, "/") + "/oauth/token",
|
||||
Source: oauth2.ContextTokenSource(),
|
||||
Client: defaultClient(config.Gitee.SkipVerify),
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
spec "github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/plugin/admission"
|
||||
"github.com/drone/drone/plugin/config"
|
||||
"github.com/drone/drone/plugin/converter"
|
||||
"github.com/drone/drone/plugin/registry"
|
||||
"github.com/drone/drone/plugin/secret"
|
||||
"github.com/drone/drone/plugin/validator"
|
||||
"github.com/drone/drone/plugin/webhook"
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// wire set for loading plugins.
|
||||
var pluginSet = wire.NewSet(
|
||||
provideAdmissionPlugin,
|
||||
provideConfigPlugin,
|
||||
provideConvertPlugin,
|
||||
provideRegistryPlugin,
|
||||
provideSecretPlugin,
|
||||
provideValidatePlugin,
|
||||
provideWebhookPlugin,
|
||||
)
|
||||
|
||||
// provideAdmissionPlugin is a Wire provider function that
|
||||
// returns an admission plugin based on the environment
|
||||
// configuration.
|
||||
func provideAdmissionPlugin(client *scm.Client, orgs core.OrganizationService, users core.UserService, config spec.Config) core.AdmissionService {
|
||||
return admission.Combine(
|
||||
admission.Membership(orgs, config.Users.Filter),
|
||||
admission.Open(config.Registration.Closed),
|
||||
admission.Nobot(users, config.Users.MinAge),
|
||||
admission.External(
|
||||
config.Authn.Endpoint,
|
||||
config.Authn.Secret,
|
||||
config.Authn.SkipVerify,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// provideConfigPlugin is a Wire provider function that returns
|
||||
// a yaml configuration plugin based on the environment
|
||||
// configuration.
|
||||
func provideConfigPlugin(client *scm.Client, contents core.FileService, conf spec.Config) core.ConfigService {
|
||||
return config.Combine(
|
||||
config.Memoize(
|
||||
config.Global(
|
||||
conf.Yaml.Endpoint,
|
||||
conf.Yaml.Secret,
|
||||
conf.Yaml.SkipVerify,
|
||||
conf.Yaml.Timeout,
|
||||
),
|
||||
),
|
||||
config.Repository(contents),
|
||||
)
|
||||
}
|
||||
|
||||
// provideConvertPlugin is a Wire provider function that returns
|
||||
// a yaml conversion plugin based on the environment
|
||||
// configuration.
|
||||
func provideConvertPlugin(client *scm.Client, fileService core.FileService, conf spec.Config, templateStore core.TemplateStore) core.ConvertService {
|
||||
return converter.Combine(
|
||||
conf.Convert.Multi,
|
||||
converter.Legacy(false),
|
||||
converter.Starlark(
|
||||
conf.Starlark.Enabled,
|
||||
conf.Starlark.StepLimit,
|
||||
conf.Starlark.SizeLimit,
|
||||
),
|
||||
converter.Jsonnet(
|
||||
conf.Jsonnet.Enabled,
|
||||
conf.Jsonnet.ImportLimit,
|
||||
fileService,
|
||||
),
|
||||
converter.Template(
|
||||
templateStore,
|
||||
conf.Starlark.StepLimit,
|
||||
conf.Starlark.SizeLimit,
|
||||
),
|
||||
converter.Memoize(
|
||||
converter.Remote(
|
||||
conf.Convert.Endpoint,
|
||||
conf.Convert.Secret,
|
||||
conf.Convert.Extension,
|
||||
conf.Convert.SkipVerify,
|
||||
conf.Convert.Timeout,
|
||||
),
|
||||
conf.Convert.CacheSize,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// provideRegistryPlugin is a Wire provider function that
|
||||
// returns a registry plugin based on the environment
|
||||
// configuration.
|
||||
func provideRegistryPlugin(config spec.Config) core.RegistryService {
|
||||
return registry.Combine(
|
||||
registry.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
),
|
||||
registry.FileSource(
|
||||
config.Docker.Config,
|
||||
),
|
||||
registry.EndpointSource(
|
||||
config.Registries.Endpoint,
|
||||
config.Registries.Password,
|
||||
config.Registries.SkipVerify,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// provideSecretPlugin is a Wire provider function that returns
|
||||
// a secret plugin based on the environment configuration.
|
||||
func provideSecretPlugin(config spec.Config) core.SecretService {
|
||||
return secret.External(
|
||||
config.Secrets.Endpoint,
|
||||
config.Secrets.Password,
|
||||
config.Secrets.SkipVerify,
|
||||
)
|
||||
}
|
||||
|
||||
// provideValidatePlugin is a Wire provider function that
|
||||
// returns a yaml validation plugin based on the environment
|
||||
// configuration.
|
||||
func provideValidatePlugin(conf spec.Config) core.ValidateService {
|
||||
return validator.Combine(
|
||||
validator.Remote(
|
||||
conf.Validate.Endpoint,
|
||||
conf.Validate.Secret,
|
||||
conf.Validate.SkipVerify,
|
||||
conf.Validate.Timeout,
|
||||
),
|
||||
// THIS FEATURE IS INTERNAL USE ONLY AND SHOULD
|
||||
// NOT BE USED OR RELIED UPON IN PRODUCTION.
|
||||
validator.Filter(
|
||||
nil,
|
||||
conf.Repository.Ignore,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// provideWebhookPlugin is a Wire provider function that returns
|
||||
// a webhook plugin based on the environment configuration.
|
||||
func provideWebhookPlugin(config spec.Config, system *core.System) core.WebhookSender {
|
||||
return webhook.New(webhook.Config{
|
||||
Events: config.Webhook.Events,
|
||||
Endpoint: config.Webhook.Endpoint,
|
||||
Secret: config.Webhook.Secret,
|
||||
System: system,
|
||||
})
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone-runtime/engine/docker"
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/operator/manager"
|
||||
"github.com/drone/drone/operator/runner"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the server.
|
||||
var runnerSet = wire.NewSet(
|
||||
provideRunner,
|
||||
)
|
||||
|
||||
// provideRunner is a Wire provider function that returns a
|
||||
// local build runner configured from the environment.
|
||||
func provideRunner(
|
||||
manager manager.BuildManager,
|
||||
secrets core.SecretService,
|
||||
registry core.RegistryService,
|
||||
config config.Config,
|
||||
) *runner.Runner {
|
||||
// the local runner is only created when remote agents
|
||||
// are disabled
|
||||
if config.Agent.Disabled == false {
|
||||
return nil
|
||||
}
|
||||
engine, err := docker.NewEnv()
|
||||
if err != nil {
|
||||
logrus.WithError(err).
|
||||
Fatalln("cannot load the docker engine")
|
||||
return nil
|
||||
}
|
||||
return &runner.Runner{
|
||||
Platform: config.Runner.Platform,
|
||||
OS: config.Runner.OS,
|
||||
Arch: config.Runner.Arch,
|
||||
Kernel: config.Runner.Kernel,
|
||||
Variant: config.Runner.Variant,
|
||||
Engine: engine,
|
||||
Manager: manager,
|
||||
Secrets: secrets,
|
||||
Registry: registry,
|
||||
Volumes: config.Runner.Volumes,
|
||||
Networks: config.Runner.Networks,
|
||||
Devices: config.Runner.Devices,
|
||||
Privileged: config.Runner.Privileged,
|
||||
Machine: config.Runner.Machine,
|
||||
Labels: config.Runner.Labels,
|
||||
Environ: config.Runner.Environ,
|
||||
Limits: runner.Limits{
|
||||
MemSwapLimit: int64(config.Runner.Limits.MemSwapLimit),
|
||||
MemLimit: int64(config.Runner.Limits.MemLimit),
|
||||
ShmSize: int64(config.Runner.Limits.ShmSize),
|
||||
CPUQuota: config.Runner.Limits.CPUQuota,
|
||||
CPUShares: config.Runner.Limits.CPUShares,
|
||||
CPUSet: config.Runner.Limits.CPUSet,
|
||||
},
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/scheduler/queue"
|
||||
"github.com/drone/drone/service/redisdb"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// wire set for loading the scheduler.
|
||||
var schedulerSet = wire.NewSet(
|
||||
provideScheduler,
|
||||
)
|
||||
|
||||
// provideScheduler is a Wire provider function that returns a
|
||||
// scheduler based on the environment configuration.
|
||||
func provideScheduler(store core.StageStore, r redisdb.RedisDB) core.Scheduler {
|
||||
return queue.New(store, r)
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api"
|
||||
"github.com/drone/drone/handler/health"
|
||||
"github.com/drone/drone/handler/web"
|
||||
"github.com/drone/drone/metric"
|
||||
"github.com/drone/drone/operator/manager"
|
||||
"github.com/drone/drone/operator/manager/rpc"
|
||||
"github.com/drone/drone/operator/manager/rpc2"
|
||||
"github.com/drone/drone/server"
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/go-chi/chi/middleware"
|
||||
"github.com/unrolled/secure"
|
||||
)
|
||||
|
||||
type (
|
||||
healthzHandler http.Handler
|
||||
metricsHandler http.Handler
|
||||
pprofHandler http.Handler
|
||||
rpcHandlerV1 http.Handler
|
||||
rpcHandlerV2 http.Handler
|
||||
)
|
||||
|
||||
// wire set for loading the server.
|
||||
var serverSet = wire.NewSet(
|
||||
manager.New,
|
||||
api.New,
|
||||
web.New,
|
||||
provideHealthz,
|
||||
provideMetric,
|
||||
providePprof,
|
||||
provideRouter,
|
||||
provideRPC,
|
||||
provideRPC2,
|
||||
provideServer,
|
||||
provideServerOptions,
|
||||
)
|
||||
|
||||
// provideRouter is a Wire provider function that returns a
|
||||
// router that is serves the provided handlers.
|
||||
func provideRouter(api api.Server, web web.Server, rpcv1 rpcHandlerV1, rpcv2 rpcHandlerV2, healthz healthzHandler, metrics *metric.Server, pprof pprofHandler) *chi.Mux {
|
||||
r := chi.NewRouter()
|
||||
r.Mount("/healthz", healthz)
|
||||
r.Mount("/metrics", metrics)
|
||||
r.Mount("/api", api.Handler())
|
||||
r.Mount("/rpc/v2", rpcv2)
|
||||
r.Mount("/rpc", rpcv1)
|
||||
r.Mount("/", web.Handler())
|
||||
r.Mount("/debug", pprof)
|
||||
return r
|
||||
}
|
||||
|
||||
// provideMetric is a Wire provider function that returns the
|
||||
// healthcheck server.
|
||||
func provideHealthz() healthzHandler {
|
||||
v := health.New()
|
||||
return healthzHandler(v)
|
||||
}
|
||||
|
||||
// provideMetric is a Wire provider function that returns the
|
||||
// metrics server exposing metrics in prometheus format.
|
||||
func provideMetric(session core.Session, config config.Config) *metric.Server {
|
||||
return metric.NewServer(session, config.Prometheus.EnableAnonymousAccess)
|
||||
}
|
||||
|
||||
// providePprof is a Wire provider function that returns the
|
||||
// pprof server endpoints.
|
||||
func providePprof(config config.Config) pprofHandler {
|
||||
if config.Server.Pprof == false {
|
||||
return pprofHandler(
|
||||
http.NotFoundHandler(),
|
||||
)
|
||||
}
|
||||
return pprofHandler(
|
||||
middleware.Profiler(),
|
||||
)
|
||||
}
|
||||
|
||||
// provideRPC is a Wire provider function that returns an rpc
|
||||
// handler that exposes the build manager to a remote agent.
|
||||
func provideRPC(m manager.BuildManager, config config.Config) rpcHandlerV1 {
|
||||
v := rpc.NewServer(m, config.RPC.Secret)
|
||||
return rpcHandlerV1(v)
|
||||
}
|
||||
|
||||
// provideRPC2 is a Wire provider function that returns an rpc
|
||||
// handler that exposes the build manager to a remote agent.
|
||||
func provideRPC2(m manager.BuildManager, config config.Config) rpcHandlerV2 {
|
||||
v := rpc2.NewServer(m, config.RPC.Secret)
|
||||
return rpcHandlerV2(v)
|
||||
}
|
||||
|
||||
// provideServer is a Wire provider function that returns an
|
||||
// http server that is configured from the environment.
|
||||
func provideServer(handler *chi.Mux, config config.Config) *server.Server {
|
||||
return &server.Server{
|
||||
Acme: config.Server.Acme,
|
||||
Addr: config.Server.Port,
|
||||
Cert: config.Server.Cert,
|
||||
Key: config.Server.Key,
|
||||
Host: config.Server.Host,
|
||||
Handler: handler,
|
||||
}
|
||||
}
|
||||
|
||||
// provideServerOptions is a Wire provider function that returns
|
||||
// the http web server security option from the environment.
|
||||
func provideServerOptions(config config.Config) secure.Options {
|
||||
return secure.Options{
|
||||
AllowedHosts: config.HTTP.AllowedHosts,
|
||||
HostsProxyHeaders: config.HTTP.HostsProxyHeaders,
|
||||
SSLRedirect: config.HTTP.SSLRedirect,
|
||||
SSLTemporaryRedirect: config.HTTP.SSLTemporaryRedirect,
|
||||
SSLHost: config.HTTP.SSLHost,
|
||||
SSLProxyHeaders: config.HTTP.SSLProxyHeaders,
|
||||
STSSeconds: config.HTTP.STSSeconds,
|
||||
STSIncludeSubdomains: config.HTTP.STSIncludeSubdomains,
|
||||
STSPreload: config.HTTP.STSPreload,
|
||||
ForceSTSHeader: config.HTTP.ForceSTSHeader,
|
||||
FrameDeny: config.HTTP.FrameDeny,
|
||||
ContentTypeNosniff: config.HTTP.ContentTypeNosniff,
|
||||
BrowserXssFilter: config.HTTP.BrowserXSSFilter,
|
||||
ContentSecurityPolicy: config.HTTP.ContentSecurityPolicy,
|
||||
ReferrerPolicy: config.HTTP.ReferrerPolicy,
|
||||
}
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/livelog"
|
||||
"github.com/drone/drone/metric/sink"
|
||||
"github.com/drone/drone/pubsub"
|
||||
"github.com/drone/drone/service/canceler"
|
||||
"github.com/drone/drone/service/canceler/reaper"
|
||||
"github.com/drone/drone/service/commit"
|
||||
contents "github.com/drone/drone/service/content"
|
||||
"github.com/drone/drone/service/content/cache"
|
||||
"github.com/drone/drone/service/hook"
|
||||
"github.com/drone/drone/service/hook/parser"
|
||||
"github.com/drone/drone/service/linker"
|
||||
"github.com/drone/drone/service/netrc"
|
||||
orgs "github.com/drone/drone/service/org"
|
||||
"github.com/drone/drone/service/repo"
|
||||
"github.com/drone/drone/service/status"
|
||||
"github.com/drone/drone/service/syncer"
|
||||
"github.com/drone/drone/service/token"
|
||||
"github.com/drone/drone/service/transfer"
|
||||
"github.com/drone/drone/service/user"
|
||||
"github.com/drone/drone/session"
|
||||
"github.com/drone/drone/trigger"
|
||||
"github.com/drone/drone/trigger/cron"
|
||||
"github.com/drone/drone/version"
|
||||
"github.com/drone/go-scm/scm"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// wire set for loading the services.
|
||||
var serviceSet = wire.NewSet(
|
||||
canceler.New,
|
||||
commit.New,
|
||||
cron.New,
|
||||
livelog.New,
|
||||
linker.New,
|
||||
parser.New,
|
||||
pubsub.New,
|
||||
token.Renewer,
|
||||
transfer.New,
|
||||
trigger.New,
|
||||
user.New,
|
||||
|
||||
provideRepositoryService,
|
||||
provideContentService,
|
||||
provideDatadog,
|
||||
provideHookService,
|
||||
provideNetrcService,
|
||||
provideOrgService,
|
||||
provideReaper,
|
||||
provideSession,
|
||||
provideStatusService,
|
||||
provideSyncer,
|
||||
provideSystem,
|
||||
)
|
||||
|
||||
// provideContentService is a Wire provider function that
|
||||
// returns a contents service wrapped with a simple LRU cache.
|
||||
func provideContentService(client *scm.Client, renewer core.Renewer) core.FileService {
|
||||
return cache.Contents(
|
||||
contents.New(client, renewer),
|
||||
)
|
||||
}
|
||||
|
||||
// provideHookService is a Wire provider function that returns a
|
||||
// hook service based on the environment configuration.
|
||||
func provideHookService(client *scm.Client, renewer core.Renewer, config config.Config) core.HookService {
|
||||
return hook.New(client, config.Proxy.Addr, renewer)
|
||||
}
|
||||
|
||||
// provideNetrcService is a Wire provider function that returns
|
||||
// a netrc service based on the environment configuration.
|
||||
func provideNetrcService(client *scm.Client, renewer core.Renewer, config config.Config) core.NetrcService {
|
||||
return netrc.New(
|
||||
client,
|
||||
renewer,
|
||||
config.Cloning.AlwaysAuth,
|
||||
config.Cloning.Username,
|
||||
config.Cloning.Password,
|
||||
)
|
||||
}
|
||||
|
||||
// provideOrgService is a Wire provider function that
|
||||
// returns an organization service wrapped with a simple cache.
|
||||
func provideOrgService(client *scm.Client, renewer core.Renewer) core.OrganizationService {
|
||||
return orgs.NewCache(orgs.New(client, renewer), 10, time.Minute*5)
|
||||
}
|
||||
|
||||
// provideRepo is a Wire provider function that returns
|
||||
// a repo based on the environment configuration
|
||||
func provideRepositoryService(client *scm.Client, renewer core.Renewer, config config.Config) core.RepositoryService {
|
||||
return repo.New(
|
||||
client,
|
||||
renewer,
|
||||
config.Repository.Visibility,
|
||||
config.Repository.Trusted,
|
||||
)
|
||||
}
|
||||
|
||||
// provideSession is a Wire provider function that returns a
|
||||
// user session based on the environment configuration.
|
||||
func provideSession(store core.UserStore, config config.Config) (core.Session, error) {
|
||||
return session.New(store, session.NewConfig(
|
||||
config.Session.Secret,
|
||||
config.Session.Timeout,
|
||||
config.Session.Secure),
|
||||
), nil
|
||||
}
|
||||
|
||||
// provideUserService is a Wire provider function that returns a
|
||||
// user service based on the environment configuration.
|
||||
func provideStatusService(client *scm.Client, renewer core.Renewer, config config.Config) core.StatusService {
|
||||
return status.New(client, renewer, status.Config{
|
||||
Base: config.Server.Addr,
|
||||
Name: config.Status.Name,
|
||||
Disabled: config.Status.Disabled,
|
||||
})
|
||||
}
|
||||
|
||||
// provideSyncer is a Wire provider function that returns a
|
||||
// repository synchronizer.
|
||||
func provideSyncer(repoz core.RepositoryService,
|
||||
repos core.RepositoryStore,
|
||||
users core.UserStore,
|
||||
batch core.Batcher,
|
||||
config config.Config) core.Syncer {
|
||||
sync := syncer.New(repoz, repos, users, batch)
|
||||
// the user can define a filter that limits which
|
||||
// repositories can be synchronized and stored in the
|
||||
// database.
|
||||
if filter := config.Repository.Filter; len(filter) > 0 {
|
||||
sync.SetFilter(syncer.NamespaceFilter(filter))
|
||||
}
|
||||
return sync
|
||||
}
|
||||
|
||||
// provideSyncer is a Wire provider function that returns the
|
||||
// system details structure.
|
||||
func provideSystem(config config.Config) *core.System {
|
||||
return &core.System{
|
||||
Proto: config.Server.Proto,
|
||||
Host: config.Server.Host,
|
||||
Link: config.Server.Addr,
|
||||
Version: version.Version.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// provideReaper is a Wire provider function that returns the
|
||||
// zombie build reaper.
|
||||
func provideReaper(
|
||||
repos core.RepositoryStore,
|
||||
builds core.BuildStore,
|
||||
stages core.StageStore,
|
||||
canceler core.Canceler,
|
||||
config config.Config,
|
||||
) *reaper.Reaper {
|
||||
return reaper.New(
|
||||
repos,
|
||||
builds,
|
||||
stages,
|
||||
canceler,
|
||||
config.Cleanup.Running,
|
||||
config.Cleanup.Pending,
|
||||
config.Cleanup.Buffer,
|
||||
)
|
||||
}
|
||||
|
||||
// provideDatadog is a Wire provider function that returns the
|
||||
// datadog sink.
|
||||
func provideDatadog(
|
||||
users core.UserStore,
|
||||
repos core.RepositoryStore,
|
||||
builds core.BuildStore,
|
||||
system *core.System,
|
||||
license *core.License,
|
||||
config config.Config,
|
||||
) *sink.Datadog {
|
||||
return sink.New(
|
||||
users,
|
||||
repos,
|
||||
builds,
|
||||
*system,
|
||||
sink.Config{
|
||||
Endpoint: config.Datadog.Endpoint,
|
||||
Token: config.Datadog.Token,
|
||||
License: license.Kind,
|
||||
Licensor: license.Licensor,
|
||||
Subscription: license.Subscription,
|
||||
EnableGithub: config.IsGitHub(),
|
||||
EnableGithubEnt: config.IsGitHubEnterprise(),
|
||||
EnableGitlab: config.IsGitLab(),
|
||||
EnableBitbucket: config.IsBitbucket(),
|
||||
EnableStash: config.IsStash(),
|
||||
EnableGogs: config.IsGogs(),
|
||||
EnableGitea: config.IsGitea(),
|
||||
EnableGitee: config.IsGitee(),
|
||||
EnableAgents: !config.Agent.Disabled,
|
||||
},
|
||||
)
|
||||
}
|
@ -0,0 +1,181 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/metric"
|
||||
"github.com/drone/drone/store/batch"
|
||||
"github.com/drone/drone/store/batch2"
|
||||
"github.com/drone/drone/store/build"
|
||||
"github.com/drone/drone/store/card"
|
||||
"github.com/drone/drone/store/cron"
|
||||
"github.com/drone/drone/store/logs"
|
||||
"github.com/drone/drone/store/perm"
|
||||
"github.com/drone/drone/store/repos"
|
||||
"github.com/drone/drone/store/secret"
|
||||
"github.com/drone/drone/store/secret/global"
|
||||
"github.com/drone/drone/store/shared/db"
|
||||
"github.com/drone/drone/store/shared/encrypt"
|
||||
"github.com/drone/drone/store/stage"
|
||||
"github.com/drone/drone/store/step"
|
||||
"github.com/drone/drone/store/template"
|
||||
"github.com/drone/drone/store/user"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// wire set for loading the stores.
|
||||
var storeSet = wire.NewSet(
|
||||
provideDatabase,
|
||||
provideEncrypter,
|
||||
provideBuildStore,
|
||||
provideLogStore,
|
||||
provideRepoStore,
|
||||
provideStageStore,
|
||||
provideUserStore,
|
||||
provideBatchStore,
|
||||
// batch.New,
|
||||
cron.New,
|
||||
card.New,
|
||||
perm.New,
|
||||
secret.New,
|
||||
global.New,
|
||||
step.New,
|
||||
template.New,
|
||||
)
|
||||
|
||||
// provideDatabase is a Wire provider function that provides a
|
||||
// database connection, configured from the environment.
|
||||
func provideDatabase(config config.Config) (*db.DB, error) {
|
||||
return db.Connect(
|
||||
config.Database.Driver,
|
||||
config.Database.Datasource,
|
||||
config.Database.MaxConnections,
|
||||
)
|
||||
}
|
||||
|
||||
// provideEncrypter is a Wire provider function that provides a
|
||||
// database encrypter, configured from the environment.
|
||||
func provideEncrypter(config config.Config) (encrypt.Encrypter, error) {
|
||||
enc, err := encrypt.New(config.Database.Secret)
|
||||
// mixed-content mode should be set to true if the database
|
||||
// originally had encryption disabled and therefore has
|
||||
// plaintext entries. This prevents Drone from returning an
|
||||
// error if decryption fails; on failure, the ciphertext is
|
||||
// returned as-is and the error is ignored.
|
||||
if aesgcm, ok := enc.(*encrypt.Aesgcm); ok {
|
||||
logrus.Debugln("main: database encryption enabled")
|
||||
if config.Database.EncryptMixedContent {
|
||||
logrus.Debugln("main: database encryption mixed-mode enabled")
|
||||
aesgcm.Compat = true
|
||||
}
|
||||
}
|
||||
return enc, err
|
||||
}
|
||||
|
||||
// provideBuildStore is a Wire provider function that provides a
|
||||
// build datastore, configured from the environment, with metrics
|
||||
// enabled.
|
||||
func provideBuildStore(db *db.DB) core.BuildStore {
|
||||
builds := build.New(db)
|
||||
metric.BuildCount(builds)
|
||||
metric.PendingBuildCount(builds)
|
||||
metric.RunningBuildCount(builds)
|
||||
return builds
|
||||
}
|
||||
|
||||
// provideLogStore is a Wire provider function that provides a
|
||||
// log datastore, configured from the environment.
|
||||
func provideLogStore(db *db.DB, config config.Config) core.LogStore {
|
||||
s := logs.New(db)
|
||||
if config.S3.Bucket != "" {
|
||||
p := logs.NewS3Env(
|
||||
config.S3.Bucket,
|
||||
config.S3.Prefix,
|
||||
config.S3.Endpoint,
|
||||
config.S3.PathStyle,
|
||||
)
|
||||
return logs.NewCombined(p, s)
|
||||
}
|
||||
if config.AzureBlob.ContainerName != "" {
|
||||
p := logs.NewAzureBlobEnv(
|
||||
config.AzureBlob.ContainerName,
|
||||
config.AzureBlob.StorageAccountName,
|
||||
config.AzureBlob.StorageAccessKey,
|
||||
)
|
||||
return logs.NewCombined(p, s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// provideStageStore is a Wire provider function that provides a
|
||||
// stage datastore, configured from the environment, with metrics
|
||||
// enabled.
|
||||
func provideStageStore(db *db.DB) core.StageStore {
|
||||
stages := stage.New(db)
|
||||
metric.PendingJobCount(stages)
|
||||
metric.RunningJobCount(stages)
|
||||
return stages
|
||||
}
|
||||
|
||||
// provideRepoStore is a Wire provider function that provides a
|
||||
// user datastore, configured from the environment, with metrics
|
||||
// enabled.
|
||||
func provideRepoStore(db *db.DB) core.RepositoryStore {
|
||||
repos := repos.New(db)
|
||||
metric.RepoCount(repos)
|
||||
return repos
|
||||
}
|
||||
|
||||
// provideBatchStore is a Wire provider function that provides a
|
||||
// batcher. If the experimental batcher is enabled it is returned.
|
||||
func provideBatchStore(db *db.DB, config config.Config) core.Batcher {
|
||||
if config.Database.LegacyBatch {
|
||||
return batch.New(db)
|
||||
}
|
||||
return batch2.New(db)
|
||||
}
|
||||
|
||||
// provideUserStore is a Wire provider function that provides a
|
||||
// user datastore, configured from the environment, with metrics
|
||||
// enabled.
|
||||
func provideUserStore(db *db.DB, enc encrypt.Encrypter, config config.Config) core.UserStore {
|
||||
// create the user store with encryption iff the user
|
||||
// encryption feature flag is enabled.
|
||||
//
|
||||
// why not enable by default? because the user table is
|
||||
// accessed on every http request and we are unsure what,
|
||||
// if any performance implications user table encryption
|
||||
// may have on the system.
|
||||
//
|
||||
// it is very possible there are zero material performance
|
||||
// implications, however, if there is a performance regression
|
||||
// we could look at implementing in-memory lru caching, which
|
||||
// we already employ in other areas of the software.
|
||||
if config.Database.EncryptUserTable {
|
||||
logrus.Debugln("main: database encryption enabled for user table")
|
||||
users := user.New(db, enc)
|
||||
metric.UserCount(users)
|
||||
return users
|
||||
}
|
||||
|
||||
noenc, _ := encrypt.New("")
|
||||
users := user.New(db, noenc)
|
||||
metric.UserCount(users)
|
||||
return users
|
||||
}
|
@ -0,0 +1,193 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/drone/drone/cmd/drone-server/bootstrap"
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/metric/sink"
|
||||
"github.com/drone/drone/operator/runner"
|
||||
"github.com/drone/drone/service/canceler/reaper"
|
||||
"github.com/drone/drone/server"
|
||||
"github.com/drone/drone/trigger/cron"
|
||||
"github.com/drone/signal"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var envfile string
|
||||
flag.StringVar(&envfile, "env-file", ".env", "Read in a file of environment variables")
|
||||
flag.Parse()
|
||||
|
||||
godotenv.Load(envfile)
|
||||
config, err := config.Environ()
|
||||
if err != nil {
|
||||
logger := logrus.WithError(err)
|
||||
logger.Fatalln("main: invalid configuration")
|
||||
}
|
||||
|
||||
initLogging(config)
|
||||
ctx := signal.WithContext(
|
||||
context.Background(),
|
||||
)
|
||||
|
||||
// if trace level logging is enabled, output the
|
||||
// configuration parameters.
|
||||
if logrus.IsLevelEnabled(logrus.TraceLevel) {
|
||||
fmt.Println(config.String())
|
||||
}
|
||||
|
||||
app, err := InitializeApplication(config)
|
||||
if err != nil {
|
||||
logger := logrus.WithError(err)
|
||||
logger.Fatalln("main: cannot initialize server")
|
||||
}
|
||||
|
||||
// optionally bootstrap the system with administrative or
|
||||
// machine users configured in the environment.
|
||||
err = bootstrap.New(app.users).Bootstrap(ctx, &core.User{
|
||||
Login: config.Users.Create.Username,
|
||||
Machine: config.Users.Create.Machine,
|
||||
Admin: config.Users.Create.Admin,
|
||||
Hash: config.Users.Create.Token,
|
||||
})
|
||||
if err != nil {
|
||||
logger := logrus.WithError(err)
|
||||
logger.Fatalln("cannot bootstrap user account")
|
||||
}
|
||||
|
||||
g := errgroup.Group{}
|
||||
g.Go(func() error {
|
||||
logrus.WithFields(
|
||||
logrus.Fields{
|
||||
"proto": config.Server.Proto,
|
||||
"host": config.Server.Host,
|
||||
"port": config.Server.Port,
|
||||
"url": config.Server.Addr,
|
||||
"acme": config.Server.Acme,
|
||||
},
|
||||
).Infoln("starting the http server")
|
||||
return app.server.ListenAndServe(ctx)
|
||||
})
|
||||
|
||||
// launches the datadog sink in a goroutine. If the sink
|
||||
// is disabled, the goroutine exits immediately without error.
|
||||
g.Go(func() (err error) {
|
||||
if !config.Datadog.Enabled {
|
||||
return nil
|
||||
}
|
||||
return app.sink.Start(ctx)
|
||||
})
|
||||
|
||||
// launches the cron runner in a goroutine. If the cron
|
||||
// runner is disabled, the goroutine exits immediately
|
||||
// without error.
|
||||
g.Go(func() (err error) {
|
||||
if config.Cron.Disabled {
|
||||
return nil
|
||||
}
|
||||
logrus.WithField("interval", config.Cron.Interval.String()).
|
||||
Infoln("starting the cron scheduler")
|
||||
return app.cron.Start(ctx, config.Cron.Interval)
|
||||
})
|
||||
|
||||
// launches the reaper in a goroutine. If the reaper
|
||||
// is disabled, the goroutine exits immediately
|
||||
// without error.
|
||||
g.Go(func() (err error) {
|
||||
if config.Cleanup.Disabled {
|
||||
return nil
|
||||
}
|
||||
logrus.WithField("interval", config.Cleanup.Interval.String()).
|
||||
Infoln("starting the zombie build reaper")
|
||||
return app.reaper.Start(ctx, config.Cleanup.Interval)
|
||||
})
|
||||
|
||||
// launches the build runner in a goroutine. If the local
|
||||
// runner is disabled (because nomad or kubernetes is enabled)
|
||||
// then the goroutine exits immediately without error.
|
||||
g.Go(func() (err error) {
|
||||
if app.runner == nil {
|
||||
return nil
|
||||
}
|
||||
logrus.WithField("threads", config.Runner.Capacity).
|
||||
Infoln("main: starting the local build runner")
|
||||
return app.runner.Start(ctx, config.Runner.Capacity)
|
||||
})
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
logrus.WithError(err).Fatalln("program terminated")
|
||||
}
|
||||
}
|
||||
|
||||
// helper function configures the logging.
|
||||
func initLogging(c config.Config) {
|
||||
if c.Logging.Debug {
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
if c.Logging.Trace {
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
if c.Logging.Text {
|
||||
logrus.SetFormatter(&logrus.TextFormatter{
|
||||
ForceColors: c.Logging.Color,
|
||||
DisableColors: !c.Logging.Color,
|
||||
})
|
||||
} else {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{
|
||||
PrettyPrint: c.Logging.Pretty,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// application is the main struct for the Drone server.
|
||||
type application struct {
|
||||
cron *cron.Scheduler
|
||||
reaper *reaper.Reaper
|
||||
sink *sink.Datadog
|
||||
runner *runner.Runner
|
||||
server *server.Server
|
||||
users core.UserStore
|
||||
}
|
||||
|
||||
// newApplication creates a new application struct.
|
||||
func newApplication(
|
||||
cron *cron.Scheduler,
|
||||
reaper *reaper.Reaper,
|
||||
sink *sink.Datadog,
|
||||
runner *runner.Runner,
|
||||
server *server.Server,
|
||||
users core.UserStore) application {
|
||||
return application{
|
||||
users: users,
|
||||
cron: cron,
|
||||
sink: sink,
|
||||
server: server,
|
||||
runner: runner,
|
||||
reaper: reaper,
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//+build wireinject
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
func InitializeApplication(config config.Config) (application, error) {
|
||||
wire.Build(
|
||||
clientSet,
|
||||
licenseSet,
|
||||
loginSet,
|
||||
pluginSet,
|
||||
runnerSet,
|
||||
schedulerSet,
|
||||
serverSet,
|
||||
serviceSet,
|
||||
storeSet,
|
||||
externalSet,
|
||||
newApplication,
|
||||
)
|
||||
return application{}, nil
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
// Code generated by Wire. DO NOT EDIT.
|
||||
|
||||
//go:generate wire
|
||||
//+build !wireinject
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/handler/api"
|
||||
"github.com/drone/drone/handler/web"
|
||||
"github.com/drone/drone/livelog"
|
||||
"github.com/drone/drone/operator/manager"
|
||||
"github.com/drone/drone/pubsub"
|
||||
"github.com/drone/drone/service/canceler"
|
||||
"github.com/drone/drone/service/commit"
|
||||
"github.com/drone/drone/service/hook/parser"
|
||||
"github.com/drone/drone/service/license"
|
||||
"github.com/drone/drone/service/linker"
|
||||
"github.com/drone/drone/service/token"
|
||||
"github.com/drone/drone/service/transfer"
|
||||
"github.com/drone/drone/service/user"
|
||||
"github.com/drone/drone/store/card"
|
||||
"github.com/drone/drone/store/cron"
|
||||
"github.com/drone/drone/store/perm"
|
||||
"github.com/drone/drone/store/secret"
|
||||
"github.com/drone/drone/store/secret/global"
|
||||
"github.com/drone/drone/store/step"
|
||||
"github.com/drone/drone/store/template"
|
||||
"github.com/drone/drone/trigger"
|
||||
cron2 "github.com/drone/drone/trigger/cron"
|
||||
)
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
// Injectors from wire.go:
|
||||
|
||||
func InitializeApplication(config2 config.Config) (application, error) {
|
||||
client := provideClient(config2)
|
||||
refresher := provideRefresher(config2)
|
||||
db, err := provideDatabase(config2)
|
||||
if err != nil {
|
||||
return application{}, err
|
||||
}
|
||||
encrypter, err := provideEncrypter(config2)
|
||||
if err != nil {
|
||||
return application{}, err
|
||||
}
|
||||
userStore := provideUserStore(db, encrypter, config2)
|
||||
renewer := token.Renewer(refresher, userStore)
|
||||
commitService := commit.New(client, renewer)
|
||||
cronStore := cron.New(db)
|
||||
repositoryStore := provideRepoStore(db)
|
||||
buildStore := provideBuildStore(db)
|
||||
redisDB, err := provideRedisClient(config2)
|
||||
if err != nil {
|
||||
return application{}, err
|
||||
}
|
||||
corePubsub := pubsub.New(redisDB)
|
||||
stageStore := provideStageStore(db)
|
||||
scheduler := provideScheduler(stageStore, redisDB)
|
||||
statusService := provideStatusService(client, renewer, config2)
|
||||
stepStore := step.New(db)
|
||||
system := provideSystem(config2)
|
||||
webhookSender := provideWebhookPlugin(config2, system)
|
||||
coreCanceler := canceler.New(buildStore, corePubsub, repositoryStore, scheduler, stageStore, statusService, stepStore, userStore, webhookSender)
|
||||
fileService := provideContentService(client, renewer)
|
||||
configService := provideConfigPlugin(client, fileService, config2)
|
||||
templateStore := template.New(db)
|
||||
convertService := provideConvertPlugin(client, fileService, config2, templateStore)
|
||||
validateService := provideValidatePlugin(config2)
|
||||
triggerer := trigger.New(coreCanceler, configService, convertService, commitService, statusService, buildStore, scheduler, repositoryStore, userStore, validateService, webhookSender)
|
||||
cronScheduler := cron2.New(commitService, cronStore, repositoryStore, userStore, triggerer)
|
||||
reaper := provideReaper(repositoryStore, buildStore, stageStore, coreCanceler, config2)
|
||||
coreLicense := provideLicense(client, config2)
|
||||
datadog := provideDatadog(userStore, repositoryStore, buildStore, system, coreLicense, config2)
|
||||
cardStore := card.New(db)
|
||||
logStore := provideLogStore(db, config2)
|
||||
logStream := livelog.New(redisDB)
|
||||
netrcService := provideNetrcService(client, renewer, config2)
|
||||
secretStore := secret.New(db, encrypter)
|
||||
globalSecretStore := global.New(db, encrypter)
|
||||
buildManager := manager.New(buildStore, cardStore, configService, convertService, corePubsub, logStore, logStream, netrcService, repositoryStore, scheduler, secretStore, globalSecretStore, statusService, stageStore, stepStore, system, userStore, webhookSender)
|
||||
secretService := provideSecretPlugin(config2)
|
||||
registryService := provideRegistryPlugin(config2)
|
||||
runner := provideRunner(buildManager, secretService, registryService, config2)
|
||||
hookService := provideHookService(client, renewer, config2)
|
||||
licenseService := license.NewService(userStore, repositoryStore, buildStore, coreLicense)
|
||||
organizationService := provideOrgService(client, renewer)
|
||||
permStore := perm.New(db)
|
||||
repositoryService := provideRepositoryService(client, renewer, config2)
|
||||
session, err := provideSession(userStore, config2)
|
||||
if err != nil {
|
||||
return application{}, err
|
||||
}
|
||||
batcher := provideBatchStore(db, config2)
|
||||
syncer := provideSyncer(repositoryService, repositoryStore, userStore, batcher, config2)
|
||||
transferer := transfer.New(repositoryStore, permStore)
|
||||
userService := user.New(client, renewer)
|
||||
server := api.New(buildStore, commitService, cardStore, cronStore, corePubsub, globalSecretStore, hookService, logStore, coreLicense, licenseService, organizationService, permStore, repositoryStore, repositoryService, scheduler, secretStore, stageStore, stepStore, statusService, session, logStream, syncer, system, templateStore, transferer, triggerer, userStore, userService, webhookSender)
|
||||
admissionService := provideAdmissionPlugin(client, organizationService, userService, config2)
|
||||
hookParser := parser.New(client)
|
||||
coreLinker := linker.New(client)
|
||||
middleware := provideLogin(config2)
|
||||
options := provideServerOptions(config2)
|
||||
webServer := web.New(admissionService, buildStore, client, hookParser, coreLicense, licenseService, coreLinker, middleware, repositoryStore, session, syncer, triggerer, userStore, userService, webhookSender, options, system)
|
||||
mainRpcHandlerV1 := provideRPC(buildManager, config2)
|
||||
mainRpcHandlerV2 := provideRPC2(buildManager, config2)
|
||||
mainHealthzHandler := provideHealthz()
|
||||
metricServer := provideMetric(session, config2)
|
||||
mainPprofHandler := providePprof(config2)
|
||||
mux := provideRouter(server, webServer, mainRpcHandlerV1, mainRpcHandlerV2, mainHealthzHandler, metricServer, mainPprofHandler)
|
||||
serverServer := provideServer(mux, config2)
|
||||
mainApplication := newApplication(cronScheduler, reaper, datadog, runner, serverServer, userStore)
|
||||
return mainApplication, nil
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// AdmissionService grants access to the system. The service can
|
||||
// be used to restrict access to authorized users, such as
|
||||
// members of an organization in your source control management
|
||||
// system.
|
||||
type AdmissionService interface {
|
||||
Admit(context.Context, *User) error
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Batch represents a Batch request to synchronize the local
|
||||
// repository and permission store for a user account.
|
||||
type Batch struct {
|
||||
Insert []*Repository `json:"insert"`
|
||||
Update []*Repository `json:"update"`
|
||||
Rename []*Repository `json:"rename"`
|
||||
Revoke []*Repository `json:"revoke"`
|
||||
}
|
||||
|
||||
// Batcher batch updates the user account.
|
||||
type Batcher interface {
|
||||
Batch(context.Context, *User, *Batch) error
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Build represents a build execution.
|
||||
type Build struct {
|
||||
ID int64 `db:"build_id" json:"id"`
|
||||
RepoID int64 `db:"build_repo_id" json:"repo_id"`
|
||||
Trigger string `db:"build_trigger" json:"trigger"`
|
||||
Number int64 `db:"build_number" json:"number"`
|
||||
Parent int64 `db:"build_parent" json:"parent,omitempty"`
|
||||
Status string `db:"build_status" json:"status"`
|
||||
Error string `db:"build_error" json:"error,omitempty"`
|
||||
Event string `db:"build_event" json:"event"`
|
||||
Action string `db:"build_action" json:"action"`
|
||||
Link string `db:"build_link" json:"link"`
|
||||
Timestamp int64 `db:"build_timestamp" json:"timestamp"`
|
||||
Title string `db:"build_title" json:"title,omitempty"`
|
||||
Message string `db:"build_message" json:"message"`
|
||||
Before string `db:"build_before" json:"before"`
|
||||
After string `db:"build_after" json:"after"`
|
||||
Ref string `db:"build_ref" json:"ref"`
|
||||
Fork string `db:"build_source_repo" json:"source_repo"`
|
||||
Source string `db:"build_source" json:"source"`
|
||||
Target string `db:"build_target" json:"target"`
|
||||
Author string `db:"build_author" json:"author_login"`
|
||||
AuthorName string `db:"build_author_name" json:"author_name"`
|
||||
AuthorEmail string `db:"build_author_email" json:"author_email"`
|
||||
AuthorAvatar string `db:"build_author_avatar" json:"author_avatar"`
|
||||
Sender string `db:"build_sender" json:"sender"`
|
||||
Params map[string]string `db:"build_params" json:"params,omitempty"`
|
||||
Cron string `db:"build_cron" json:"cron,omitempty"`
|
||||
Deploy string `db:"build_deploy" json:"deploy_to,omitempty"`
|
||||
DeployID int64 `db:"build_deploy_id" json:"deploy_id,omitempty"`
|
||||
Debug bool `db:"build_debug" json:"debug,omitempty"`
|
||||
Started int64 `db:"build_started" json:"started"`
|
||||
Finished int64 `db:"build_finished" json:"finished"`
|
||||
Created int64 `db:"build_created" json:"created"`
|
||||
Updated int64 `db:"build_updated" json:"updated"`
|
||||
Version int64 `db:"build_version" json:"version"`
|
||||
Stages []*Stage `db:"-" json:"stages,omitempty"`
|
||||
}
|
||||
|
||||
// BuildStore defines operations for working with builds.
|
||||
type BuildStore interface {
|
||||
// Find returns a build from the datastore.
|
||||
Find(context.Context, int64) (*Build, error)
|
||||
|
||||
// FindNumber returns a build from the datastore by build number.
|
||||
FindNumber(context.Context, int64, int64) (*Build, error)
|
||||
|
||||
// FindLast returns the last build from the datastore by ref.
|
||||
FindRef(context.Context, int64, string) (*Build, error)
|
||||
|
||||
// List returns a list of builds from the datastore by repository id.
|
||||
List(context.Context, int64, int, int) ([]*Build, error)
|
||||
|
||||
// ListRef returns a list of builds from the datastore by ref.
|
||||
ListRef(context.Context, int64, string, int, int) ([]*Build, error)
|
||||
|
||||
// LatestBranches returns the latest builds from the
|
||||
// datastore by branch.
|
||||
LatestBranches(context.Context, int64) ([]*Build, error)
|
||||
|
||||
// LatestPulls returns the latest builds from the
|
||||
// datastore by pull request.
|
||||
LatestPulls(context.Context, int64) ([]*Build, error)
|
||||
|
||||
// LatestDeploys returns the latest builds from the
|
||||
// datastore by deployment target.
|
||||
LatestDeploys(context.Context, int64) ([]*Build, error)
|
||||
|
||||
// Pending returns a list of pending builds from the
|
||||
// datastore by repository id (DEPRECATED).
|
||||
Pending(context.Context) ([]*Build, error)
|
||||
|
||||
// Running returns a list of running builds from the
|
||||
// datastore by repository id (DEPRECATED).
|
||||
Running(context.Context) ([]*Build, error)
|
||||
|
||||
// Create persists a build to the datastore.
|
||||
Create(context.Context, *Build, []*Stage) error
|
||||
|
||||
// Update updates a build in the datastore.
|
||||
Update(context.Context, *Build) error
|
||||
|
||||
// Delete deletes a build from the datastore.
|
||||
Delete(context.Context, *Build) error
|
||||
|
||||
// DeletePull deletes a pull request index from the datastore.
|
||||
DeletePull(context.Context, int64, int) error
|
||||
|
||||
// DeleteBranch deletes a branch index from the datastore.
|
||||
DeleteBranch(context.Context, int64, string) error
|
||||
|
||||
// DeleteDeploy deletes a deploy index from the datastore.
|
||||
DeleteDeploy(context.Context, int64, string) error
|
||||
|
||||
// Purge deletes builds from the database where the build number is less than n.
|
||||
Purge(context.Context, int64, int64) error
|
||||
|
||||
// Count returns a count of builds.
|
||||
Count(context.Context) (int64, error)
|
||||
}
|
||||
|
||||
// IsDone returns true if the build has a completed state.
|
||||
func (b *Build) IsDone() bool {
|
||||
switch b.Status {
|
||||
case StatusWaiting,
|
||||
StatusPending,
|
||||
StatusRunning,
|
||||
StatusBlocked:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// IsFailed returns true if the build has failed
|
||||
func (b *Build) IsFailed() bool {
|
||||
switch b.Status {
|
||||
case StatusFailing,
|
||||
StatusKilled,
|
||||
StatusError:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,27 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Canceler cancels a build.
|
||||
type Canceler interface {
|
||||
// Cancel cancels the provided build.
|
||||
Cancel(context.Context, *Repository, *Build) error
|
||||
|
||||
// CancelPending cancels all pending builds of the same
|
||||
// type of as the provided build.
|
||||
CancelPending(context.Context, *Repository, *Build) error
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type CardInput struct {
|
||||
Schema string `json:"schema"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
// CardStore manages repository cards.
|
||||
type CardStore interface {
|
||||
// Find returns a card data stream from the datastore.
|
||||
Find(ctx context.Context, step int64) (io.ReadCloser, error)
|
||||
|
||||
// Create copies the card stream from Reader r to the datastore.
|
||||
Create(ctx context.Context, step int64, r io.Reader) error
|
||||
|
||||
// Update copies the card stream from Reader r to the datastore.
|
||||
Update(ctx context.Context, step int64, r io.Reader) error
|
||||
|
||||
// Delete purges the card data from the datastore.
|
||||
Delete(ctx context.Context, step int64) error
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// Commit represents a git commit.
|
||||
Commit struct {
|
||||
Sha string
|
||||
Ref string
|
||||
Message string
|
||||
Author *Committer
|
||||
Committer *Committer
|
||||
Link string
|
||||
}
|
||||
|
||||
// Committer represents the commit author.
|
||||
Committer struct {
|
||||
Name string
|
||||
Email string
|
||||
Date int64
|
||||
Login string
|
||||
Avatar string
|
||||
}
|
||||
|
||||
// Change represents a file change in a commit.
|
||||
Change struct {
|
||||
Path string
|
||||
Added bool
|
||||
Renamed bool
|
||||
Deleted bool
|
||||
}
|
||||
|
||||
// CommitService provides access to the commit history from
|
||||
// the external source code management service (e.g. GitHub).
|
||||
CommitService interface {
|
||||
// Find returns the commit information by sha.
|
||||
Find(ctx context.Context, user *User, repo, sha string) (*Commit, error)
|
||||
|
||||
// FindRef returns the commit information by reference.
|
||||
FindRef(ctx context.Context, user *User, repo, ref string) (*Commit, error)
|
||||
|
||||
// ListChanges returns the files change by sha or reference.
|
||||
ListChanges(ctx context.Context, user *User, repo, sha, ref string) ([]*Change, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,40 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// Config represents a pipeline config file.
|
||||
Config struct {
|
||||
Data string `json:"data"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
|
||||
// ConfigArgs represents a request for the pipeline
|
||||
// configuration file (e.g. .drone.yml)
|
||||
ConfigArgs struct {
|
||||
User *User `json:"-"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// ConfigService provides pipeline configuration from an
|
||||
// external service.
|
||||
ConfigService interface {
|
||||
Find(context.Context, *ConfigArgs) (*Config, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,35 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// ConvertArgs represents a request to the pipeline
|
||||
// conversion service.
|
||||
ConvertArgs struct {
|
||||
User *User `json:"-"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// ConvertService converts non-native pipeline
|
||||
// configuration formats to native configuration
|
||||
// formats (e.g. jsonnet to yaml).
|
||||
ConvertService interface {
|
||||
Convert(context.Context, *ConvertArgs) (*Config, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,117 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/gosimple/slug"
|
||||
"github.com/robfig/cron"
|
||||
)
|
||||
|
||||
var (
|
||||
errCronExprInvalid = errors.New("Invalid Cronjob Expression")
|
||||
errCronNameInvalid = errors.New("Invalid Cronjob Name")
|
||||
errCronBranchInvalid = errors.New("Invalid Cronjob Branch")
|
||||
)
|
||||
|
||||
type (
|
||||
// Cron defines a cron job.
|
||||
Cron struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
Name string `json:"name"`
|
||||
Expr string `json:"expr"`
|
||||
Next int64 `json:"next"`
|
||||
Prev int64 `json:"prev"`
|
||||
Event string `json:"event"`
|
||||
Branch string `json:"branch"`
|
||||
Target string `json:"target,omitempty"`
|
||||
Disabled bool `json:"disabled"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
Version int64 `json:"version"`
|
||||
}
|
||||
|
||||
// CronStore persists cron information to storage.
|
||||
CronStore interface {
|
||||
// List returns a cron list from the datastore.
|
||||
List(context.Context, int64) ([]*Cron, error)
|
||||
|
||||
// Ready returns a cron list from the datastore ready for execution.
|
||||
Ready(context.Context, int64) ([]*Cron, error)
|
||||
|
||||
// Find returns a cron job from the datastore.
|
||||
Find(context.Context, int64) (*Cron, error)
|
||||
|
||||
// FindName returns a cron job from the datastore.
|
||||
FindName(context.Context, int64, string) (*Cron, error)
|
||||
|
||||
// Create persists a new cron job to the datastore.
|
||||
Create(context.Context, *Cron) error
|
||||
|
||||
// Update persists an updated cron job to the datastore.
|
||||
Update(context.Context, *Cron) error
|
||||
|
||||
// Delete deletes a cron job from the datastore.
|
||||
Delete(context.Context, *Cron) error
|
||||
}
|
||||
)
|
||||
|
||||
// Validate validates the required fields and formats.
|
||||
func (c *Cron) Validate() error {
|
||||
_, err := cron.Parse(c.Expr)
|
||||
if err != nil {
|
||||
return errCronExprInvalid
|
||||
}
|
||||
switch {
|
||||
case c.Name == "":
|
||||
return errCronNameInvalid
|
||||
case c.Name != slug.Make(c.Name):
|
||||
return errCronNameInvalid
|
||||
case c.Branch == "":
|
||||
return errCronBranchInvalid
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// SetExpr sets the cron expression name and updates
|
||||
// the next execution date.
|
||||
func (c *Cron) SetExpr(expr string) error {
|
||||
_, err := cron.Parse(expr)
|
||||
if err != nil {
|
||||
return errCronExprInvalid
|
||||
}
|
||||
c.Expr = expr
|
||||
return c.Update()
|
||||
}
|
||||
|
||||
// SetName sets the cronjob name.
|
||||
func (c *Cron) SetName(name string) {
|
||||
c.Name = slug.Make(name)
|
||||
}
|
||||
|
||||
// Update updates the next Cron execution date.
|
||||
func (c *Cron) Update() error {
|
||||
sched, err := cron.Parse(c.Expr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Next = sched.Next(time.Now()).Unix()
|
||||
return nil
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,26 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
// Hook event constants.
|
||||
const (
|
||||
EventCron = "cron"
|
||||
EventCustom = "custom"
|
||||
EventPush = "push"
|
||||
EventPullRequest = "pull_request"
|
||||
EventTag = "tag"
|
||||
EventPromote = "promote"
|
||||
EventRollback = "rollback"
|
||||
)
|
@ -0,0 +1,40 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// File represents the raw file contents in the remote
|
||||
// version control system.
|
||||
File struct {
|
||||
Data []byte
|
||||
Hash []byte
|
||||
}
|
||||
|
||||
// FileArgs provides repository and commit details required
|
||||
// to fetch the file from the remote source code management
|
||||
// service.
|
||||
FileArgs struct {
|
||||
Commit string
|
||||
Ref string
|
||||
}
|
||||
|
||||
// FileService provides access to contents of files in
|
||||
// the remote source code management service (e.g. GitHub).
|
||||
FileService interface {
|
||||
Find(ctx context.Context, user *User, repo, commit, ref, path string) (*File, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,70 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Hook action constants.
|
||||
const (
|
||||
ActionOpen = "open"
|
||||
ActionClose = "close"
|
||||
ActionCreate = "create"
|
||||
ActionDelete = "delete"
|
||||
ActionSync = "sync"
|
||||
)
|
||||
|
||||
// Hook represents the payload of a post-commit hook.
|
||||
type Hook struct {
|
||||
Parent int64 `json:"parent"`
|
||||
Trigger string `json:"trigger"`
|
||||
Event string `json:"event"`
|
||||
Action string `json:"action"`
|
||||
Link string `json:"link"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Title string `json:"title"`
|
||||
Message string `json:"message"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
Ref string `json:"ref"`
|
||||
Fork string `json:"hook"`
|
||||
Source string `json:"source"`
|
||||
Target string `json:"target"`
|
||||
Author string `json:"author_login"`
|
||||
AuthorName string `json:"author_name"`
|
||||
AuthorEmail string `json:"author_email"`
|
||||
AuthorAvatar string `json:"author_avatar"`
|
||||
Deployment string `json:"deploy_to"`
|
||||
DeploymentID int64 `json:"deploy_id"`
|
||||
Debug bool `json:"debug"`
|
||||
Cron string `json:"cron"`
|
||||
Sender string `json:"sender"`
|
||||
Params map[string]string `json:"params"`
|
||||
}
|
||||
|
||||
// HookService manages post-commit hooks in the external
|
||||
// source code management service (e.g. GitHub).
|
||||
type HookService interface {
|
||||
Create(ctx context.Context, user *User, repo *Repository) error
|
||||
Delete(ctx context.Context, user *User, repo *Repository) error
|
||||
}
|
||||
|
||||
// HookParser parses a post-commit hook from the source
|
||||
// code management system, and returns normalized data.
|
||||
type HookParser interface {
|
||||
Parse(req *http.Request, secretFunc func(string) string) (*Hook, *Repository, error)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,75 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// License types.
|
||||
const (
|
||||
LicenseFoss = "foss"
|
||||
LicenseFree = "free"
|
||||
LicensePersonal = "personal"
|
||||
LicenseStandard = "standard"
|
||||
LicenseTrial = "trial"
|
||||
)
|
||||
|
||||
// ErrUserLimit is returned when attempting to create a new
|
||||
// user but the maximum number of allowed user accounts
|
||||
// is exceeded.
|
||||
var ErrUserLimit = errors.New("User limit exceeded")
|
||||
|
||||
// ErrRepoLimit is returned when attempting to create a new
|
||||
// repository but the maximum number of allowed repositories
|
||||
// is exceeded.
|
||||
var ErrRepoLimit = errors.New("Repository limit exceeded")
|
||||
|
||||
// ErrBuildLimit is returned when attempting to create a new
|
||||
// build but the maximum number of allowed builds is exceeded.
|
||||
var ErrBuildLimit = errors.New("Build limit exceeded")
|
||||
|
||||
type (
|
||||
// License defines software license parameters.
|
||||
License struct {
|
||||
Licensor string `json:"-"`
|
||||
Subscription string `json:"-"`
|
||||
Expires time.Time `json:"expires_at,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Repos int64 `json:"repos,omitempty"`
|
||||
Users int64 `json:"users,omitempty"`
|
||||
Builds int64 `json:"builds,omitempty"`
|
||||
Nodes int64 `json:"nodes,omitempty"`
|
||||
}
|
||||
|
||||
// LicenseService provides access to the license
|
||||
// service and can be used to check for violations
|
||||
// and expirations.
|
||||
LicenseService interface {
|
||||
// Exceeded returns true if the system has exceeded
|
||||
// its limits as defined in the license.
|
||||
Exceeded(context.Context) (bool, error)
|
||||
|
||||
// Expired returns true if the license is expired.
|
||||
Expired(context.Context) bool
|
||||
}
|
||||
)
|
||||
|
||||
// Expired returns true if the license is expired.
|
||||
func (l *License) Expired() bool {
|
||||
return l.Expires.IsZero() == false && time.Now().After(l.Expires)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Linker provides a deep link to a git resource in the
|
||||
// source control management system for a given build.
|
||||
type Linker interface {
|
||||
Link(ctx context.Context, repo, ref, sha string) (string, error)
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Line represents a line in the logs.
|
||||
type Line struct {
|
||||
Number int `json:"pos"`
|
||||
Message string `json:"out"`
|
||||
Timestamp int64 `json:"time"`
|
||||
}
|
||||
|
||||
// LogStore persists build output to storage.
|
||||
type LogStore interface {
|
||||
// Find returns a log stream from the datastore.
|
||||
Find(ctx context.Context, stage int64) (io.ReadCloser, error)
|
||||
|
||||
// Create writes copies the log stream from Reader r to the datastore.
|
||||
Create(ctx context.Context, stage int64, r io.Reader) error
|
||||
|
||||
// Update writes copies the log stream from Reader r to the datastore.
|
||||
Update(ctx context.Context, stage int64, r io.Reader) error
|
||||
|
||||
// Delete purges the log stream from the datastore.
|
||||
Delete(ctx context.Context, stage int64) error
|
||||
}
|
||||
|
||||
// LogStream manages a live stream of logs.
|
||||
type LogStream interface {
|
||||
// Create creates the log stream for the step ID.
|
||||
Create(context.Context, int64) error
|
||||
|
||||
// Delete deletes the log stream for the step ID.
|
||||
Delete(context.Context, int64) error
|
||||
|
||||
// Writes writes to the log stream.
|
||||
Write(context.Context, int64, *Line) error
|
||||
|
||||
// Tail tails the log stream.
|
||||
Tail(context.Context, int64) (<-chan *Line, <-chan error)
|
||||
|
||||
// Info returns internal stream information.
|
||||
Info(context.Context) *LogStreamInfo
|
||||
}
|
||||
|
||||
// LogStreamInfo provides internal stream information. This can
|
||||
// be used to monitor the number of registered streams and
|
||||
// subscribers.
|
||||
type LogStreamInfo struct {
|
||||
// Streams is a key-value pair where the key is the step
|
||||
// identifier, and the value is the count of subscribers
|
||||
// streaming the logs.
|
||||
Streams map[int64]int `json:"streams"`
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type (
|
||||
// Netrc contains login and initialization information used by
|
||||
// an automated login process.
|
||||
Netrc struct {
|
||||
Machine string `json:"machine"`
|
||||
Login string `json:"login"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
// NetrcService returns a valid netrc file that can be used
|
||||
// to authenticate and clone a private repository. If
|
||||
// authentication is not required or enabled, a nil Netrc
|
||||
// file and nil error are returned.
|
||||
NetrcService interface {
|
||||
Create(context.Context, *User, *Repository) (*Netrc, error)
|
||||
}
|
||||
)
|
||||
|
||||
// SetMachine sets the netrc machine from a URL value.
|
||||
func (n *Netrc) SetMachine(address string) error {
|
||||
url, err := url.Parse(address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.Machine = url.Hostname()
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns the string representation of a netrc file.
|
||||
func (n *Netrc) String() string {
|
||||
return fmt.Sprintf("machine %s login %s password %s",
|
||||
n.Machine,
|
||||
n.Login,
|
||||
n.Password,
|
||||
)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,38 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Organization represents an organization in the source
|
||||
// code management system (e.g. GitHub).
|
||||
type Organization struct {
|
||||
Name string
|
||||
Avatar string
|
||||
}
|
||||
|
||||
// OrganizationService provides access to organization and
|
||||
// team access in the external source code management system
|
||||
// (e.g. GitHub).
|
||||
type OrganizationService interface {
|
||||
// List returns a list of organization to which the
|
||||
// user is a member.
|
||||
List(context.Context, *User) ([]*Organization, error)
|
||||
|
||||
// Membership returns true if the user is a member
|
||||
// of the organization, and true if the user is an
|
||||
// of the organization.
|
||||
Membership(context.Context, *User, string) (bool, bool, error)
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// Perm represents an individuals repository
|
||||
// permission.
|
||||
Perm struct {
|
||||
UserID int64 `db:"perm_user_id" json:"-"`
|
||||
RepoUID string `db:"perm_repo_uid" json:"-"`
|
||||
Read bool `db:"perm_read" json:"read"`
|
||||
Write bool `db:"perm_write" json:"write"`
|
||||
Admin bool `db:"perm_admin" json:"admin"`
|
||||
Synced int64 `db:"perm_synced" json:"-"`
|
||||
Created int64 `db:"perm_created" json:"-"`
|
||||
Updated int64 `db:"perm_updated" json:"-"`
|
||||
}
|
||||
|
||||
// Collaborator represents a project collaborator,
|
||||
// and provides the account and repository permissions
|
||||
// details.
|
||||
Collaborator struct {
|
||||
UserID int64 `db:"perm_user_id" json:"user_id"`
|
||||
RepoUID string `db:"perm_repo_uid" json:"repo_id"`
|
||||
Login string `db:"user_login" json:"login"`
|
||||
Avatar string `db:"user_avatar" json:"avatar"`
|
||||
Read bool `db:"perm_read" json:"read"`
|
||||
Write bool `db:"perm_write" json:"write"`
|
||||
Admin bool `db:"perm_admin" json:"admin"`
|
||||
Synced int64 `db:"perm_synced" json:"synced"`
|
||||
Created int64 `db:"perm_created" json:"created"`
|
||||
Updated int64 `db:"perm_updated" json:"updated"`
|
||||
}
|
||||
|
||||
// PermStore defines operations for working with
|
||||
// repository permissions.
|
||||
PermStore interface {
|
||||
// Find returns a project member from the
|
||||
// datastore.
|
||||
Find(ctx context.Context, repoUID string, userID int64) (*Perm, error)
|
||||
|
||||
// List returns a list of project members from the
|
||||
// datastore.
|
||||
List(ctx context.Context, repoUID string) ([]*Collaborator, error)
|
||||
|
||||
// Update persists an updated project member
|
||||
// to the datastore.
|
||||
Update(context.Context, *Perm) error
|
||||
|
||||
// Delete deletes a project member from the
|
||||
// datastore.
|
||||
Delete(context.Context, *Perm) error
|
||||
}
|
||||
)
|
@ -0,0 +1,37 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Message defines a build change.
|
||||
type Message struct {
|
||||
Repository string
|
||||
Visibility string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Pubsub provides publish subscriber capabilities, distributing
|
||||
// messages from multiple publishers to multiple subscribers.
|
||||
type Pubsub interface {
|
||||
// Publish publishes the message to all subscribers.
|
||||
Publish(context.Context, *Message) error
|
||||
|
||||
// Subscribe subscribes to the message broker.
|
||||
Subscribe(context.Context) (<-chan *Message, <-chan error)
|
||||
|
||||
// Subscribers returns a count of subscribers.
|
||||
Subscribers() (int, error)
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone-yaml/yaml"
|
||||
)
|
||||
|
||||
const (
|
||||
// RegistryPull policy allows pulling from a registry.
|
||||
RegistryPull = "pull"
|
||||
|
||||
// RegistryPush Policy allows pushing to a registry for
|
||||
// all event types except pull requests.
|
||||
RegistryPush = "push"
|
||||
|
||||
// RegistryPushPullRequest Policy allows pushing to a
|
||||
// registry for all event types, including pull requests.
|
||||
RegistryPushPullRequest = "push-pull-request"
|
||||
)
|
||||
|
||||
type (
|
||||
// Registry represents a docker registry with credentials.
|
||||
Registry struct {
|
||||
Address string `json:"address"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Policy string `json:"policy"`
|
||||
}
|
||||
|
||||
// RegistryArgs provides arguments for requesting
|
||||
// registry credentials from the remote service.
|
||||
RegistryArgs struct {
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Conf *yaml.Manifest `json:"-"`
|
||||
Pipeline *yaml.Pipeline `json:"-"`
|
||||
}
|
||||
|
||||
// RegistryService provides registry credentials from an
|
||||
// external service.
|
||||
RegistryService interface {
|
||||
// List returns registry credentials from the global
|
||||
// remote registry plugin.
|
||||
List(context.Context, *RegistryArgs) ([]*Registry, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,24 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Renewer renews the user account authorization. If
|
||||
// successful, the user token and token expiry attributes
|
||||
// are updated, and persisted to the datastore.
|
||||
type Renewer interface {
|
||||
Renew(ctx context.Context, user *User, force bool) error
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Repository visibility.
|
||||
const (
|
||||
VisibilityPublic = "public"
|
||||
VisibilityPrivate = "private"
|
||||
VisibilityInternal = "internal"
|
||||
)
|
||||
|
||||
// Version control systems.
|
||||
const (
|
||||
VersionControlGit = "git"
|
||||
VersionControlMercurial = "hg"
|
||||
)
|
||||
|
||||
type (
|
||||
// Repository represents a source code repository.
|
||||
Repository struct {
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Namespace string `json:"namespace"`
|
||||
Name string `json:"name"`
|
||||
Slug string `json:"slug"`
|
||||
SCM string `json:"scm"`
|
||||
HTTPURL string `json:"git_http_url"`
|
||||
SSHURL string `json:"git_ssh_url"`
|
||||
Link string `json:"link"`
|
||||
Branch string `json:"default_branch"`
|
||||
Private bool `json:"private"`
|
||||
Visibility string `json:"visibility"`
|
||||
Active bool `json:"active"`
|
||||
Config string `json:"config_path"`
|
||||
Trusted bool `json:"trusted"`
|
||||
Protected bool `json:"protected"`
|
||||
IgnoreForks bool `json:"ignore_forks"`
|
||||
IgnorePulls bool `json:"ignore_pull_requests"`
|
||||
CancelPulls bool `json:"auto_cancel_pull_requests"`
|
||||
CancelPush bool `json:"auto_cancel_pushes"`
|
||||
CancelRunning bool `json:"auto_cancel_running"`
|
||||
Timeout int64 `json:"timeout"`
|
||||
Throttle int64 `json:"throttle,omitempty"`
|
||||
Counter int64 `json:"counter"`
|
||||
Synced int64 `json:"synced"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
Version int64 `json:"version"`
|
||||
Signer string `json:"-"`
|
||||
Secret string `json:"-"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Perms *Perm `json:"permissions,omitempty"`
|
||||
Archived bool `json:"archived"`
|
||||
}
|
||||
|
||||
RepoBuildStage struct {
|
||||
RepoNamespace string `json:"repo_namespace"`
|
||||
RepoName string `json:"repo_name"`
|
||||
RepoSlug string `json:"repo_slug"`
|
||||
BuildNumber int64 `json:"build_number"`
|
||||
BuildAuthor string `json:"build_author"`
|
||||
BuildAuthorName string `json:"build_author_name"`
|
||||
BuildAuthorEmail string `json:"build_author_email"`
|
||||
BuildAuthorAvatar string `json:"build_author_avatar"`
|
||||
BuildSender string `json:"build_sender"`
|
||||
BuildStarted int64 `json:"build_started"`
|
||||
BuildFinished int64 `json:"build_finished"`
|
||||
BuildCreated int64 `json:"build_created"`
|
||||
BuildUpdated int64 `json:"build_updated"`
|
||||
StageName string `json:"stage_name"`
|
||||
StageKind string `json:"stage_kind"`
|
||||
StageType string `json:"stage_type"`
|
||||
StageStatus string `json:"stage_status"`
|
||||
StageMachine string `json:"stage_machine"`
|
||||
StageOS string `json:"stage_os"`
|
||||
StageArch string `json:"stage_arch"`
|
||||
StageVariant string `json:"stage_variant"`
|
||||
StageKernel string `json:"stage_kernel"`
|
||||
StageLimit string `json:"stage_limit"`
|
||||
StageLimitRepo string `json:"stage_limit_repo"`
|
||||
StageStarted int64 `json:"stage_started"`
|
||||
StageStopped int64 `json:"stage_stopped"`
|
||||
}
|
||||
|
||||
// RepositoryStore defines operations for working with repositories.
|
||||
RepositoryStore interface {
|
||||
// List returns a repository list from the datastore.
|
||||
List(context.Context, int64) ([]*Repository, error)
|
||||
|
||||
// ListLatest returns a unique repository list form
|
||||
// the datastore with the most recent build.
|
||||
ListLatest(context.Context, int64) ([]*Repository, error)
|
||||
|
||||
// ListRecent returns a non-unique repository list form
|
||||
// the datastore with the most recent builds.
|
||||
ListRecent(context.Context, int64) ([]*Repository, error)
|
||||
|
||||
// ListIncomplete returns a non-unique repository list form
|
||||
// the datastore with incomplete builds.
|
||||
ListIncomplete(context.Context) ([]*Repository, error)
|
||||
|
||||
// ListRunningStatus returns a list of build / repository /stage information for builds that are incomplete.
|
||||
ListRunningStatus(context.Context) ([]*RepoBuildStage, error)
|
||||
|
||||
// ListAll returns a paginated list of all repositories
|
||||
// stored in the database, including disabled repositories.
|
||||
ListAll(ctx context.Context, limit, offset int) ([]*Repository, error)
|
||||
|
||||
// Find returns a repository from the datastore.
|
||||
Find(context.Context, int64) (*Repository, error)
|
||||
|
||||
// FindName returns a named repository from the datastore.
|
||||
FindName(context.Context, string, string) (*Repository, error)
|
||||
|
||||
// Create persists a new repository in the datastore.
|
||||
Create(context.Context, *Repository) error
|
||||
|
||||
// Activate persists the activated repository to the datastore.
|
||||
Activate(context.Context, *Repository) error
|
||||
|
||||
// Update persists repository changes to the datastore.
|
||||
Update(context.Context, *Repository) error
|
||||
|
||||
// Delete deletes a repository from the datastore.
|
||||
Delete(context.Context, *Repository) error
|
||||
|
||||
// Count returns a count of activated repositories.
|
||||
Count(context.Context) (int64, error)
|
||||
|
||||
// Increment returns an incremented build number
|
||||
Increment(context.Context, *Repository) (*Repository, error)
|
||||
}
|
||||
|
||||
// RepositoryService provides access to repository information
|
||||
// in the remote source code management system (e.g. GitHub).
|
||||
RepositoryService interface {
|
||||
// List returns a list of repositories.
|
||||
List(ctx context.Context, user *User) ([]*Repository, error)
|
||||
|
||||
// Find returns the named repository details.
|
||||
Find(ctx context.Context, user *User, repo string) (*Repository, error)
|
||||
|
||||
// FindPerm returns the named repository permissions.
|
||||
FindPerm(ctx context.Context, user *User, repo string) (*Perm, error)
|
||||
}
|
||||
)
|
@ -0,0 +1,58 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Filter provides filter criteria to limit stages requested
|
||||
// from the scheduler.
|
||||
type Filter struct {
|
||||
Kind string
|
||||
Type string
|
||||
OS string
|
||||
Arch string
|
||||
Kernel string
|
||||
Variant string
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// Scheduler schedules Build stages for execution.
|
||||
type Scheduler interface {
|
||||
// Schedule schedules the stage for execution.
|
||||
Schedule(context.Context, *Stage) error
|
||||
|
||||
// Request requests the next stage scheduled for execution.
|
||||
Request(context.Context, Filter) (*Stage, error)
|
||||
|
||||
// Cancel cancels scheduled or running jobs associated
|
||||
// with the parent build ID.
|
||||
Cancel(context.Context, int64) error
|
||||
|
||||
// Cancelled blocks and listens for a cancellation event and
|
||||
// returns true if the build has been cancelled.
|
||||
Cancelled(context.Context, int64) (bool, error)
|
||||
|
||||
// Pause pauses the scheduler and prevents new pipelines
|
||||
// from being scheduled for execution.
|
||||
Pause(context.Context) error
|
||||
|
||||
// Resume unpauses the scheduler, allowing new pipelines
|
||||
// to be scheduled for execution.
|
||||
Resume(context.Context) error
|
||||
|
||||
// Stats provides statistics for underlying scheduler. The
|
||||
// data format is scheduler-specific.
|
||||
Stats(context.Context) (interface{}, error)
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"regexp"
|
||||
|
||||
"github.com/drone/drone-yaml/yaml"
|
||||
)
|
||||
|
||||
var (
|
||||
errSecretNameInvalid = errors.New("Invalid Secret Name")
|
||||
errSecretDataInvalid = errors.New("Invalid Secret Value")
|
||||
)
|
||||
|
||||
type (
|
||||
// Secret represents a secret variable, such as a password or token,
|
||||
// that is provided to the build at runtime.
|
||||
Secret struct {
|
||||
ID int64 `json:"id,omitempty"`
|
||||
RepoID int64 `json:"repo_id,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Data string `json:"data,omitempty"`
|
||||
PullRequest bool `json:"pull_request,omitempty"`
|
||||
PullRequestPush bool `json:"pull_request_push,omitempty"`
|
||||
}
|
||||
|
||||
// SecretArgs provides arguments for requesting secrets
|
||||
// from the remote service.
|
||||
SecretArgs struct {
|
||||
Name string `json:"name"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Conf *yaml.Manifest `json:"-"`
|
||||
}
|
||||
|
||||
// SecretStore manages repository secrets.
|
||||
SecretStore interface {
|
||||
// List returns a secret list from the datastore.
|
||||
List(context.Context, int64) ([]*Secret, error)
|
||||
|
||||
// Find returns a secret from the datastore.
|
||||
Find(context.Context, int64) (*Secret, error)
|
||||
|
||||
// FindName returns a secret from the datastore.
|
||||
FindName(context.Context, int64, string) (*Secret, error)
|
||||
|
||||
// Create persists a new secret to the datastore.
|
||||
Create(context.Context, *Secret) error
|
||||
|
||||
// Update persists an updated secret to the datastore.
|
||||
Update(context.Context, *Secret) error
|
||||
|
||||
// Delete deletes a secret from the datastore.
|
||||
Delete(context.Context, *Secret) error
|
||||
}
|
||||
|
||||
// GlobalSecretStore manages global secrets accessible to
|
||||
// all repositories in the system.
|
||||
GlobalSecretStore interface {
|
||||
// List returns a secret list from the datastore.
|
||||
List(ctx context.Context, namespace string) ([]*Secret, error)
|
||||
|
||||
// ListAll returns a secret list from the datastore
|
||||
// for all namespaces.
|
||||
ListAll(ctx context.Context) ([]*Secret, error)
|
||||
|
||||
// Find returns a secret from the datastore.
|
||||
Find(ctx context.Context, id int64) (*Secret, error)
|
||||
|
||||
// FindName returns a secret from the datastore.
|
||||
FindName(ctx context.Context, namespace, name string) (*Secret, error)
|
||||
|
||||
// Create persists a new secret to the datastore.
|
||||
Create(ctx context.Context, secret *Secret) error
|
||||
|
||||
// Update persists an updated secret to the datastore.
|
||||
Update(ctx context.Context, secret *Secret) error
|
||||
|
||||
// Delete deletes a secret from the datastore.
|
||||
Delete(ctx context.Context, secret *Secret) error
|
||||
}
|
||||
|
||||
// SecretService provides secrets from an external service.
|
||||
SecretService interface {
|
||||
// Find returns a named secret from the global remote service.
|
||||
Find(context.Context, *SecretArgs) (*Secret, error)
|
||||
}
|
||||
)
|
||||
|
||||
// Validate validates the required fields and formats.
|
||||
func (s *Secret) Validate() error {
|
||||
switch {
|
||||
case len(s.Name) == 0:
|
||||
return errSecretNameInvalid
|
||||
case len(s.Data) == 0:
|
||||
return errSecretDataInvalid
|
||||
case slugRE.MatchString(s.Name):
|
||||
return errSecretNameInvalid
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Copy makes a copy of the secret without the value.
|
||||
func (s *Secret) Copy() *Secret {
|
||||
return &Secret{
|
||||
ID: s.ID,
|
||||
RepoID: s.RepoID,
|
||||
Namespace: s.Namespace,
|
||||
Name: s.Name,
|
||||
Type: s.Type,
|
||||
PullRequest: s.PullRequest,
|
||||
PullRequestPush: s.PullRequestPush,
|
||||
}
|
||||
}
|
||||
|
||||
// slug regular expression
|
||||
var slugRE = regexp.MustCompile("[^a-zA-Z0-9-_.]+")
|
@ -0,0 +1,78 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSecretValidate(t *testing.T) {
|
||||
tests := []struct {
|
||||
secret *Secret
|
||||
error error
|
||||
}{
|
||||
{
|
||||
secret: &Secret{Name: "password", Data: "correct-horse-battery-staple"},
|
||||
error: nil,
|
||||
},
|
||||
{
|
||||
secret: &Secret{Name: ".some_random-password", Data: "correct-horse-battery-staple"},
|
||||
error: nil,
|
||||
},
|
||||
{
|
||||
secret: &Secret{Name: "password", Data: ""},
|
||||
error: errSecretDataInvalid,
|
||||
},
|
||||
{
|
||||
secret: &Secret{Name: "", Data: "correct-horse-battery-staple"},
|
||||
error: errSecretNameInvalid,
|
||||
},
|
||||
{
|
||||
secret: &Secret{Name: "docker/password", Data: "correct-horse-battery-staple"},
|
||||
error: errSecretNameInvalid,
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
got, want := test.secret.Validate(), test.error
|
||||
if got != want {
|
||||
t.Errorf("Want error %v, got %v at index %d", want, got, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretSafeCopy(t *testing.T) {
|
||||
before := Secret{
|
||||
ID: 1,
|
||||
RepoID: 2,
|
||||
Name: "docker_password",
|
||||
Namespace: "octocat",
|
||||
Type: "",
|
||||
Data: "correct-horse-battery-staple",
|
||||
PullRequest: true,
|
||||
PullRequestPush: true,
|
||||
}
|
||||
after := before.Copy()
|
||||
if got, want := after.ID, before.ID; got != want {
|
||||
t.Errorf("Want secret ID %d, got %d", want, got)
|
||||
}
|
||||
if got, want := after.RepoID, before.RepoID; got != want {
|
||||
t.Errorf("Want secret RepoID %d, got %d", want, got)
|
||||
}
|
||||
if got, want := after.Name, before.Name; got != want {
|
||||
t.Errorf("Want secret Name %s, got %s", want, got)
|
||||
}
|
||||
if got, want := after.Namespace, before.Namespace; got != want {
|
||||
t.Errorf("Want secret Namespace %s, got %s", want, got)
|
||||
}
|
||||
if got, want := after.PullRequest, before.PullRequest; got != want {
|
||||
t.Errorf("Want secret PullRequest %v, got %v", want, got)
|
||||
}
|
||||
if got, want := after.PullRequestPush, before.PullRequestPush; got != want {
|
||||
t.Errorf("Want secret PullRequest %v, got %v", want, got)
|
||||
}
|
||||
if after.Data != "" {
|
||||
t.Errorf("Expect secret is empty after copy")
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Session provides session management for
|
||||
// authenticated users.
|
||||
type Session interface {
|
||||
// Create creates a new user session and writes the
|
||||
// session to the http.Response.
|
||||
Create(http.ResponseWriter, *User) error
|
||||
|
||||
// Delete deletes the user session from the http.Response.
|
||||
Delete(http.ResponseWriter) error
|
||||
|
||||
// Get returns the session from the http.Request. If no
|
||||
// session exists a nil user is returned. Returning an
|
||||
// error is optional, for debugging purposes only.
|
||||
Get(*http.Request) (*User, error)
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// Stage represents a stage of build execution.
|
||||
Stage struct {
|
||||
ID int64 `json:"id"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
BuildID int64 `json:"build_id"`
|
||||
Number int `json:"number"`
|
||||
Name string `json:"name"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrIgnore bool `json:"errignore"`
|
||||
ExitCode int `json:"exit_code"`
|
||||
Machine string `json:"machine,omitempty"`
|
||||
OS string `json:"os"`
|
||||
Arch string `json:"arch"`
|
||||
Variant string `json:"variant,omitempty"`
|
||||
Kernel string `json:"kernel,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
LimitRepo int `json:"throttle,omitempty"`
|
||||
Started int64 `json:"started"`
|
||||
Stopped int64 `json:"stopped"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
Version int64 `json:"version"`
|
||||
OnSuccess bool `json:"on_success"`
|
||||
OnFailure bool `json:"on_failure"`
|
||||
DependsOn []string `json:"depends_on,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Steps []*Step `json:"steps,omitempty"`
|
||||
}
|
||||
|
||||
// StageStore persists build stage information to storage.
|
||||
StageStore interface {
|
||||
// List returns a build stage list from the datastore.
|
||||
List(context.Context, int64) ([]*Stage, error)
|
||||
|
||||
// List returns a build stage list from the datastore
|
||||
// where the stage is incomplete (pending or running).
|
||||
ListIncomplete(ctx context.Context) ([]*Stage, error)
|
||||
|
||||
// ListSteps returns a build stage list from the datastore,
|
||||
// with the individual steps included.
|
||||
ListSteps(context.Context, int64) ([]*Stage, error)
|
||||
|
||||
// ListState returns a build stage list from the database
|
||||
// across all repositories.
|
||||
ListState(context.Context, string) ([]*Stage, error)
|
||||
|
||||
// Find returns a build stage from the datastore by ID.
|
||||
Find(context.Context, int64) (*Stage, error)
|
||||
|
||||
// FindNumber returns a stage from the datastore by number.
|
||||
FindNumber(context.Context, int64, int) (*Stage, error)
|
||||
|
||||
// Create persists a new stage to the datastore.
|
||||
Create(context.Context, *Stage) error
|
||||
|
||||
// Update persists an updated stage to the datastore.
|
||||
Update(context.Context, *Stage) error
|
||||
}
|
||||
)
|
||||
|
||||
// IsDone returns true if the step has a completed state.
|
||||
func (s *Stage) IsDone() bool {
|
||||
switch s.Status {
|
||||
case StatusWaiting,
|
||||
StatusPending,
|
||||
StatusRunning,
|
||||
StatusBlocked:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// IsFailed returns true if the step has failed
|
||||
func (s *Stage) IsFailed() bool {
|
||||
switch s.Status {
|
||||
case StatusFailing,
|
||||
StatusKilled,
|
||||
StatusError:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
||||
|
||||
import "testing"
|
||||
|
||||
var statusDone = []string{
|
||||
StatusDeclined,
|
||||
StatusError,
|
||||
StatusFailing,
|
||||
StatusKilled,
|
||||
StatusSkipped,
|
||||
StatusPassing,
|
||||
}
|
||||
|
||||
var statusNotDone = []string{
|
||||
StatusWaiting,
|
||||
StatusPending,
|
||||
StatusRunning,
|
||||
StatusBlocked,
|
||||
}
|
||||
|
||||
var statusFailed = []string{
|
||||
StatusError,
|
||||
StatusFailing,
|
||||
StatusKilled,
|
||||
}
|
||||
|
||||
var statusNotFailed = []string{
|
||||
StatusDeclined,
|
||||
StatusSkipped,
|
||||
StatusPassing,
|
||||
StatusWaiting,
|
||||
StatusPending,
|
||||
StatusRunning,
|
||||
StatusBlocked,
|
||||
}
|
||||
|
||||
func TestStageIsDone(t *testing.T) {
|
||||
for _, status := range statusDone {
|
||||
v := Stage{Status: status}
|
||||
if v.IsDone() == false {
|
||||
t.Errorf("Expect status %s is done", status)
|
||||
}
|
||||
}
|
||||
|
||||
for _, status := range statusNotDone {
|
||||
v := Stage{Status: status}
|
||||
if v.IsDone() == true {
|
||||
t.Errorf("Expect status %s is not done", status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStageIsFailed(t *testing.T) {
|
||||
for _, status := range statusFailed {
|
||||
v := Stage{Status: status}
|
||||
if v.IsFailed() == false {
|
||||
t.Errorf("Expect status %s is failed", status)
|
||||
}
|
||||
}
|
||||
|
||||
for _, status := range statusNotFailed {
|
||||
v := Stage{Status: status}
|
||||
if v.IsFailed() == true {
|
||||
t.Errorf("Expect status %s is not failed", status)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Status types.
|
||||
const (
|
||||
StatusSkipped = "skipped"
|
||||
StatusBlocked = "blocked"
|
||||
StatusDeclined = "declined"
|
||||
StatusWaiting = "waiting_on_dependencies"
|
||||
StatusPending = "pending"
|
||||
StatusRunning = "running"
|
||||
StatusPassing = "success"
|
||||
StatusFailing = "failure"
|
||||
StatusKilled = "killed"
|
||||
StatusError = "error"
|
||||
)
|
||||
|
||||
type (
|
||||
// Status represents a commit status.
|
||||
Status struct {
|
||||
State string
|
||||
Label string
|
||||
Desc string
|
||||
Target string
|
||||
}
|
||||
|
||||
// StatusInput provides the necessary metadata to
|
||||
// set the commit or deployment status.
|
||||
StatusInput struct {
|
||||
Repo *Repository
|
||||
Build *Build
|
||||
}
|
||||
|
||||
// StatusService sends the commit status to an external
|
||||
// source code management service (e.g. GitHub).
|
||||
StatusService interface {
|
||||
Send(ctx context.Context, user *User, req *StatusInput) error
|
||||
}
|
||||
)
|
@ -0,0 +1,69 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
type (
|
||||
// Step represents an individual step in the stage.
|
||||
Step struct {
|
||||
ID int64 `json:"id"`
|
||||
StageID int64 `json:"step_id"` // this is a typo, fixing it has far reaching ramifications. It should only be attempted in a major version change
|
||||
Number int `json:"number"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrIgnore bool `json:"errignore,omitempty"`
|
||||
ExitCode int `json:"exit_code"`
|
||||
Started int64 `json:"started,omitempty"`
|
||||
Stopped int64 `json:"stopped,omitempty"`
|
||||
Version int64 `json:"version"`
|
||||
DependsOn []string `json:"depends_on,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Detached bool `json:"detached,omitempty"`
|
||||
Schema string `json:"schema,omitempty"`
|
||||
}
|
||||
|
||||
// StepStore persists build step information to storage.
|
||||
StepStore interface {
|
||||
// List returns a build stage list from the datastore.
|
||||
List(context.Context, int64) ([]*Step, error)
|
||||
|
||||
// Find returns a build stage from the datastore by ID.
|
||||
Find(context.Context, int64) (*Step, error)
|
||||
|
||||
// FindNumber returns a stage from the datastore by number.
|
||||
FindNumber(context.Context, int64, int) (*Step, error)
|
||||
|
||||
// Create persists a new stage to the datastore.
|
||||
Create(context.Context, *Step) error
|
||||
|
||||
// Update persists an updated stage to the datastore.
|
||||
Update(context.Context, *Step) error
|
||||
}
|
||||
)
|
||||
|
||||
// IsDone returns true if the step has a completed state.
|
||||
func (s *Step) IsDone() bool {
|
||||
switch s.Status {
|
||||
case StatusWaiting,
|
||||
StatusPending,
|
||||
StatusRunning,
|
||||
StatusBlocked:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStepIsDone(t *testing.T) {
|
||||
for _, status := range statusDone {
|
||||
v := Step{Status: status}
|
||||
if v.IsDone() == false {
|
||||
t.Errorf("Expect status %s is done", status)
|
||||
}
|
||||
}
|
||||
|
||||
for _, status := range statusNotDone {
|
||||
v := Step{Status: status}
|
||||
if v.IsDone() == true {
|
||||
t.Errorf("Expect status %s is not done", status)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Syncer synchronizes the account repository list.
|
||||
type Syncer interface {
|
||||
Sync(context.Context, *User) (*Batch, error)
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
// System stores system information.
|
||||
type System struct {
|
||||
Proto string `json:"proto,omitempty"`
|
||||
Host string `json:"host,omitempty"`
|
||||
Link string `json:"link,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/drone/drone/handler/api/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
errTemplateNameInvalid = errors.New("No Template Name Provided")
|
||||
errTemplateDataInvalid = errors.New("No Template Data Provided")
|
||||
)
|
||||
|
||||
type (
|
||||
TemplateArgs struct {
|
||||
Kind string
|
||||
Load string
|
||||
Data map[string]interface{}
|
||||
}
|
||||
|
||||
Template struct {
|
||||
Id int64 `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Data string `json:"data,omitempty"`
|
||||
Created int64 `json:"created,omitempty"`
|
||||
Updated int64 `json:"updated,omitempty"`
|
||||
}
|
||||
|
||||
// TemplateStore manages repository templates.
|
||||
TemplateStore interface {
|
||||
// List returns template list at org level
|
||||
List(ctx context.Context, namespace string) ([]*Template, error)
|
||||
|
||||
// ListAll returns templates list from the datastore.
|
||||
ListAll(ctx context.Context) ([]*Template, error)
|
||||
|
||||
// Find returns a template from the datastore.
|
||||
Find(ctx context.Context, id int64) (*Template, error)
|
||||
|
||||
// FindName returns a template from the data store
|
||||
FindName(ctx context.Context, name string, namespace string) (*Template, error)
|
||||
|
||||
// Create persists a new template to the datastore.
|
||||
Create(ctx context.Context, template *Template) error
|
||||
|
||||
// Update persists an updated template to the datastore.
|
||||
Update(ctx context.Context, template *Template) error
|
||||
|
||||
// Delete deletes a template from the datastore.
|
||||
Delete(ctx context.Context, template *Template) error
|
||||
}
|
||||
)
|
||||
|
||||
// Validate validates the required fields and formats.
|
||||
func (s *Template) Validate() error {
|
||||
switch {
|
||||
case len(s.Name) == 0:
|
||||
return errTemplateNameInvalid
|
||||
case len(s.Data) == 0:
|
||||
return errTemplateDataInvalid
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Transferer handles transferring repository ownership from one
|
||||
// user to another user account.
|
||||
type Transferer interface {
|
||||
Transfer(ctx context.Context, user *User) error
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import "context"
|
||||
|
||||
// Trigger types
|
||||
const (
|
||||
TriggerHook = "@hook"
|
||||
TriggerCron = "@cron"
|
||||
)
|
||||
|
||||
// Triggerer is responsible for triggering a Build from an
|
||||
// incoming drone. If a build is skipped a nil value is
|
||||
// returned.
|
||||
type Triggerer interface {
|
||||
Trigger(context.Context, *Repository, *Hook) (*Build, error)
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
@ -0,0 +1,115 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
var (
|
||||
errUsernameLen = errors.New("Invalid username length")
|
||||
errUsernameChar = errors.New("Invalid character in username")
|
||||
)
|
||||
|
||||
type (
|
||||
// User represents a user of the system.
|
||||
User struct {
|
||||
ID int64 `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Email string `json:"email"`
|
||||
Machine bool `json:"machine"`
|
||||
Admin bool `json:"admin"`
|
||||
Active bool `json:"active"`
|
||||
Avatar string `json:"avatar"`
|
||||
Syncing bool `json:"syncing"`
|
||||
Synced int64 `json:"synced"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
LastLogin int64 `json:"last_login"`
|
||||
Token string `json:"-"`
|
||||
Refresh string `json:"-"`
|
||||
Expiry int64 `json:"-"`
|
||||
Hash string `json:"-"`
|
||||
}
|
||||
|
||||
// UserParams defines user query parameters.
|
||||
UserParams struct {
|
||||
// Sort instructs the system to sort by Login if true,
|
||||
// else sort by primary key.
|
||||
Sort bool
|
||||
|
||||
Page int64
|
||||
Size int64
|
||||
}
|
||||
|
||||
// UserStore defines operations for working with users.
|
||||
UserStore interface {
|
||||
// Find returns a user from the datastore.
|
||||
Find(context.Context, int64) (*User, error)
|
||||
|
||||
// FindLogin returns a user from the datastore by username.
|
||||
FindLogin(context.Context, string) (*User, error)
|
||||
|
||||
// FindToken returns a user from the datastore by token.
|
||||
FindToken(context.Context, string) (*User, error)
|
||||
|
||||
// List returns a list of users from the datastore.
|
||||
List(context.Context) ([]*User, error)
|
||||
|
||||
// ListRange returns a range of users from the datastore.
|
||||
ListRange(context.Context, UserParams) ([]*User, error)
|
||||
|
||||
// Create persists a new user to the datastore.
|
||||
Create(context.Context, *User) error
|
||||
|
||||
// Update persists an updated user to the datastore.
|
||||
Update(context.Context, *User) error
|
||||
|
||||
// Delete deletes a user from the datastore.
|
||||
Delete(context.Context, *User) error
|
||||
|
||||
// Count returns a count of human and machine users.
|
||||
Count(context.Context) (int64, error)
|
||||
|
||||
// CountHuman returns a count of human users.
|
||||
CountHuman(context.Context) (int64, error)
|
||||
}
|
||||
|
||||
// UserService provides access to user account
|
||||
// resources in the remote system (e.g. GitHub).
|
||||
UserService interface {
|
||||
// Find returns the authenticated user.
|
||||
Find(ctx context.Context, access, refresh string) (*User, error)
|
||||
|
||||
// FindLogin returns a user by username.
|
||||
FindLogin(ctx context.Context, user *User, login string) (*User, error)
|
||||
}
|
||||
)
|
||||
|
||||
// Validate validates the user and returns an error if the
|
||||
// validation fails.
|
||||
func (u *User) Validate() error {
|
||||
switch {
|
||||
case !govalidator.IsByteLength(u.Login, 1, 50):
|
||||
return errUsernameLen
|
||||
case !govalidator.Matches(u.Login, "^[.a-zA-Z0-9_-]+$"):
|
||||
return errUsernameChar
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
// +build !oss
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateUser(t *testing.T) {
|
||||
tests := []struct {
|
||||
user *User
|
||||
err error
|
||||
}{
|
||||
{
|
||||
user: &User{Login: ""},
|
||||
err: errUsernameLen,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "©"}, // non ascii character
|
||||
err: errUsernameChar,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "소주"}, // non ascii character
|
||||
err: errUsernameChar,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "foo/bar"},
|
||||
err: errUsernameChar,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "this-is-a-really-really-really-really-long-username"},
|
||||
err: errUsernameLen,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "octocat"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "octocat.with.dot"},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
user: &User{Login: "OctO-Cat_01"},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
got := test.user.Validate()
|
||||
if got == nil && test.err == nil {
|
||||
continue
|
||||
}
|
||||
if got == nil && test.err != nil {
|
||||
t.Errorf("Expected error: %q at index %d", test.err, i)
|
||||
continue
|
||||
}
|
||||
if got != nil && test.err == nil {
|
||||
t.Errorf("Unexpected error: %q at index %d", got, i)
|
||||
continue
|
||||
}
|
||||
if got, want := got.Error(), test.err.Error(); got != want {
|
||||
t.Errorf("Want error %q, got %q at index %d", want, got, i)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrValidatorSkip is returned if the pipeline
|
||||
// validation fails, but the pipeline should be skipped
|
||||
// and silently ignored instead of erroring.
|
||||
ErrValidatorSkip = errors.New("validation failed: skip pipeline")
|
||||
|
||||
// ErrValidatorBlock is returned if the pipeline
|
||||
// validation fails, but the pipeline should be blocked
|
||||
// pending manual approval instead of erroring.
|
||||
ErrValidatorBlock = errors.New("validation failed: block pipeline")
|
||||
)
|
||||
|
||||
type (
|
||||
// ValidateArgs represents a request to the pipeline
|
||||
// validation service.
|
||||
ValidateArgs struct {
|
||||
User *User `json:"-"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
Config *Config `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
// ValidateService validates the yaml configuration
|
||||
// and returns an error if the yaml is deemed invalid.
|
||||
ValidateService interface {
|
||||
Validate(context.Context, *ValidateArgs) error
|
||||
}
|
||||
)
|
@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Webhook event types.
|
||||
const (
|
||||
WebhookEventBuild = "build"
|
||||
WebhookEventRepo = "repo"
|
||||
WebhookEventUser = "user"
|
||||
)
|
||||
|
||||
// Webhook action types.
|
||||
const (
|
||||
WebhookActionCreated = "created"
|
||||
WebhookActionUpdated = "updated"
|
||||
WebhookActionDeleted = "deleted"
|
||||
WebhookActionEnabled = "enabled"
|
||||
WebhookActionDisabled = "disabled"
|
||||
)
|
||||
|
||||
type (
|
||||
// Webhook defines an integration endpoint.
|
||||
Webhook struct {
|
||||
Endpoint string `json:"endpoint,omitempty"`
|
||||
Signer string `json:"-"`
|
||||
SkipVerify bool `json:"skip_verify,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookData provides the webhook data.
|
||||
WebhookData struct {
|
||||
Event string `json:"event"`
|
||||
Action string `json:"action"`
|
||||
User *User `json:"user,omitempty"`
|
||||
Repo *Repository `json:"repo,omitempty"`
|
||||
Build *Build `json:"build,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookSender sends the webhook payload.
|
||||
WebhookSender interface {
|
||||
// Send sends the webhook to the global endpoint.
|
||||
Send(context.Context, *WebhookData) error
|
||||
}
|
||||
)
|
@ -0,0 +1,19 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
ENV GODEBUG netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/amd64
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ADD release/linux/amd64/drone-agent /bin/
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ENTRYPOINT ["/bin/drone-agent"]
|
@ -0,0 +1,12 @@
|
||||
FROM drone/ca-certs
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/arm
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ENV DRONE_RUNNER_VARIANT=v7
|
||||
ADD release/linux/arm/drone-agent /bin/
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ENTRYPOINT ["/bin/drone-agent"]
|
@ -0,0 +1,12 @@
|
||||
FROM drone/ca-certs
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm64
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/arm64
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ENV DRONE_RUNNER_VARIANT=v8
|
||||
ADD release/linux/arm64/drone-agent /bin/
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ENTRYPOINT ["/bin/drone-agent"]
|
@ -0,0 +1,14 @@
|
||||
FROM mcr.microsoft.com/windows/nanoserver:1803
|
||||
USER ContainerAdministrator
|
||||
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=windows
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=windows/amd64
|
||||
ENV DRONE_RUNNER_KERNEL=1803
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ADD release/windows/amd64/drone-agent.exe C:/drone-agent.exe
|
||||
ENTRYPOINT [ "C:\\drone-agent.exe" ]
|
@ -0,0 +1,14 @@
|
||||
FROM mcr.microsoft.com/windows/nanoserver:1809
|
||||
USER ContainerAdministrator
|
||||
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=windows
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=windows/amd64
|
||||
ENV DRONE_RUNNER_KERNEL=1809
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ADD release/windows/amd64/drone-agent.exe C:/drone-agent.exe
|
||||
ENTRYPOINT [ "C:\\drone-agent.exe" ]
|
@ -0,0 +1,14 @@
|
||||
FROM mcr.microsoft.com/windows/nanoserver:1903
|
||||
USER ContainerAdministrator
|
||||
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=windows
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=windows/amd64
|
||||
ENV DRONE_RUNNER_KERNEL=1903
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
|
||||
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"
|
||||
|
||||
ADD release/windows/amd64/drone-agent.exe C:/drone-agent.exe
|
||||
ENTRYPOINT [ "C:\\drone-agent.exe" ]
|
@ -0,0 +1,15 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
ENV GODEBUG netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/amd64
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ADD release/linux/amd64/drone-controller /bin/
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ENTRYPOINT ["/bin/drone-controller"]
|
@ -0,0 +1,16 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/arm
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ENV DRONE_RUNNER_VARIANT=v7
|
||||
ADD release/linux/arm/drone-controller /bin/
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ENTRYPOINT ["/bin/drone-controller"]
|
@ -0,0 +1,16 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm64
|
||||
ENV DRONE_RUNNER_PLATFORM=linux/arm64
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
ENV DRONE_RUNNER_VARIANT=v8
|
||||
ADD release/linux/arm64/drone-controller /bin/
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ENTRYPOINT ["/bin/drone-controller"]
|
@ -0,0 +1,12 @@
|
||||
FROM mcr.microsoft.com/windows/nanoserver:1803
|
||||
USER ContainerAdministrator
|
||||
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=windows
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=windows/amd64
|
||||
ENV DRONE_RUNNER_KERNEL=1803
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
|
||||
ADD release/windows/1803/amd64/drone-controller.exe C:/drone-controller.exe
|
||||
ENTRYPOINT [ "C:\\drone-controller.exe" ]
|
@ -0,0 +1,12 @@
|
||||
FROM mcr.microsoft.com/windows/nanoserver:1809
|
||||
USER ContainerAdministrator
|
||||
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=windows
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_RUNNER_PLATFORM=windows/amd64
|
||||
ENV DRONE_RUNNER_KERNEL=1809
|
||||
ENV DRONE_RUNNER_CAPACITY=1
|
||||
|
||||
ADD release/windows/1809/amd64/drone-controller.exe C:/drone-controller.exe
|
||||
ENTRYPOINT [ "C:\\drone-controller.exe" ]
|
@ -0,0 +1,27 @@
|
||||
# docker build --rm -f docker/Dockerfile -t drone/drone .
|
||||
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
ENV GODEBUG netdns=go
|
||||
ENV XDG_CACHE_HOME /data
|
||||
ENV DRONE_DATABASE_DRIVER sqlite3
|
||||
ENV DRONE_DATABASE_DATASOURCE /data/database.sqlite
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
ENV DRONE_SERVER_PORT=:80
|
||||
ENV DRONE_SERVER_HOST=localhost
|
||||
ENV DRONE_DATADOG_ENABLED=true
|
||||
ENV DRONE_DATADOG_ENDPOINT=https://stats.drone.ci/api/v1/series
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ADD release/linux/amd64/drone-server /bin/
|
||||
ENTRYPOINT ["/bin/drone-server"]
|
@ -0,0 +1,27 @@
|
||||
# docker build --rm -f docker/Dockerfile -t drone/drone .
|
||||
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
ENV GODEBUG netdns=go
|
||||
ENV XDG_CACHE_HOME /data
|
||||
ENV DRONE_DATABASE_DRIVER sqlite3
|
||||
ENV DRONE_DATABASE_DATASOURCE /data/database.sqlite
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm
|
||||
ENV DRONE_SERVER_PORT=:80
|
||||
ENV DRONE_SERVER_HOST=localhost
|
||||
ENV DRONE_DATADOG_ENABLED=true
|
||||
ENV DRONE_DATADOG_ENDPOINT=https://stats.drone.ci/api/v1/series
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ADD release/linux/arm/drone-server /bin/
|
||||
ENTRYPOINT ["/bin/drone-server"]
|
@ -0,0 +1,27 @@
|
||||
# docker build --rm -f docker/Dockerfile -t drone/drone .
|
||||
|
||||
FROM alpine:3.11 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
|
||||
ENV GODEBUG netdns=go
|
||||
ENV XDG_CACHE_HOME /data
|
||||
ENV DRONE_DATABASE_DRIVER sqlite3
|
||||
ENV DRONE_DATABASE_DATASOURCE /data/database.sqlite
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm64
|
||||
ENV DRONE_SERVER_PORT=:80
|
||||
ENV DRONE_SERVER_HOST=localhost
|
||||
ENV DRONE_DATADOG_ENABLED=true
|
||||
ENV DRONE_DATADOG_ENDPOINT=https://stats.drone.ci/api/v1/series
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
||||
ADD release/linux/arm64/drone-server /bin/
|
||||
ENTRYPOINT ["/bin/drone-server"]
|
@ -0,0 +1,57 @@
|
||||
# Local development
|
||||
|
||||
This directory contains Docker compose files used by the core development team for local development and testing purposes only. These are not part of the core distribution, and are not intended for use outside of the core development team. We are not currently accepting changes or additions to these files.
|
||||
|
||||
## Running a Drone deployment locally using Github
|
||||
|
||||
At the end of this guide you will have a drone server and a drone runner that is hooked up to your Github account. This will allow you to trigger builds on your Github repositories.
|
||||
|
||||
### (prerequisite) Setup a Github oauth application
|
||||
|
||||
Create an oauth application here <https://github.com/settings/developers>
|
||||
|
||||
The most important entry is setting the `Authorization callback URL` you can set this to `http://localhost:8080/login`
|
||||
|
||||
You will also need to create a client secret for the application.
|
||||
|
||||
Now you have the `DRONE_GITHUB_CLIENT_ID` and `DRONE_GITHUB_CLIENT_SECRET`
|
||||
|
||||
### (prerequisite) Setup Ngrok
|
||||
|
||||
Ngrok allows us to send the webhooks from Github to our local Drone setup.
|
||||
|
||||
Follow the guide here <https://dashboard.ngrok.com/get-started/setup>
|
||||
|
||||
### Running Drone
|
||||
|
||||
+ Move into the `drone/docker/compose/drone-github` folder.
|
||||
|
||||
+ Run Ngrok against port `8080` it will run in the foreground.
|
||||
|
||||
``` bash
|
||||
./ngrok http 8080
|
||||
```
|
||||
|
||||
Take note of the forwarding hostname this is your `DRONE_SERVER_PROXY_HOST` EG
|
||||
|
||||
``` bash
|
||||
Forwarding http://c834c33asdde.ngrok.io -> http://localhost:8080
|
||||
```
|
||||
|
||||
+ You will want to edit the Docker compose file `docker-compose.yml` updating in the following entries.
|
||||
|
||||
``` bash
|
||||
DRONE_SERVER_PROXY_HOST=${DRONE_SERVER_PROXY_HOST} # taken from Ngrok
|
||||
DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID} # taken from your Github oauth application
|
||||
DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET} # taken from your Github oauth application
|
||||
```
|
||||
|
||||
NB for `DRONE_SERVER_PROXY_HOST` do not include http/https.
|
||||
|
||||
+ Run docker compose
|
||||
|
||||
``` bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
Now you can go access the Drone ui at <http://localhost:8080>
|
@ -0,0 +1,40 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
drone:
|
||||
image: drone/drone:latest
|
||||
ports:
|
||||
- "9000:80"
|
||||
environment:
|
||||
- DRONE_SERVER_HOST=localhost:9000
|
||||
- DRONE_SERVER_PROTO=http
|
||||
- DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
|
||||
- DRONE_COOKIE_SECRET=e8206356c843d81e05ab6735e7ebf075
|
||||
- DRONE_COOKIE_TIMEOUT=720h
|
||||
- DRONE_GITEA_CLIENT_ID=${DRONE_GITEA_CLIENT_ID}
|
||||
- DRONE_GITEA_CLIENT_SECRET=${DRONE_GITEA_CLIENT_SECRET}
|
||||
- DRONE_GITEA_SERVER=http://gitea:3000
|
||||
- DRONE_LOGS_DEBUG=true
|
||||
- DRONE_CRON_DISABLED=true
|
||||
volumes:
|
||||
- ./data:/data
|
||||
networks:
|
||||
- default
|
||||
- gitea
|
||||
runner:
|
||||
image: drone/drone-runner-docker:latest
|
||||
environment:
|
||||
- DRONE_RPC_HOST=drone
|
||||
- DRONE_RPC_PROTO=http
|
||||
- DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- default
|
||||
- gitea
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: false
|
||||
gitea:
|
||||
external:
|
||||
name: gitea
|
@ -0,0 +1,29 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
drone:
|
||||
image: drone/drone:latest
|
||||
ports:
|
||||
- "8080:80"
|
||||
environment:
|
||||
- DRONE_SERVER_HOST=localhost:8080
|
||||
- DRONE_SERVER_PROTO=http
|
||||
- DRONE_SERVER_PROXY_HOST=${DRONE_SERVER_PROXY_HOST}
|
||||
- DRONE_SERVER_PROXY_PROTO=https
|
||||
- DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
|
||||
- DRONE_COOKIE_SECRET=e8206356c843d81e05ab6735e7ebf075
|
||||
- DRONE_COOKIE_TIMEOUT=720h
|
||||
- DRONE_GITHUB_CLIENT_ID=${DRONE_GITHUB_CLIENT_ID}
|
||||
- DRONE_GITHUB_CLIENT_SECRET=${DRONE_GITHUB_CLIENT_SECRET}
|
||||
- DRONE_LOGS_DEBUG=true
|
||||
- DRONE_CRON_DISABLED=true
|
||||
volumes:
|
||||
- ./data:/data
|
||||
runner:
|
||||
image: drone/drone-runner-docker:latest
|
||||
environment:
|
||||
- DRONE_RPC_HOST=drone
|
||||
- DRONE_RPC_PROTO=http
|
||||
- DRONE_RPC_SECRET=bea26a2221fd8090ea38720fc445eca6
|
||||
- DRONE_TMATE_ENABLED=true
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
@ -0,0 +1,21 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- ROOT_URL=http://gitea:3000
|
||||
networks:
|
||||
- gitea
|
||||
volumes:
|
||||
- ./data:/data
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "3022:22"
|
||||
|
||||
networks:
|
||||
gitea:
|
||||
name: gitea
|
||||
external: false
|
@ -0,0 +1,43 @@
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
||||
platform:
|
||||
architecture: arm
|
||||
os: linux
|
||||
variant: v7
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1803-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: windows
|
||||
variant: 1803
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: windows
|
||||
variant: 1809
|
||||
-
|
||||
image: drone/agent:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1903-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: windows
|
||||
variant: 1903
|
@ -0,0 +1,37 @@
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
||||
-
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
|
||||
platform:
|
||||
architecture: arm
|
||||
os: linux
|
||||
variant: v7
|
||||
-
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1803-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: windows
|
||||
variant: 1803
|
||||
-
|
||||
image: drone/controller:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}windows-1809-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: windows
|
||||
variant: 1809
|
@ -0,0 +1,19 @@
|
||||
image: drone/drone:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||
{{#if build.tags}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
image: drone/drone:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
||||
platform:
|
||||
architecture: amd64
|
||||
os: linux
|
||||
-
|
||||
image: drone/drone:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
|
||||
platform:
|
||||
architecture: arm64
|
||||
os: linux
|
||||
variant: v8
|
@ -0,0 +1,63 @@
|
||||
module github.com/drone/drone
|
||||
|
||||
replace github.com/docker/docker => github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
|
||||
|
||||
require (
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e
|
||||
github.com/Azure/azure-storage-blob-go v0.7.0
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.3 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20180315120708-ccb8e960c48f
|
||||
github.com/aws/aws-sdk-go v1.37.3
|
||||
github.com/codegangsta/negroni v1.0.0 // indirect
|
||||
github.com/coreos/go-semver v0.2.0
|
||||
github.com/dchest/authcookie v0.0.0-20120917135355-fbdef6e99866
|
||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
|
||||
github.com/drone/drone-go v1.7.2-0.20220308165842-f9e4fe31c2af
|
||||
github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d
|
||||
github.com/drone/drone-ui v2.11.5+incompatible
|
||||
github.com/drone/drone-yaml v1.2.4-0.20220204000225-01fb17858c9b
|
||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629
|
||||
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056
|
||||
github.com/drone/go-license v1.0.2
|
||||
github.com/drone/go-login v1.1.0
|
||||
github.com/drone/go-scm v1.28.0
|
||||
github.com/drone/signal v1.0.0
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/go-chi/chi v3.3.3+incompatible
|
||||
github.com/go-chi/cors v1.0.0
|
||||
github.com/go-redis/redis/v8 v8.11.0
|
||||
github.com/go-redsync/redsync/v4 v4.3.0
|
||||
github.com/go-sql-driver/mysql v1.4.0
|
||||
github.com/golang/mock v1.3.1
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/go-jsonnet v0.17.0
|
||||
github.com/google/wire v0.2.1
|
||||
github.com/gosimple/slug v1.3.0
|
||||
github.com/h2non/gock v1.0.15
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4
|
||||
github.com/hashicorp/golang-lru v0.5.1
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/kelseyhightower/envconfig v1.3.0
|
||||
github.com/kr/pretty v0.2.0 // indirect
|
||||
github.com/lib/pq v1.1.0
|
||||
github.com/mattn/go-sqlite3 v1.9.0
|
||||
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2
|
||||
github.com/prometheus/client_golang v0.9.2
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967
|
||||
github.com/segmentio/ksuid v1.0.2
|
||||
github.com/sirupsen/logrus v1.6.0
|
||||
github.com/unrolled/secure v0.0.0-20181022170031-4b6b7cf51606
|
||||
go.starlark.net v0.0.0-20221020143700-22309ac47eac
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
)
|
||||
|
||||
replace github.com/h2non/gock => gopkg.in/h2non/gock.v1 v1.0.14
|
||||
|
||||
go 1.13
|
@ -0,0 +1,414 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
docker.io/go-docker v1.0.0/go.mod h1:7tiAn5a0LFmjbPDbyTPOaTTOuG1ZRNXdPA6RvKY+fpY=
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e h1:rl2Aq4ZODqTDkeSqQBy+fzpZPamacO1Srp8zq7jf2Sc=
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e/go.mod h1:Xa6lInWHNQnuWoF0YPSsx+INFA9qk7/7pTjwb3PInkY=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo=
|
||||
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
|
||||
github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck=
|
||||
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.3 h1:O1AGG9Xig71FxdX9HO5pGNyZ7TbSyHaVg+5eJO/jSGw=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180315120708-ccb8e960c48f h1:y2hSFdXeA1y5z5f0vfNO0Dg5qVY036qzlz3Pds0B92o=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180315120708-ccb8e960c48f/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.37.3 h1:1f0groABc4AuapskpHf6EBRaG2tqw0Sx3ebCMwfp1Ys=
|
||||
github.com/aws/aws-sdk-go v1.37.3/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ=
|
||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||
github.com/buildkite/yaml v2.1.0+incompatible h1:xirI+ql5GzfikVNDmt+yeiXpf/v1Gt03qXTtT5WXdr8=
|
||||
github.com/buildkite/yaml v2.1.0+incompatible/go.mod h1:UoU8vbcwu1+vjZq01+KrpSeLBgQQIjL/H7Y6KwikUrI=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
|
||||
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
||||
github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=
|
||||
github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dchest/authcookie v0.0.0-20120917135355-fbdef6e99866 h1:98WJ4YCdjmB7uyrdT3P4A2Oa1hiRPKoa/0zInG6UnfQ=
|
||||
github.com/dchest/authcookie v0.0.0-20120917135355-fbdef6e99866/go.mod h1:x7AK2h2QzaXVEFi1tbMYMDuvHcCEr1QdMDrg3hkW24Q=
|
||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 h1:74lLNRzvsdIlkTgfDSMuaPjBr4cf6k7pwQQANm/yLKU=
|
||||
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/docker/distribution v0.0.0-20170726174610-edc3ab29cdff/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible h1:hx8H7MbcmXUXAmphQuA/XB7CfSzX4DRrNuHFvfK9aIQ=
|
||||
github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible/go.mod h1:3CPr2caMgTHxxIAZgEMd3uLYPDlRvPqCpyeRf6ncPcY=
|
||||
github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
|
||||
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/drone/drone-go v1.7.2-0.20220308165842-f9e4fe31c2af h1:I+xfWPZLMaskFvfFO5fEJ6tVI1Q9bWR9tuORZeaCTPo=
|
||||
github.com/drone/drone-go v1.7.2-0.20220308165842-f9e4fe31c2af/go.mod h1:fxCf9jAnXDZV1yDr0ckTuWd1intvcQwfJmTRpTZ1mXg=
|
||||
github.com/drone/drone-runtime v1.0.7-0.20190729202838-87c84080f4a1/go.mod h1:+osgwGADc/nyl40J0fdsf8Z09bgcBZXvXXnLOY48zYs=
|
||||
github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d h1:P5HI/Y9hARTZ3F3EKs0kYijhjXZWQRQHYn1neTi0pWM=
|
||||
github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d/go.mod h1:4/2QToW5+HGD0y1sTw7X35W1f7YINS14UfDY4isggT8=
|
||||
github.com/drone/drone-ui v2.11.5+incompatible h1:e+OmpCuxfCS1V8Szx+4OzCMXiM80ZJkV05/BuY8pVv8=
|
||||
github.com/drone/drone-ui v2.11.5+incompatible/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI=
|
||||
github.com/drone/drone-yaml v1.2.4-0.20220204000225-01fb17858c9b h1:NU8JZ2Py6dLa5kktIvcsQ5sokdDbvjL8GUOYEU53Wfk=
|
||||
github.com/drone/drone-yaml v1.2.4-0.20220204000225-01fb17858c9b/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10=
|
||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw=
|
||||
github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g=
|
||||
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 h1:SCJwMR0FMA0aKwAntCBh02YmtHEnU40zaDzeeCvIRug=
|
||||
github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E=
|
||||
github.com/drone/go-license v1.0.2 h1:7OwndfYk+Lp/cGHkxe4HUn/Ysrrw3WYH2pnd99yrkok=
|
||||
github.com/drone/go-license v1.0.2/go.mod h1:fGRHf+F1cEaw3YVYiJ6js3G3dVhcxyS617RnNRUMsms=
|
||||
github.com/drone/go-login v1.1.0 h1:anQFRh2Z5ketEJ/LvL6SJ6rIwDdfysGXK5bSXkFLInI=
|
||||
github.com/drone/go-login v1.1.0/go.mod h1:FLxy9vRzLbyBxoCJYxGbG9R0WGn6OyuvBmAtYNt43uw=
|
||||
github.com/drone/go-scm v1.28.0 h1:Y5SCf01Iw7/VO8hhjNgAX0eGIXZ225ctw7DlGQHh5g4=
|
||||
github.com/drone/go-scm v1.28.0/go.mod h1:DFIJJjhMj0TSXPz+0ni4nyZ9gtTtC40Vh/TGRugtyWw=
|
||||
github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI=
|
||||
github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-chi/chi v3.3.3+incompatible h1:KHkmBEMNkwKuK4FdQL7N2wOeB9jnIx7jR5wsuSBEFI8=
|
||||
github.com/go-chi/chi v3.3.3+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
||||
github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
|
||||
github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
|
||||
github.com/go-redis/redis/v8 v8.1.1/go.mod h1:ysgGY09J/QeDYbu3HikWEIPCwaeOkuNoTgKayTEaEOw=
|
||||
github.com/go-redis/redis/v8 v8.11.0 h1:O1Td0mQ8UFChQ3N9zFQqo6kTU2cJ+/it88gDB+zg0wo=
|
||||
github.com/go-redis/redis/v8 v8.11.0/go.mod h1:DLomh7y2e3ggQXQLd1YgmvIfecPJoFl7WU5SOQ/r06M=
|
||||
github.com/go-redsync/redsync/v4 v4.3.0 h1:5cNxbHJc/tr1KX04piPv8nylURyuT3nqjmodkW8JCjM=
|
||||
github.com/go-redsync/redsync/v4 v4.3.0/go.mod h1:QBOJAs1k8O6Eyrre4a++pxQgHe5eQ+HF56KuTVv+8Bs=
|
||||
github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506 h1:zDlw+wgyXdfkRuvFCdEDUiPLmZp2cvf/dWHazY0a5VM=
|
||||
github.com/gogo/protobuf v0.0.0-20170307180453-100ba4e88506/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
|
||||
github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-jsonnet v0.17.0 h1:/9NIEfhK1NQRKl3sP2536b2+x5HnZMdql7x3yK/l8JY=
|
||||
github.com/google/go-jsonnet v0.17.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/wire v0.2.1 h1:TYj4Z2qjqxa2ufb34UJqVeO9aznL+i0fLO6TqThKZ7Y=
|
||||
github.com/google/wire v0.2.1/go.mod h1:ptBl5bWD3nzmJHVNwYHV3v4wdtKzBMlU2YbtKQCG9GI=
|
||||
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gosimple/slug v1.3.0 h1:NKQyQMjKkgCpD/Vd+wKtFc7N60bJNCLDubKU/UDKMFI=
|
||||
github.com/gosimple/slug v1.3.0/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0=
|
||||
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+uGHxWtRt4C0Wjc6kJKo5XYx8xE=
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/kelseyhightower/envconfig v1.3.0 h1:IvRS4f2VcIQy6j4ORGIf9145T/AsUB+oY8LyvN8BXNM=
|
||||
github.com/kelseyhightower/envconfig v1.3.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4=
|
||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA=
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 h1:dnMxwus89s86tI8rcGVp2HwZzlz7c5o92VOy7dSckBQ=
|
||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4/go.mod h1:cojhOHk1gbMeklOyDP2oKKLftefXoJreOQGOrXk+Z38=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
|
||||
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
|
||||
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 h1:CXwSGu/LYmbjEab5aMCs5usQRVBGThelUKBNnoSOuso=
|
||||
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2/go.mod h1:L3UMQOThbttwfYRNFOWLLVXMhk5Lkio4GGOtw5UrxS0=
|
||||
github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c/go.mod h1:HUpKUBZnpzkdx0kD/+Yfuft+uD3zHGtXF/XJB14TUr4=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967 h1:x7xEyJDP7Hv3LVgvWhzioQqbC/KtuUhTigKlH/8ehhE=
|
||||
github.com/robfig/cron v0.0.0-20180505203441-b41be1df6967/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
||||
github.com/segmentio/ksuid v1.0.2 h1:9yBfKyw4ECGTdALaF09Snw3sLJmYIX6AbPJrAy6MrDc=
|
||||
github.com/segmentio/ksuid v1.0.2/go.mod h1:BXuJDr2byAiHuQaQtSKoXh1J0YmUDurywOXgB2w+OSU=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
||||
github.com/unrolled/secure v0.0.0-20181022170031-4b6b7cf51606 h1:dU9yXzNi9rl6Mou7+3npdfPyeFPb2+7BHs3zL47bhPY=
|
||||
github.com/unrolled/secure v0.0.0-20181022170031-4b6b7cf51606/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
|
||||
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d h1:3wDi6J5APMqaHBVPuVd7RmHD2gRTfqbdcVSpCNoUWtk=
|
||||
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d/go.mod h1:mb5taDqMnJiZNRQ3+02W2IFG+oEz1+dTuCXkp4jpkfo=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opentelemetry.io/otel v0.11.0/go.mod h1:G8UCk+KooF2HLkgo8RHX9epABH/aRGYET7gQOqBVdB0=
|
||||
go.starlark.net v0.0.0-20221020143700-22309ac47eac h1:gBO5Qfcw5V9404yzsu2FEIsxK/u2mBNTNogK0uIoVhk=
|
||||
go.starlark.net v0.0.0-20221020143700-22309ac47eac/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181005133103-4497e2df6f9e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181017214349-06f26fdaaa28/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/h2non/gock.v1 v1.0.14 h1:fTeu9fcUvSnLNacYvYI54h+1/XEteDyHvrVCZEEEYNM=
|
||||
gopkg.in/h2non/gock.v1 v1.0.14/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.0.0-20181130031204-d04500c8c3dd/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||
k8s.io/apimachinery v0.0.0-20181201231028-18a5ff3097b4/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
|
||||
k8s.io/client-go v9.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||
k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
@ -0,0 +1,59 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package acl
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/drone/handler/api/errors"
|
||||
"github.com/drone/drone/handler/api/render"
|
||||
"github.com/drone/drone/handler/api/request"
|
||||
"github.com/drone/drone/logger"
|
||||
)
|
||||
|
||||
// AuthorizeUser returns an http.Handler middleware that authorizes only
|
||||
// authenticated users to proceed to the next handler in the chain. Guest users
|
||||
// are rejected with a 401 unauthorized error.
|
||||
func AuthorizeUser(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, ok := request.UserFrom(r.Context())
|
||||
if !ok {
|
||||
render.Unauthorized(w, errors.ErrUnauthorized)
|
||||
logger.FromRequest(r).
|
||||
Debugln("api: authentication required")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// AuthorizeAdmin returns an http.Handler middleware that authorizes only
|
||||
// system administrators to proceed to the next handler in the chain.
|
||||
func AuthorizeAdmin(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
user, ok := request.UserFrom(r.Context())
|
||||
if !ok {
|
||||
render.Unauthorized(w, errors.ErrUnauthorized)
|
||||
logger.FromRequest(r).
|
||||
Debugln("api: authentication required")
|
||||
} else if !user.Admin {
|
||||
render.Forbidden(w, errors.ErrForbidden)
|
||||
logger.FromRequest(r).
|
||||
Debugln("api: administrative access required")
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package acl
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api/request"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func init() {
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
}
|
||||
|
||||
var (
|
||||
mockUser = &core.User{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
Admin: false,
|
||||
Active: true,
|
||||
}
|
||||
|
||||
mockUserAdmin = &core.User{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
Admin: true,
|
||||
Active: true,
|
||||
}
|
||||
|
||||
mockUserInactive = &core.User{
|
||||
ID: 1,
|
||||
Login: "octocat",
|
||||
Admin: false,
|
||||
Active: false,
|
||||
}
|
||||
|
||||
mockRepo = &core.Repository{
|
||||
ID: 1,
|
||||
UID: "42",
|
||||
Namespace: "octocat",
|
||||
Name: "hello-world",
|
||||
Slug: "octocat/hello-world",
|
||||
Counter: 42,
|
||||
Branch: "master",
|
||||
Private: true,
|
||||
Visibility: core.VisibilityPrivate,
|
||||
}
|
||||
)
|
||||
|
||||
func TestAuthorizeUser(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(r.Context(), mockUser),
|
||||
)
|
||||
|
||||
AuthorizeUser(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// use dummy status code to signal the next handler in
|
||||
// the middleware chain was properly invoked.
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
}),
|
||||
).ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizeUserErr(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
|
||||
AuthorizeUser(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
}),
|
||||
).ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizeAdmin(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(r.Context(), &core.User{Admin: true}),
|
||||
)
|
||||
|
||||
AuthorizeAdmin(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// use dummy status code to signal the next handler in
|
||||
// the middleware chain was properly invoked.
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
}),
|
||||
).ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizeAdminUnauthorized(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
|
||||
AuthorizeAdmin(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
}),
|
||||
).ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizeAdminForbidden(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(r.Context(), &core.User{Admin: false}),
|
||||
)
|
||||
|
||||
AuthorizeAdmin(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
}),
|
||||
).ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusForbidden; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
// Copyright 2019 Drone IO, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package acl
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api/errors"
|
||||
"github.com/drone/drone/handler/api/render"
|
||||
"github.com/drone/drone/handler/api/request"
|
||||
"github.com/drone/drone/logger"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// CheckReadAccess returns an http.Handler middleware that authorizes only
|
||||
// authenticated users with read repository access to proceed to the next
|
||||
// handler in the chain.
|
||||
func CheckReadAccess() func(http.Handler) http.Handler {
|
||||
return CheckAccess(true, false, false)
|
||||
}
|
||||
|
||||
// CheckWriteAccess returns an http.Handler middleware that authorizes only
|
||||
// authenticated users with write repository access to proceed to the next
|
||||
// handler in the chain.
|
||||
func CheckWriteAccess() func(http.Handler) http.Handler {
|
||||
return CheckAccess(true, true, false)
|
||||
}
|
||||
|
||||
// CheckAdminAccess returns an http.Handler middleware that authorizes only
|
||||
// authenticated users with admin repository access to proceed to the next
|
||||
// handler in the chain.
|
||||
func CheckAdminAccess() func(http.Handler) http.Handler {
|
||||
return CheckAccess(true, true, true)
|
||||
}
|
||||
|
||||
// CheckAccess returns an http.Handler middleware that authorizes only
|
||||
// authenticated users with the required read, write or admin access
|
||||
// permissions to the requested repository resource.
|
||||
func CheckAccess(read, write, admin bool) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
owner = chi.URLParam(r, "owner")
|
||||
name = chi.URLParam(r, "name")
|
||||
)
|
||||
log := logger.FromRequest(r).
|
||||
WithField("namespace", owner).
|
||||
WithField("name", name)
|
||||
|
||||
user, ok := request.UserFrom(ctx)
|
||||
switch {
|
||||
case ok == false && write == true:
|
||||
render.Unauthorized(w, errors.ErrUnauthorized)
|
||||
log.Debugln("api: authentication required for write access")
|
||||
return
|
||||
case ok == false && admin == true:
|
||||
render.Unauthorized(w, errors.ErrUnauthorized)
|
||||
log.Debugln("api: authentication required for admin access")
|
||||
return
|
||||
case ok == true && user.Admin == true:
|
||||
log.Debugln("api: root access granted")
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
repo, noRepo := request.RepoFrom(ctx)
|
||||
if !noRepo {
|
||||
// this should never happen. the repository
|
||||
// should always be injected into the context
|
||||
// by an upstream handler in the chain.
|
||||
log.Errorln("api: null repository in context")
|
||||
render.NotFound(w, errors.ErrNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
log = log.WithField("visibility", repo.Visibility)
|
||||
|
||||
switch {
|
||||
case admin == true: // continue
|
||||
case write == true: // continue
|
||||
case repo.Visibility == core.VisibilityPublic:
|
||||
log.Debugln("api: read access granted")
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
case ok == false:
|
||||
render.Unauthorized(w, errors.ErrUnauthorized)
|
||||
log.Debugln("api: authentication required")
|
||||
return
|
||||
case ok == true && repo.Visibility == core.VisibilityInternal:
|
||||
log.Debugln("api: read access granted")
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
perm, ok := request.PermFrom(ctx)
|
||||
if !ok {
|
||||
render.NotFound(w, errors.ErrNotFound)
|
||||
log.Debugln("api: repository permissions not found")
|
||||
return
|
||||
}
|
||||
log = log.WithFields(
|
||||
logrus.Fields{
|
||||
"read": perm.Read,
|
||||
"write": perm.Write,
|
||||
"admin": perm.Admin,
|
||||
},
|
||||
)
|
||||
|
||||
switch {
|
||||
case user.Active == false:
|
||||
render.Forbidden(w, errors.ErrForbidden)
|
||||
log.Debugln("api: active account required")
|
||||
case read == true && perm.Read == false:
|
||||
render.NotFound(w, errors.ErrNotFound)
|
||||
log.Debugln("api: read access required")
|
||||
case write == true && perm.Write == false:
|
||||
render.NotFound(w, errors.ErrNotFound)
|
||||
log.Debugln("api: write access required")
|
||||
case admin == true && perm.Admin == false:
|
||||
render.NotFound(w, errors.ErrNotFound)
|
||||
log.Debugln("api: admin access required")
|
||||
default:
|
||||
log.Debug("api: access granted")
|
||||
next.ServeHTTP(w, r.WithContext(
|
||||
request.WithPerm(ctx, perm),
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,827 @@
|
||||
// Copyright 2019 Drone.IO Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
package acl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api/errors"
|
||||
"github.com/drone/drone/handler/api/request"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
var noContext = context.Background()
|
||||
|
||||
// this test verifies that a 401 unauthorized error is written to
|
||||
// the response if the client is not authenticated and repository
|
||||
// visibility is internal or private.
|
||||
func TestCheckAccess_Guest_Unauthorized(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrUnauthorized
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user is not authenticated BUT
|
||||
// the repository is publicly visible.
|
||||
func TestCheckAccess_Guest_PublicVisibility(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := *mockRepo
|
||||
mockRepo.Visibility = core.VisibilityPublic
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithRepo(noContext, &mockRepo),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 401 unauthorized error is written to
|
||||
// the response if the repository visibility is internal, and the
|
||||
// client is not authenticated.
|
||||
func TestCheckAccess_Guest_InternalVisibility(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := *mockRepo
|
||||
mockRepo.Visibility = core.VisibilityInternal
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithRepo(noContext, &mockRepo),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user is authenticated AND
|
||||
// the repository is publicly visible.
|
||||
func TestCheckAccess_Authenticated_PublicVisibility(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := *mockRepo
|
||||
mockRepo.Visibility = core.VisibilityPublic
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, &mockRepo), mockUser),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user is authenticated AND
|
||||
// the repository has internal visible.
|
||||
func TestCheckAccess_Authenticated_InternalVisibility(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := *mockRepo
|
||||
mockRepo.Visibility = core.VisibilityInternal
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, &mockRepo), mockUser),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 404 not found error is written to
|
||||
// the response if the repository is not found AND the user is
|
||||
// authenticated.
|
||||
func TestCheckAccess_Authenticated_RepositoryNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusNotFound; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrNotFound
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 404 not found error is written to
|
||||
// the response if the user does not have permissions to access
|
||||
// the repository.
|
||||
func TestCheckAccess_Permission_NotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo), mockUser),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusNotFound; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrNotFound
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user has read access to the
|
||||
// repository.
|
||||
func TestCheckReadAccess(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
readAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: false,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(r.Context(), mockUser),
|
||||
)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
readAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 404 not found error is written to
|
||||
// the response if the user lacks read access to the repository.
|
||||
func TestCheckReadAccess_InsufficientPermissions(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
noAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: false,
|
||||
Write: false,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
noAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckReadAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusNotFound; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrNotFound
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user has write access to the
|
||||
// repository.
|
||||
func TestCheckWriteAccess(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
writeAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: true,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
writeAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckWriteAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is not processed if the user has write access BUT
|
||||
// has been inactivated (e.g. blocked).
|
||||
func TestCheckWriteAccess_InactiveUser(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
writeAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: true,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUserInactive,
|
||||
),
|
||||
writeAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckWriteAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Error("should not invoke handler")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusForbidden; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 404 not found error is written to
|
||||
// the response if the user lacks write access to the repository.
|
||||
//
|
||||
// TODO(bradrydzewski) we should consider returning a 403 forbidden
|
||||
// if the user has read access.
|
||||
func TestCheckWriteAccess_InsufficientPermissions(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
noAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: false,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
noAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckWriteAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusNotFound; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrNotFound
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the user has admin access to the
|
||||
// repository.
|
||||
func TestCheckAdminAccess(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
noAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: true,
|
||||
Admin: true,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
noAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckAdminAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 404 not found error is written to
|
||||
// the response if the user lacks admin access to the repository.
|
||||
//
|
||||
// TODO(bradrydzewski) we should consider returning a 403 forbidden
|
||||
// if the user has read access.
|
||||
func TestCheckAdminAccess_InsufficientPermissions(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
noAccess := &core.Perm{
|
||||
Synced: time.Now().Unix(),
|
||||
Read: true,
|
||||
Write: true,
|
||||
Admin: false,
|
||||
}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithPerm(
|
||||
request.WithUser(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
mockUser,
|
||||
),
|
||||
noAccess,
|
||||
),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckAdminAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusNotFound; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrNotFound
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies the the next handler in the middleware
|
||||
// chain is processed if the authenticated user is a system
|
||||
// administrator.
|
||||
func TestCheckAdminAccess_SystemAdmin(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
user := &core.User{ID: 1, Admin: true, Active: true}
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithUser(r.Context(), user),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckAdminAccess())
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusTeapot)
|
||||
})
|
||||
})
|
||||
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 401 unauthorized error is written to
|
||||
// the response if the client is not authenticated and write
|
||||
// access is required.
|
||||
func TestCheckAccess_Guest_Write(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckAccess(true, true, false))
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrUnauthorized
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 401 unauthorized error is written to
|
||||
// the response if the client is not authenticated and admin
|
||||
// access is required.
|
||||
func TestCheckAccess_Guest_Admin(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
r = r.WithContext(
|
||||
request.WithRepo(noContext, mockRepo),
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
router.Use(CheckAccess(true, false, true))
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("Must not invoke next handler in middleware chain")
|
||||
})
|
||||
})
|
||||
router.ServeHTTP(w, r)
|
||||
|
||||
if got, want := w.Code, http.StatusUnauthorized; got != want {
|
||||
t.Errorf("Want status code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.ErrUnauthorized
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// // this test verifies the the next handler in the middleware
|
||||
// // chain is processed if the authenticated has read permissions
|
||||
// // that are successfully synchronized with the source.
|
||||
// func TestCheckAccess_RefreshPerms(t *testing.T) {
|
||||
// controller := gomock.NewController(t)
|
||||
// defer controller.Finish()
|
||||
|
||||
// expiredAccess := &core.Perm{
|
||||
// Synced: 0,
|
||||
// Read: false,
|
||||
// Write: false,
|
||||
// Admin: false,
|
||||
// }
|
||||
|
||||
// updatedAccess := &core.Perm{
|
||||
// Read: true,
|
||||
// Write: true,
|
||||
// Admin: true,
|
||||
// }
|
||||
|
||||
// checkPermUpdate := func(ctx context.Context, perm *core.Perm) {
|
||||
// if perm.Synced == 0 {
|
||||
// t.Errorf("Expect synced timestamp updated")
|
||||
// }
|
||||
// if perm.Read == false {
|
||||
// t.Errorf("Expect Read flag updated")
|
||||
// }
|
||||
// if perm.Write == false {
|
||||
// t.Errorf("Expect Write flag updated")
|
||||
// }
|
||||
// if perm.Admin == false {
|
||||
// t.Errorf("Expect Admin flag updated")
|
||||
// }
|
||||
// }
|
||||
|
||||
// repos := mock.NewMockRepositoryStore(controller)
|
||||
// repos.EXPECT().FindName(gomock.Any(), "octocat", "hello-world").Return(mockRepo, nil)
|
||||
|
||||
// perms := mock.NewMockPermStore(controller)
|
||||
// perms.EXPECT().Find(gomock.Any(), mockRepo.UID, mockUser.ID).Return(expiredAccess, nil)
|
||||
// perms.EXPECT().Update(gomock.Any(), expiredAccess).Return(nil).Do(checkPermUpdate)
|
||||
|
||||
// service := mock.NewMockRepositoryService(controller)
|
||||
// service.EXPECT().FindPerm(gomock.Any(), "octocat/hello-world").Return(updatedAccess, nil)
|
||||
|
||||
// factory := mock.NewMockRepositoryServiceFactory(controller)
|
||||
// factory.EXPECT().Create(mockUser).Return(service)
|
||||
|
||||
// w := httptest.NewRecorder()
|
||||
// r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
// r = r.WithContext(
|
||||
// request.WithUser(r.Context(), mockUser),
|
||||
// )
|
||||
|
||||
// router := chi.NewRouter()
|
||||
// router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
// router.Use(CheckReadAccess(factory, repos, perms))
|
||||
// router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// w.WriteHeader(http.StatusTeapot)
|
||||
// })
|
||||
// })
|
||||
|
||||
// router.ServeHTTP(w, r)
|
||||
|
||||
// if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
// t.Errorf("Want status code %d, got %d", want, got)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // this test verifies that a 404 not found error is written to
|
||||
// // the response if the user permissions are expired and the
|
||||
// // updated permissions cannot be fetched.
|
||||
// func TestCheckAccess_RefreshPerms_Error(t *testing.T) {
|
||||
// controller := gomock.NewController(t)
|
||||
// defer controller.Finish()
|
||||
|
||||
// expiredAccess := &core.Perm{
|
||||
// Synced: 0,
|
||||
// Read: false,
|
||||
// Write: false,
|
||||
// Admin: false,
|
||||
// }
|
||||
|
||||
// repos := mock.NewMockRepositoryStore(controller)
|
||||
// repos.EXPECT().FindName(gomock.Any(), "octocat", "hello-world").Return(mockRepo, nil)
|
||||
|
||||
// perms := mock.NewMockPermStore(controller)
|
||||
// perms.EXPECT().Find(gomock.Any(), mockRepo.UID, mockUser.ID).Return(expiredAccess, nil)
|
||||
|
||||
// service := mock.NewMockRepositoryService(controller)
|
||||
// service.EXPECT().FindPerm(gomock.Any(), "octocat/hello-world").Return(nil, io.EOF)
|
||||
|
||||
// factory := mock.NewMockRepositoryServiceFactory(controller)
|
||||
// factory.EXPECT().Create(mockUser).Return(service)
|
||||
|
||||
// w := httptest.NewRecorder()
|
||||
// r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
// r = r.WithContext(
|
||||
// request.WithUser(r.Context(), mockUser),
|
||||
// )
|
||||
|
||||
// router := chi.NewRouter()
|
||||
// router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
// router.Use(CheckReadAccess(factory, repos, perms))
|
||||
// router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// w.WriteHeader(http.StatusTeapot)
|
||||
// })
|
||||
// })
|
||||
|
||||
// router.ServeHTTP(w, r)
|
||||
// if got, want := w.Code, 404; got != want {
|
||||
// t.Errorf("Want status code %d, got %d", want, got)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // this test verifies the the next handler in the middleware
|
||||
// // chain is processed if the user permissions are expired,
|
||||
// // updated permissions are fetched, but fail the changes fail
|
||||
// // to persist to the database. We know the user has access,
|
||||
// // so we allow them to proceed even in the event of a failure.
|
||||
// func TestCheckAccess_RefreshPerms_CannotSave(t *testing.T) {
|
||||
// controller := gomock.NewController(t)
|
||||
// defer controller.Finish()
|
||||
|
||||
// expiredAccess := &core.Perm{
|
||||
// Synced: 0,
|
||||
// Read: false,
|
||||
// Write: false,
|
||||
// Admin: false,
|
||||
// }
|
||||
|
||||
// updatedAccess := &core.Perm{
|
||||
// Read: true,
|
||||
// Write: true,
|
||||
// Admin: true,
|
||||
// }
|
||||
|
||||
// service := mock.NewMockRepositoryService(controller)
|
||||
// service.EXPECT().FindPerm(gomock.Any(), "octocat/hello-world").Return(updatedAccess, nil)
|
||||
|
||||
// factory := mock.NewMockRepositoryServiceFactory(controller)
|
||||
// factory.EXPECT().Create(mockUser).Return(service)
|
||||
|
||||
// repos := mock.NewMockRepositoryStore(controller)
|
||||
// repos.EXPECT().FindName(gomock.Any(), "octocat", "hello-world").Return(mockRepo, nil)
|
||||
|
||||
// perms := mock.NewMockPermStore(controller)
|
||||
// perms.EXPECT().Find(gomock.Any(), mockRepo.UID, mockUser.ID).Return(expiredAccess, nil)
|
||||
// perms.EXPECT().Update(gomock.Any(), expiredAccess).Return(io.EOF)
|
||||
|
||||
// w := httptest.NewRecorder()
|
||||
// r := httptest.NewRequest("GET", "/api/repos/octocat/hello-world", nil)
|
||||
// r = r.WithContext(
|
||||
// request.WithUser(r.Context(), mockUser),
|
||||
// )
|
||||
|
||||
// router := chi.NewRouter()
|
||||
// router.Route("/api/repos/{owner}/{name}", func(router chi.Router) {
|
||||
// router.Use(CheckReadAccess(factory, repos, perms))
|
||||
// router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// w.WriteHeader(http.StatusTeapot)
|
||||
// })
|
||||
// })
|
||||
|
||||
// router.ServeHTTP(w, r)
|
||||
// if got, want := w.Code, http.StatusTeapot; got != want {
|
||||
// t.Errorf("Want status code %d, got %d", want, got)
|
||||
// }
|
||||
// }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue