mirror of
https://github.com/harness/drone.git
synced 2025-07-10 20:49:02 +00:00
Compare commits
15 Commits
master
...
v2.25.1-de
Author | SHA1 | Date | |
---|---|---|---|
|
3e7ecf1615 | ||
|
c32df38e62 | ||
|
9b951983de | ||
|
5a73d60992 | ||
|
c4037def3e | ||
|
87381af2ac | ||
|
cc2f033569 | ||
|
94bcb869dc | ||
|
e1fc66e077 | ||
|
05296f42d2 | ||
|
af44f639fd | ||
|
3c37646f3a | ||
|
915212145f | ||
|
0d41939140 | ||
|
320cd3edab |
@ -9,14 +9,14 @@ platform:
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.14.15
|
||||
image: golang:1.22.7
|
||||
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
|
||||
image: golang:1.22.7
|
||||
commands:
|
||||
- sh scripts/build.sh
|
||||
environment:
|
||||
@ -53,7 +53,7 @@ platform:
|
||||
|
||||
steps:
|
||||
- name: build
|
||||
image: golang:1.14.15
|
||||
image: golang:1.22.7
|
||||
commands:
|
||||
- sh scripts/build.sh
|
||||
environment:
|
||||
|
125
.github/readme.md
vendored
125
.github/readme.md
vendored
@ -1,7 +1,122 @@
|
||||
Gitness is an Open Source developer platform with Source Control management, Continuous Integration and Continuous Delivery. Gitness is the successor to Drone and will be merging with the Drone project over the coming months.
|
||||
# [Drone](https://www.drone.io/) <img src="https://github.com/drone/brand/blob/master/screenshots/screenshot_build_success.png" style="max-width:100px;" />
|
||||
**Welcome to the Drone codebase, we are thrilled to have you here!**
|
||||
|
||||
Documentation and Other Links:
|
||||
## What is Drone?
|
||||
Drone is a continuous delivery system built on container technology. Drone uses a simple YAML build file, to define and execute build pipelines inside Docker containers.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* Setup Documentation [docs.gitness.com/getting-started](https://docs.gitness.com/)
|
||||
* Usage Documentation for repositories [docs.drone.io/getting-started](https://docs.gitness.com/repositories/overview)
|
||||
* Join the [Gitness Slack Channel](https://join.slack.com/t/harnesscommunity/shared_invite/zt-y4hdqh7p-RVuEQyIl5Hcx4Ck8VCvzBw)
|
||||
- [What is Drone?](#what-is-drone)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Community and Support](#community-and-support)
|
||||
- [Contributing](#contributing)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [Setup Documentation](#setup-documentation)
|
||||
- [Usage Documentation](#usage-documentation)
|
||||
- [Example `.drone.yml` build file](#example-droneyml-build-file)
|
||||
- [Plugin Index](#plugin-index)
|
||||
- [Documentation and Other Links](#documentation-and-Other-Links)
|
||||
|
||||
## Community and Support
|
||||
[Harness Community Slack](https://join.slack.com/t/harnesscommunity/shared_invite/zt-y4hdqh7p-RVuEQyIl5Hcx4Ck8VCvzBw) - Join the #drone slack channel to connect with our engineers and other users running Drone CI.
|
||||
</br>
|
||||
[Harness Community Forum](https://community.harness.io/) - Ask questions, find answers, and help other users.
|
||||
</br>
|
||||
[Report A Bug]([https://community.harness.io/c/bugs/17](https://github.com/harness/harness/issues/new)) - Found a bug? Please file it under Issues. Ensure to include detailed steps to reproduce and relevant screenshots for better clarity.
|
||||
</br>
|
||||
[Events](https://www.meetup.com/harness/) - Keep up to date with Drone events and check out previous events [here](https://www.youtube.com/watch?v=Oq34ImUGcHA&list=PLXsYHFsLmqf3zwelQDAKoVNmLeqcVsD9o).
|
||||
|
||||
## Contributing
|
||||
|
||||
We encourage you to contribute to Drone! Whether that's joining in on the community slack or discourse, or contributing pull requests / documentation changes or raising issues.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Drone follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
### Setup Documentation
|
||||
|
||||
This section of the [documentation](http://docs.drone.io/installation/) will help you install and configure the Drone Server and one or many Runners. A runner is a standalone daemon that polls the server for pending pipelines to execute.
|
||||
|
||||
### Usage Documentation
|
||||
|
||||
Our [documentation](http://docs.drone.io/getting-started/) can help you get started with the different types of pipelines/builds. There are different runners / plugins / extensions designed for different use cases to help make an efficient and simple build pipeline
|
||||
|
||||
### Plugin Index
|
||||
|
||||
Plugins are used in build steps to perform actions, eg send a message to slack or push a container to a registry. We have an extensive list of community plugins to customize your build pipeline, you can find those [here](http://plugins.drone.io/).
|
||||
|
||||
### Example `.drone.yml` build file.
|
||||
|
||||
This build file contains a single pipeline (you can have multiple pipelines too) that builds a go application. The front end with npm. Publishes the docker container to a registry and announces the results to a slack room.
|
||||
|
||||
```YAML
|
||||
name: default
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
|
||||
steps:
|
||||
- name: backend
|
||||
image: golang
|
||||
commands:
|
||||
- go get
|
||||
- go build
|
||||
- go test
|
||||
|
||||
- name: frontend
|
||||
image: node:6
|
||||
commands:
|
||||
- npm install
|
||||
- npm test
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: octocat/hello-world
|
||||
tags: [ 1, 1.1, latest ]
|
||||
registry: index.docker.io
|
||||
|
||||
- name: notify
|
||||
image: plugins/slack
|
||||
settings:
|
||||
channel: developers
|
||||
username: drone
|
||||
```
|
||||
|
||||
## Documentation and Other Links
|
||||
|
||||
* Setup Documentation [docs.drone.io/installation](http://docs.drone.io/installation/)
|
||||
* Usage Documentation [docs.drone.io/getting-started](http://docs.drone.io/getting-started/)
|
||||
* Plugin Index [plugins.drone.io](http://plugins.drone.io/)
|
||||
* Getting Help [discourse.drone.io](https://discourse.drone.io)
|
||||
* Build the Enterprise Edition [BUILDING](https://github.com/drone/drone/blob/master/BUILDING)
|
||||
* Build the Community Edition [BUILDING_OSS](https://github.com/drone/drone/blob/master/BUILDING_OSS)
|
||||
|
||||
## Building from source
|
||||
|
||||
We have two versions available: the [Enterprise Edition](https://github.com/drone/drone/blob/master/BUILDING) and the [Community Edition](https://github.com/drone/drone/blob/master/BUILDING_OSS)
|
||||
|
||||
## Release procedure
|
||||
|
||||
Run the changelog generator.
|
||||
|
||||
```BASH
|
||||
docker run -it --rm -v "$(pwd)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator -u drone -p drone -t <secret github token>
|
||||
```
|
||||
|
||||
You can generate a token by logging into your GitHub account and going to Settings -> Personal access tokens.
|
||||
|
||||
Next we tag the PR's with the fixes or enhancements labels. If the PR does not fulfill the requirements, do not add a label.
|
||||
|
||||
**Before moving on make sure to update the version file `version/version.go && version/version_test.go`.**
|
||||
|
||||
Run the changelog generator again with the future version according to semver.
|
||||
|
||||
```BASH
|
||||
docker run -it --rm -v "$(pwd)":/usr/local/src/your-app githubchangeloggenerator/github-changelog-generator -u harness -p drone -t <secret token> --future-release v1.0.0
|
||||
```
|
||||
|
||||
Create your pull request for the release. Get it merged then tag the release.
|
||||
|
||||
[⬆ Back to Top](#table-of-contents)
|
||||
|
@ -80,13 +80,14 @@ type (
|
||||
Yaml Yaml
|
||||
|
||||
// Remote configurations
|
||||
Bitbucket Bitbucket
|
||||
Gitea Gitea
|
||||
Github Github
|
||||
GitLab GitLab
|
||||
Gogs Gogs
|
||||
Stash Stash
|
||||
Gitee Gitee
|
||||
Bitbucket Bitbucket
|
||||
Gitea Gitea
|
||||
Github Github
|
||||
GitLab GitLab
|
||||
Gogs Gogs
|
||||
Stash Stash
|
||||
Gitee Gitee
|
||||
IncomingWebhook IncomingWebhook
|
||||
}
|
||||
|
||||
// Cloning provides the cloning configuration.
|
||||
@ -170,6 +171,7 @@ type (
|
||||
// Prometheus provides the prometheus configuration.
|
||||
Prometheus struct {
|
||||
EnableAnonymousAccess bool `envconfig:"DRONE_PROMETHEUS_ANONYMOUS_ACCESS" default:"false"`
|
||||
EnableHTTPMetrics bool `envconfig:"DRONE_PROMETHEUS_HTTP_METRICS" default:"false"`
|
||||
}
|
||||
|
||||
// Redis provides the redis configuration.
|
||||
@ -442,6 +444,10 @@ type (
|
||||
ContentSecurityPolicy string `envconfig:"DRONE_HTTP_CONTENT_SECURITY_POLICY"`
|
||||
ReferrerPolicy string `envconfig:"DRONE_HTTP_REFERRER_POLICY"`
|
||||
}
|
||||
|
||||
IncomingWebhook struct {
|
||||
Events []string `envconfig:"DRONE_INCOMING_WEBHOOK_EVENTS" default:"branch,deployment,push,tag,pull_request"`
|
||||
}
|
||||
)
|
||||
|
||||
// Environ returns the settings from the environment.
|
||||
|
@ -17,6 +17,7 @@ package main
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
chiprometheus "github.com/766b/chi-prometheus"
|
||||
"github.com/drone/drone/cmd/drone-server/config"
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api"
|
||||
@ -59,8 +60,12 @@ var serverSet = wire.NewSet(
|
||||
|
||||
// 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 {
|
||||
func provideRouter(api api.Server, web web.Server, rpcv1 rpcHandlerV1, rpcv2 rpcHandlerV2, healthz healthzHandler, metrics *metric.Server, pprof pprofHandler, config config.Config) *chi.Mux {
|
||||
r := chi.NewRouter()
|
||||
if config.Prometheus.EnableHTTPMetrics {
|
||||
m := chiprometheus.NewPatternMiddleware("server")
|
||||
r.Use(m)
|
||||
}
|
||||
r.Mount("/healthz", healthz)
|
||||
r.Mount("/metrics", metrics)
|
||||
r.Mount("/api", api.Handler())
|
||||
|
@ -85,7 +85,7 @@ func provideContentService(client *scm.Client, renewer core.Renewer) core.FileSe
|
||||
// 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)
|
||||
return hook.New(client, config.Proxy.Addr, renewer, config.IncomingWebhook.Events)
|
||||
}
|
||||
|
||||
// provideNetrcService is a Wire provider function that returns
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Code generated by Wire. DO NOT EDIT.
|
||||
|
||||
//go:generate wire
|
||||
//+build !wireinject
|
||||
//go:generate go run github.com/google/wire/cmd/wire
|
||||
//go:build !wireinject
|
||||
// +build !wireinject
|
||||
|
||||
package main
|
||||
|
||||
@ -113,7 +114,7 @@ func InitializeApplication(config2 config.Config) (application, error) {
|
||||
mainHealthzHandler := provideHealthz()
|
||||
metricServer := provideMetric(session, config2)
|
||||
mainPprofHandler := providePprof(config2)
|
||||
mux := provideRouter(server, webServer, mainRpcHandlerV1, mainRpcHandlerV2, mainHealthzHandler, metricServer, mainPprofHandler)
|
||||
mux := provideRouter(server, webServer, mainRpcHandlerV1, mainRpcHandlerV2, mainHealthzHandler, metricServer, mainPprofHandler, config2)
|
||||
serverServer := provideServer(mux, config2)
|
||||
mainApplication := newApplication(cronScheduler, reaper, datadog, runner, serverServer, userStore)
|
||||
return mainApplication, nil
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
ENV GODEBUG netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
@ -9,7 +9,7 @@ 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
|
||||
RUN if [[ ! -e /etc/nsswitch.conf ]] ; then echo 'hosts: files dns' > /etc/nsswitch.conf ; fi
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=alpine /usr/share/zoneinfo /usr/share/zoneinfo
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
ENV GODEBUG netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=amd64
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
ENV GODEBUG=netdns=go
|
||||
ENV DRONE_RUNNER_OS=linux
|
||||
ENV DRONE_RUNNER_ARCH=arm64
|
||||
|
@ -1,13 +1,13 @@
|
||||
# docker build --rm -f docker/Dockerfile -t drone/drone .
|
||||
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
RUN if [[ ! -e /etc/nsswitch.conf ]] ; then echo 'hosts: files dns' > /etc/nsswitch.conf ; fi
|
||||
|
||||
ENV GODEBUG netdns=go
|
||||
ENV XDG_CACHE_HOME /data
|
||||
|
@ -1,9 +1,9 @@
|
||||
# docker build --rm -f docker/Dockerfile -t drone/drone .
|
||||
|
||||
FROM alpine:3.11 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates tzdata
|
||||
|
||||
FROM alpine:3.11
|
||||
FROM alpine:3.20
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
|
@ -1,14 +1,20 @@
|
||||
# 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.20
|
||||
|
||||
FROM alpine:3.11
|
||||
# Expose necessary ports and define volume
|
||||
EXPOSE 80 443
|
||||
VOLUME /data
|
||||
|
||||
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
# Install necessary certificates and timezone data
|
||||
RUN apk add -U --no-cache ca-certificates tzdata && \
|
||||
cp -r /usr/share/zoneinfo /etc/zoneinfo && \
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
# Configure /etc/nsswitch.conf to prevent DNS-related errors
|
||||
RUN sh -c "if [ ! -f /etc/nsswitch.conf ]; then echo 'hosts: files dns' > /etc/nsswitch.conf; fi"
|
||||
|
||||
# Environment variables
|
||||
ENV GODEBUG netdns=go
|
||||
ENV XDG_CACHE_HOME /data
|
||||
ENV DRONE_DATABASE_DRIVER sqlite3
|
||||
@ -20,8 +26,8 @@ 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 the binary
|
||||
ADD release/linux/arm64/drone-server /bin/
|
||||
ENTRYPOINT ["/bin/drone-server"]
|
||||
|
||||
# Define the entrypoint
|
||||
ENTRYPOINT ["/bin/drone-server"]
|
||||
|
72
go.mod
72
go.mod
@ -3,18 +3,17 @@ 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/766b/chi-prometheus v0.0.0-20211217152057-87afa9aa2ca8
|
||||
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/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
||||
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/coreos/go-semver v0.3.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-ui v2.12.0+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
|
||||
@ -30,34 +29,73 @@ require (
|
||||
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/go-jsonnet v0.20.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-multierror v1.1.1
|
||||
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/prometheus/client_golang v1.11.1
|
||||
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/sirupsen/logrus v1.8.1
|
||||
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
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/azure-pipeline-go v0.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bmatcuk/doublestar v1.1.1 // indirect
|
||||
github.com/buildkite/yaml v2.1.0+incompatible // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/codegangsta/negroni v1.0.0 // indirect
|
||||
github.com/containerd/containerd v1.5.18 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v1.13.1 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
|
||||
github.com/vinzenz/yaml v0.0.0-20170920082545-91409cdd725d // indirect
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
|
||||
google.golang.org/grpc v1.43.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/h2non/gock => gopkg.in/h2non/gock.v1 v1.0.14
|
||||
|
||||
go 1.13
|
||||
go 1.22.7
|
||||
|
@ -239,6 +239,10 @@ func (s Server) Handler() http.Handler {
|
||||
acl.CheckAdminAccess(),
|
||||
).Post("/{number}/decline/{stage}", stages.HandleDecline(s.Repos, s.Builds, s.Stages))
|
||||
|
||||
r.With(
|
||||
acl.CheckAdminAccess(),
|
||||
).Post("/{number}/decline", stages.HandleDeclineBuild(s.Repos, s.Builds, s.Stages))
|
||||
|
||||
r.With(
|
||||
acl.CheckAdminAccess(),
|
||||
).Post("/{number}/approve/{stage}", stages.HandleApprove(s.Repos, s.Builds, s.Stages, s.Scheduler))
|
||||
|
87
handler/api/repos/builds/stages/decline_build.go
Normal file
87
handler/api/repos/builds/stages/decline_build.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2024 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 stages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api/render"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
)
|
||||
|
||||
func HandleDeclineBuild(
|
||||
repos core.RepositoryStore,
|
||||
builds core.BuildStore,
|
||||
stages core.StageStore,
|
||||
) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
namespace = chi.URLParam(r, "owner")
|
||||
name = chi.URLParam(r, "name")
|
||||
)
|
||||
buildNumber, err := strconv.ParseInt(chi.URLParam(r, "number"), 10, 64)
|
||||
if err != nil {
|
||||
render.BadRequestf(w, "Invalid build number")
|
||||
return
|
||||
}
|
||||
|
||||
repo, err := repos.FindName(r.Context(), namespace, name)
|
||||
if err != nil {
|
||||
render.NotFoundf(w, "Repository not found")
|
||||
return
|
||||
}
|
||||
build, err := builds.FindNumber(r.Context(), repo.ID, buildNumber)
|
||||
if err != nil {
|
||||
render.NotFoundf(w, "Build not found")
|
||||
return
|
||||
}
|
||||
|
||||
stageList, err := stages.List(r.Context(), build.ID)
|
||||
if err != nil {
|
||||
render.NotFoundf(w, "Stages not found")
|
||||
return
|
||||
}
|
||||
|
||||
for _, stage := range stageList {
|
||||
if stage.Status != core.StatusBlocked {
|
||||
err := fmt.Errorf("Cannot decline build with status %q", stage.Status)
|
||||
render.BadRequest(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
stage.Status = core.StatusDeclined
|
||||
err = stages.Update(r.Context(), stage)
|
||||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
build.Status = core.StatusDeclined
|
||||
err = builds.Update(r.Context(), build)
|
||||
if err != nil {
|
||||
render.InternalError(w, err)
|
||||
return
|
||||
}
|
||||
// TODO delete any pending stages from the build queue
|
||||
// TODO update any pending stages to skipped in the database
|
||||
// TODO update the build status to error in the source code management system
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
192
handler/api/repos/builds/stages/decline_build_test.go
Normal file
192
handler/api/repos/builds/stages/decline_build_test.go
Normal file
@ -0,0 +1,192 @@
|
||||
// Copyright 2024 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 stages
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/drone/drone/core"
|
||||
"github.com/drone/drone/handler/api/errors"
|
||||
"github.com/drone/drone/mock"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
// For invalid stage number test and stage not found test, it is not applicable for DeclineV2 as we are not dealing with individual stage here.
|
||||
// We are dealing with list of stages here so no UT is possible for individual stage number verification or individual stage not found.
|
||||
|
||||
// this test verifies that a 400 bad request status is returned
|
||||
// from the http.Handler with a human-readable error message if
|
||||
// the build number url parameter fails to parse.
|
||||
func TestDeclineBuild_InvalidBuildNumber(t *testing.T) {
|
||||
c := new(chi.Context)
|
||||
c.URLParams.Add("owner", "octocat")
|
||||
c.URLParams.Add("name", "hello-world")
|
||||
c.URLParams.Add("number", "I")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||
)
|
||||
|
||||
HandleDeclineBuild(nil, nil, nil)(w, r)
|
||||
if got, want := w.Code, 400; want != got {
|
||||
t.Errorf("Want response code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.New("Invalid build number")
|
||||
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 status is returned
|
||||
// from the http.Handler with a human-readable error message if
|
||||
// the repository is not found in the database.
|
||||
func TestDeclineBuild_RepoNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := &core.Repository{
|
||||
Namespace: "octocat",
|
||||
Name: "hello-world",
|
||||
}
|
||||
|
||||
repos := mock.NewMockRepositoryStore(controller)
|
||||
repos.EXPECT().FindName(gomock.Any(), mockRepo.Namespace, mockRepo.Name).Return(nil, sql.ErrNoRows)
|
||||
|
||||
c := new(chi.Context)
|
||||
c.URLParams.Add("owner", "octocat")
|
||||
c.URLParams.Add("name", "hello-world")
|
||||
c.URLParams.Add("number", "1")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||
)
|
||||
|
||||
HandleDeclineBuild(repos, nil, nil)(w, r)
|
||||
if got, want := w.Code, 404; want != got {
|
||||
t.Errorf("Want response code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.New("Repository not found")
|
||||
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 status is returned
|
||||
// from the http.Handler with a human-readable error message if
|
||||
// the build is not found in the database.
|
||||
func TestDeclineBuild_BuildNotFound(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := &core.Repository{
|
||||
Namespace: "octocat",
|
||||
Name: "hello-world",
|
||||
}
|
||||
|
||||
repos := mock.NewMockRepositoryStore(controller)
|
||||
repos.EXPECT().FindName(gomock.Any(), mockRepo.Namespace, mockRepo.Name).Return(mockRepo, nil)
|
||||
|
||||
builds := mock.NewMockBuildStore(controller)
|
||||
builds.EXPECT().FindNumber(gomock.Any(), mockRepo.ID, int64(1)).Return(nil, sql.ErrNoRows)
|
||||
|
||||
c := new(chi.Context)
|
||||
c.URLParams.Add("owner", "octocat")
|
||||
c.URLParams.Add("name", "hello-world")
|
||||
c.URLParams.Add("number", "1")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||
)
|
||||
|
||||
HandleDeclineBuild(repos, builds, nil)(w, r)
|
||||
if got, want := w.Code, 404; want != got {
|
||||
t.Errorf("Want response code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.New("Build not found")
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test verifies that a 400 bad request status is returned
|
||||
// from the http.Handler with a human-readable error message if
|
||||
// the build status is not Blocked.
|
||||
func TestDeclineBuild_InvalidStatus(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockRepo := &core.Repository{
|
||||
Namespace: "octocat",
|
||||
Name: "hello-world",
|
||||
}
|
||||
mockBuild := &core.Build{
|
||||
ID: 111,
|
||||
Number: 1,
|
||||
Status: core.StatusPending,
|
||||
}
|
||||
mockStage1 := &core.Stage{
|
||||
ID: 222,
|
||||
Number: 2,
|
||||
Status: core.StatusPending,
|
||||
}
|
||||
|
||||
mockStage2 := &core.Stage{
|
||||
ID: 333,
|
||||
Number: 3,
|
||||
Status: core.StatusPending,
|
||||
}
|
||||
|
||||
mockStageList := []*core.Stage{mockStage1, mockStage2}
|
||||
|
||||
repos := mock.NewMockRepositoryStore(controller)
|
||||
repos.EXPECT().FindName(gomock.Any(), mockRepo.Namespace, mockRepo.Name).Return(mockRepo, nil)
|
||||
|
||||
builds := mock.NewMockBuildStore(controller)
|
||||
builds.EXPECT().FindNumber(gomock.Any(), mockRepo.ID, int64(1)).Return(mockBuild, nil)
|
||||
|
||||
stages := mock.NewMockStageStore(controller)
|
||||
stages.EXPECT().List(gomock.Any(), mockBuild.ID).Return(mockStageList, nil)
|
||||
|
||||
c := new(chi.Context)
|
||||
c.URLParams.Add("owner", "octocat")
|
||||
c.URLParams.Add("name", "hello-world")
|
||||
c.URLParams.Add("number", "1")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r = r.WithContext(
|
||||
context.WithValue(context.Background(), chi.RouteCtxKey, c),
|
||||
)
|
||||
|
||||
HandleDeclineBuild(repos, builds, stages)(w, r)
|
||||
if got, want := w.Code, 400; want != got {
|
||||
t.Errorf("Want response code %d, got %d", want, got)
|
||||
}
|
||||
|
||||
got, want := new(errors.Error), errors.New(`Cannot decline build with status "pending"`)
|
||||
json.NewDecoder(w.Body).Decode(got)
|
||||
if diff := cmp.Diff(got, want); len(diff) != 0 {
|
||||
t.Errorf(diff)
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by the Drone Non-Commercial License
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !oss
|
||||
// +build !oss
|
||||
|
||||
package rpc2
|
||||
|
@ -23,14 +23,15 @@ import (
|
||||
)
|
||||
|
||||
// New returns a new HookService.
|
||||
func New(client *scm.Client, addr string, renew core.Renewer) core.HookService {
|
||||
return &service{client: client, addr: addr, renew: renew}
|
||||
func New(client *scm.Client, addr string, renew core.Renewer, events []string) core.HookService {
|
||||
return &service{client: client, addr: addr, renew: renew, events: events}
|
||||
}
|
||||
|
||||
type service struct {
|
||||
renew core.Renewer
|
||||
client *scm.Client
|
||||
addr string
|
||||
events []string
|
||||
}
|
||||
|
||||
func (s *service) Create(ctx context.Context, user *core.User, repo *core.Repository) error {
|
||||
@ -38,6 +39,12 @@ func (s *service) Create(ctx context.Context, user *core.User, repo *core.Reposi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventsMap := make(map[string]bool)
|
||||
for _, event := range s.events {
|
||||
eventsMap[event] = true
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, scm.TokenKey{}, &scm.Token{
|
||||
Token: user.Token,
|
||||
Refresh: user.Refresh,
|
||||
@ -48,11 +55,11 @@ func (s *service) Create(ctx context.Context, user *core.User, repo *core.Reposi
|
||||
Target: s.addr + "/hook",
|
||||
Secret: repo.Signer,
|
||||
Events: scm.HookEvents{
|
||||
Branch: true,
|
||||
Deployment: true,
|
||||
PullRequest: true,
|
||||
Push: true,
|
||||
Tag: true,
|
||||
Branch: eventsMap["branch"],
|
||||
Deployment: eventsMap["deployment"],
|
||||
PullRequest: eventsMap["pull_request"],
|
||||
Push: eventsMap["push"],
|
||||
Tag: eventsMap["tag"],
|
||||
},
|
||||
}
|
||||
return replaceHook(ctx, s.client, repo.Slug, hook)
|
||||
|
@ -50,11 +50,52 @@ func TestCreate(t *testing.T) {
|
||||
mockRepos := mockscm.NewMockRepositoryService(controller)
|
||||
mockRepos.EXPECT().ListHooks(gomock.Any(), "octocat/hello-world", gomock.Any()).Return(mockHooks, nil, nil)
|
||||
mockRepos.EXPECT().CreateHook(gomock.Any(), "octocat/hello-world", hook).Return(nil, nil, nil)
|
||||
|
||||
client := new(scm.Client)
|
||||
client.Repositories = mockRepos
|
||||
|
||||
service := New(client, "https://drone.company.com", mockRenewer)
|
||||
service := New(client, "https://drone.company.com", mockRenewer, []string{"branch", "deployment", "push", "tag", "pull_request"})
|
||||
err := service.Create(noContext, mockUser, mockRepo)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWithLimitedEvents(t *testing.T) {
|
||||
controller := gomock.NewController(t)
|
||||
defer controller.Finish()
|
||||
|
||||
mockUser := &core.User{}
|
||||
mockHooks := []*scm.Hook{}
|
||||
mockRepo := &core.Repository{
|
||||
Namespace: "octocat",
|
||||
Name: "hello-world",
|
||||
Slug: "octocat/hello-world",
|
||||
Signer: "abc123",
|
||||
}
|
||||
|
||||
hook := &scm.HookInput{
|
||||
Name: "drone",
|
||||
Target: "https://drone.company.com/hook",
|
||||
Secret: "abc123",
|
||||
Events: scm.HookEvents{
|
||||
Branch: false,
|
||||
Deployment: true,
|
||||
PullRequest: true,
|
||||
Push: false,
|
||||
Tag: true,
|
||||
},
|
||||
}
|
||||
|
||||
mockRenewer := mock.NewMockRenewer(controller)
|
||||
mockRenewer.EXPECT().Renew(gomock.Any(), mockUser, false).Return(nil)
|
||||
|
||||
mockRepos := mockscm.NewMockRepositoryService(controller)
|
||||
mockRepos.EXPECT().ListHooks(gomock.Any(), "octocat/hello-world", gomock.Any()).Return(mockHooks, nil, nil)
|
||||
mockRepos.EXPECT().CreateHook(gomock.Any(), "octocat/hello-world", hook).Return(nil, nil, nil)
|
||||
client := new(scm.Client)
|
||||
client.Repositories = mockRepos
|
||||
|
||||
service := New(client, "https://drone.company.com", mockRenewer, []string{"deployment", "tag", "pull_request"})
|
||||
err := service.Create(noContext, mockUser, mockRepo)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -70,7 +111,7 @@ func TestCreate_RenewErr(t *testing.T) {
|
||||
mockRenewer := mock.NewMockRenewer(controller)
|
||||
mockRenewer.EXPECT().Renew(gomock.Any(), mockUser, false).Return(scm.ErrNotAuthorized)
|
||||
|
||||
service := New(nil, "https://drone.company.com", mockRenewer)
|
||||
service := New(nil, "https://drone.company.com", mockRenewer, []string{})
|
||||
err := service.Create(noContext, mockUser, nil)
|
||||
if err != scm.ErrNotAuthorized {
|
||||
t.Errorf("Want not authorized error, got %v", err)
|
||||
@ -106,7 +147,7 @@ func TestDelete(t *testing.T) {
|
||||
client := new(scm.Client)
|
||||
client.Repositories = mockRepos
|
||||
|
||||
service := New(client, "https://drone.company.com", mockRenewer)
|
||||
service := New(client, "https://drone.company.com", mockRenewer, []string{})
|
||||
err := service.Delete(noContext, mockUser, mockRepo)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@ -122,7 +163,7 @@ func TestDelete_RenewErr(t *testing.T) {
|
||||
mockRenewer := mock.NewMockRenewer(controller)
|
||||
mockRenewer.EXPECT().Renew(gomock.Any(), mockUser, false).Return(scm.ErrNotAuthorized)
|
||||
|
||||
service := New(nil, "https://drone.company.com", mockRenewer)
|
||||
service := New(nil, "https://drone.company.com", mockRenewer, []string{})
|
||||
err := service.Delete(noContext, mockUser, nil)
|
||||
if err != scm.ErrNotAuthorized {
|
||||
t.Errorf("Want not authorized error, got %v", err)
|
||||
|
@ -25,7 +25,7 @@ var (
|
||||
// VersionMajor is for an API incompatible changes.
|
||||
VersionMajor int64 = 2
|
||||
// VersionMinor is for functionality in a backwards-compatible manner.
|
||||
VersionMinor int64 = 20
|
||||
VersionMinor int64 = 25
|
||||
// VersionPatch is for backwards-compatible bug fixes.
|
||||
VersionPatch int64 = 0
|
||||
// VersionPre indicates prerelease.
|
||||
|
@ -10,7 +10,7 @@ package version
|
||||
import "testing"
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
if got, want := Version.String(), "2.20.0"; got != want {
|
||||
if got, want := Version.String(), "2.25.0"; got != want {
|
||||
t.Errorf("Want version %s, got %s", want, got)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user