Skip to content
GitLab
Next
Menu
Why GitLab
Pricing
Contact Sales
Explore
Why GitLab
Pricing
Contact Sales
Explore
Sign in
Get free trial
Commits on Source (336)
b87a0bb1
Add bulk imports service with start migration method
Feb 05, 2025
b77f04ca
Merge branch 'bulk-imports-service' into 'main'
Feb 05, 2025
c180d86a
Introduce danger roulette
Feb 06, 2025
831f3050
Merge branch 'danger-roulette' into 'main'
Feb 06, 2025
69d9f9c5
Add usage_type to SSHKey
Feb 07, 2025
4f43f470
Merge branch 'faleksic-ssh-key-usage-type' into 'main'
Feb 07, 2025
22e80058
Update golangci/golangci-lint Docker tag to v1.64.2
Feb 11, 2025
b9a42e11
Remove exportloopref linter
Feb 12, 2025
b3ddaea8
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Feb 12, 2025
bda79b63
Update golangci/golangci-lint Docker tag to v1.64.3
Feb 12, 2025
38e64712
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Feb 12, 2025
4431cd05
Add `service_desk_reply_to` field support to Issues
Feb 12, 2025
663c286a
Merge branch 'patch-1' into 'main'
Feb 12, 2025
cd7ca291
Update golangci/golangci-lint Docker tag to v1.64.4
Feb 12, 2025
b5ce1ce1
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Feb 13, 2025
1af12fa6
Add member_role_id to group share
Feb 13, 2025
f85e69ef
Merge branch 'add-member-role-id-to-group-share' into 'main'
Feb 13, 2025
4365270e
Update go test matrix to include v1.24
Feb 13, 2025
9ce8bfc4
Merge branch 'renovate/go-1.x' into 'main'
Feb 13, 2025
5d94f1ad
Update golangci/golangci-lint Docker tag to v1.64.5
Feb 13, 2025
8f066ed1
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Feb 14, 2025
94295605
Add support for expires_at attribute in GroupsService.RotateServiceAccountPersonalAccessToken()
Feb 14, 2025
410a46ab
Merge branch 'pguinoiseau/group-service-account-rotate-expires-at' into 'main'
Feb 14, 2025
b7bbb632
add usage_type to ssh key creation
Feb 14, 2025
2dd6c081
Merge branch 'faleksic-ssh-key-add-usage-type' into 'main'
Feb 14, 2025
8d889d6a
Update alpine Docker tag to v3.21.3
Feb 14, 2025
07f0db35
Tidy group service accounts, add missing field, add tests
Feb 15, 2025
968d6614
Merge branch 'renovate/alpine-3.x' into 'main'
Feb 18, 2025
5c0427da
Merge branch 'tidy-group-serviceaccounts' into 'main'
Feb 18, 2025
380a7809
Update Group Hooks to add missing options and fix documentation links
Feb 18, 2025
7119f047
Merge branch 'tidy-group-hooks' into 'main'
Feb 18, 2025
28261806
Add support for project security settings API
Feb 18, 2025
89e6601b
Merge branch 'add-project-security-settings' into 'main'
Feb 18, 2025
5f831172
Add support for Group SCIM API
Feb 19, 2025
ce4e4694
Merge branch 'add-group-scim-support' into 'main'
Feb 19, 2025
d8c8e9f6
Add email to options when creating a service account
Feb 19, 2025
d66c2ea0
Merge branch 'add-email-create-service-account' into 'main'
Feb 20, 2025
82645d9d
Add 'username' support to AddProjectMemberOptions
Feb 20, 2025
c3a4f81a
Merge branch 'add-username-to-projectmembers' into 'main'
Feb 20, 2025
bb10e8c6
Add description to project access token APIs
Feb 21, 2025
5e04d292
Merge branch 'add-desc-project-access-token' into 'main'
Feb 21, 2025
23a6b28a
Add description to group access token APIs
Feb 21, 2025
fbdba17e
Merge branch 'add-desc-group-access-token' into 'main'
Feb 21, 2025
390a3cac
Add description to personal access token APIs
Feb 21, 2025
e7de28c2
Merge branch 'add-desc-personal-access-token' into 'main'
Feb 21, 2025
4c519f88
Add support for group releases API
Feb 21, 2025
3bcfffd3
Merge branch 'add-group-releases' into 'main'
Feb 21, 2025
72e52c99
Add filter to group variables update and delete
Feb 24, 2025
6430f4d3
Merge branch 'add-filter-to-group-variables' into 'main'
Feb 24, 2025
ece925e6
add ci_delete_pipelines_in_seconds to project edit and read
Feb 24, 2025
fb194e2a
Merge branch 'add-pipeline-retention' into 'main'
Feb 24, 2025
761f7de0
Add state option when listing project access tokens. This requires that...
Feb 24, 2025
bc06e6b2
Merge branch 'add-state-list-project-tokens' into 'main'
Feb 24, 2025
601d75bc
Add support for Secure Files API
Feb 25, 2025
f96af117
Merge branch 'add-secure-files-support' into 'main'
Feb 25, 2025
a17c2255
Fix return value of CreateMergeRequestDependency to return a single...
Feb 26, 2025
aef9e4f4
Merge branch 'feature/fix-create-mergerequest-dependency' into 'main'
Feb 26, 2025
27f52bd1
Add `Internal` support to `CreateIssueNoteOptions`
Feb 27, 2025
014b31cb
Merge branch 'notes_internal_field' into 'main'
Feb 27, 2025
c103a6b8
Add internal flag when creating different types of notes. Update documentation...
Feb 27, 2025
5ea65c57
Merge branch 'create-internal-notes' into 'main'
Feb 27, 2025
bf2d5c0f
Add function for uploading a wiki attachment
Feb 28, 2025
3d91c3aa
Merge branch 'add-wiki-attachment-uploads' into 'main'
Feb 28, 2025
fd06b55d
Add bundled reviewable command for ease of local development
Feb 28, 2025
34a11062
Merge branch 'add-reviewable-command' into 'main'
Feb 28, 2025
42ec248d
Switch to using BasicMergeRequest for API endpoints that use it
Feb 28, 2025
8b50e969
Merge branch 'use-basic-merge-request' into 'main'
Feb 28, 2025
6d63332b
Add support for instance member roles API, and align `CreateMemberRoleOptions`...
Feb 28, 2025
1be34651
Merge branch 'support-instance-custom-roles' into 'main'
Feb 28, 2025
65524df6
Refactor ShareWithGroup as a Named Struct instead of an Anonymous Struct
Feb 28, 2025
04cfd773
Merge branch 'named-struct-for-shared-with-group' into 'main'
Feb 28, 2025
dba06363
go: Update module golang.org/x/time to v0.10.0
Mar 01, 2025
dd6617b5
Merge branch 'renovate/golang.org-x-time-0.x' into 'main'
Mar 02, 2025
b26b2882
Update golangci/golangci-lint Docker tag to v1.64.6
Mar 03, 2025
72e86a21
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Mar 03, 2025
165fd77a
Add support for merge request approval settings API
Mar 03, 2025
2dd18a8f
Merge branch 'add-merge-request-approval-settings' into 'main'
Mar 03, 2025
0e325d63
Update access tokens to use alias type to reduce duplication
Mar 04, 2025
af734e5a
Merge branch 'update-access-tokens-to-reduce-duplication' into 'main'
Mar 04, 2025
6b1baf78
Fix pipeline for arbitrary fork location without Ultimate access
Mar 05, 2025
825735e3
Merge branch 'hosted-runner-cond' into 'main'
Mar 05, 2025
e34f2c78
feat: Add support for list shared projects group API
Mar 06, 2025
aaf68e99
Merge branch 'add-group-projects-shared' into 'main'
Mar 06, 2025
2632817f
add `ci_id_token_sub_claim_components` to EditProjectOptions
Mar 07, 2025
0be9bd1d
Merge branch 'main' into 'main'
Mar 07, 2025
a7434e79
Add support for `Usernames` in project-level MR approval rules
Mar 07, 2025
30f5bfd5
Merge branch 'feature/usernames-project-level-rules' into 'main'
Mar 07, 2025
0297e100
Add new user filter options: Humans, ExcludeActive and ExcludeHumans
Mar 10, 2025
7889c7ab
Merge branch '2103-extend-list-users-options' into 'main'
Mar 10, 2025
4f1442ef
Add function for configuring a project pull mirror
Mar 10, 2025
36bf45f5
Merge branch 'add-pull-mirror-configure' into 'main'
Mar 10, 2025
27ce4cb8
Add custom role support to LDAP links
Mar 11, 2025
58f1fb67
Merge branch 'custom-roles-for-ldap' into 'main'
Mar 11, 2025
8b74606a
Add `GetProjectMirrorPublicKey`, and add support for `auth_method` to `ProjectMirror`
Mar 11, 2025
3747ea3b
Merge branch 'feat/add-auth-method-to-project-mirror' into 'main'
Mar 11, 2025
42600718
Update golangci/golangci-lint Docker tag to v1.64.7
Mar 12, 2025
12d04e31
Merge branch 'renovate/golangci-golangci-lint-1.x' into 'main'
Mar 11, 2025
8b7fe39f
Add function for deleting a user's identity
Mar 12, 2025
670088b9
Merge branch 'add-delete-user-identity' into 'main'
Mar 12, 2025
ca468226
Implement testing package for gomock based tests
Mar 14, 2025
Show whitespace changes
Inline
Side-by-side
.devcontainer/devcontainer.json
View file @
3619f443
...
...
@@ -10,7 +10,7 @@
"features"
:
{
"ghcr.io/devcontainers/features/docker-in-docker:2"
:
{},
"ghcr.io/devcontainers/features/go:1"
:
{
"version"
:
"1.2
2.10
"
"version"
:
"1.2
3
"
}
},
//
Extensions
for
VSCode
...
...
.gitignore
View file @
3619f443
...
...
@@ -31,3 +31,8 @@ _testmain.go
# vendor
vendor
.go/
.golangci-lint/
# reports
gl-code-quality-report.json
\ No newline at end of file
.gitlab-ci.yml
View file @
3619f443
...
...
@@ -6,11 +6,25 @@ workflow:
-
if
:
$CI_COMMIT_REF_PROTECTED == "true"
include
:
-
template
:
Jobs/SAST.gitlab-ci.yml
-
component
:
${CI_SERVER_FQDN}/gitlab-org/components/danger-review/danger-review@2.0.0
inputs
:
job_stage
:
lint
job_allow_failure
:
true
# NOTE: the two includes below are a hack to conditionally set the tags node
# on our Go jobs. We want to use the large Ultimate runners if possible,
# which is what we have available in the gitlab-org and gitlab-community (Community Forks)
# groups. However, there is no easy way to conditionally set tags or even variables without
# jeopardizing existing (complex) workflow:rules or job:rules. Thus, we resort to
# this nasty conditionally include hack.
-
local
:
'
.gitlab/ci/gitlab-go-runner-tags.gitlab-ci.yml'
rules
:
-
if
:
$CI_PROJECT_ROOT_NAMESPACE == 'gitlab-org' || $CI_PROJECT_ROOT_NAMESPACE == 'gitlab-community'
-
local
:
'
.gitlab/ci/community-go-runner-tags.gitlab-ci.yml'
rules
:
-
if
:
$CI_PROJECT_ROOT_NAMESPACE != 'gitlab-org' && $CI_PROJECT_ROOT_NAMESPACE != 'gitlab-community'
stages
:
-
lint
-
test
...
...
@@ -20,16 +34,19 @@ stages:
parallel
:
matrix
:
-
GOLANG_IMAGE_VERSION
:
-
'
1.2
2.10
'
-
'
1.2
3.
4'
-
'
1.2
3
'
-
'
1.24'
.go:base
:
# From: https://docs.gitlab.com/ee/ci/caching/#cache-go-dependencies
extends
:
-
.go:runner-tags
# From: https://docs.gitlab.com/ci/caching/#cache-go-dependencies
variables
:
GOPATH
:
$CI_PROJECT_DIR/.go
GOLANGCI_LINT_CACHE
:
$CI_PROJECT_DIR/.golangci-lint
before_script
:
-
mkdir -p "${GOPATH}" "${GOLANGCI_LINT_CACHE}"
-
export PATH="${GOPATH}/bin:$PATH"
cache
:
paths
:
-
$GOPATH/pkg/mod/
...
...
@@ -37,14 +54,6 @@ stages:
key
:
files
:
-
go.sum
# We want to speed up CI a bit.
# Community contributors are recommended to use the Community fork
# which has access to this runners.
# For other forks to free tier namespaces this might fail,
# which is a good reminder to use the Community fork and not
# to accidentally burn to personal compute minutes.
tags
:
-
saas-linux-large-amd64
# We only need to run Go-related jobs when actual Go files changed
# or when running either on the default branch or for a tag.
rules
:
...
...
@@ -56,6 +65,7 @@ stages:
-
go.mod
-
go.sum
-
.gitlab-ci.yml
-
.gitlab/ci/*.yml
golangci-lint
:
extends
:
...
...
@@ -64,15 +74,33 @@ golangci-lint:
needs
:
[]
variables
:
REPORT_FILENAME
:
'
gl-code-quality-report.json'
image
:
golangci/golangci-lint:v1.6
3.4
image
:
golangci/golangci-lint:v
2.
1.6
script
:
-
golangci-lint run
--print-issued-lines=false --out-format code-climate:$REPORT_FILENAME,line-number
-
golangci-lint run
artifacts
:
reports
:
codequality
:
$REPORT_FILENAME
paths
:
[
$REPORT_FILENAME
]
when
:
always
verify-generated-code
:
extends
:
-
.go:base
stage
:
lint
needs
:
[]
image
:
golang:1.24-bookworm
script
:
-
make generate
-
|
echo "Checking git status"
[ -z "$(git status --short)" ] || {
echo "Error: Files should have been generated:";
git status --short; echo "Diff:";
git --no-pager diff HEAD;
echo "Run \"make generate\" and try again";
exit 1;
}
tests:unit
:
extends
:
-
.go:base
...
...
@@ -91,6 +119,8 @@ tests:unit:
COVERPROFILE_XML_FILENAME
:
coverage.xml
script
:
-
go run gotest.tools/gotestsum@${GOTESTSUM_VERSION} --format=standard-quiet --junitfile=$JUNIT_FILENAME -- -race -coverprofile=$COVERPROFILE_FILENAME -covermode=atomic ./...
-
grep -v '_generated.go' "$COVERPROFILE_FILENAME" | grep -v '_mock.go' > "${COVERPROFILE_FILENAME}.tmp"
-
mv "${COVERPROFILE_FILENAME}.tmp" "$COVERPROFILE_FILENAME"
-
go run github.com/boumenot/gocover-cobertura@${GOCOVER_COBERTURA_VERSION} < $COVERPROFILE_FILENAME > $COVERPROFILE_XML_FILENAME
-
go tool cover -func $COVERPROFILE_FILENAME
coverage
:
'
/total:.+\(statements\).+\d+\.\d+/'
...
...
@@ -108,20 +138,41 @@ tests:unit:
generate-release-notes
:
stage
:
deploy
needs
:
[]
image
:
alpine:3.21.
2
image
:
alpine:3.21.
3
before_script
:
-
apk add --update jq curl git
variables
:
GIT_DEPTH
:
400
GIT_FETCH_EXTRA_FLAGS
:
'
--tags'
script
:
-
|
# Download upstream tags if running from a fork
if [ "${CI_MERGE_REQUEST_SOURCE_PROJECT_ID}" != "${CI_MERGE_REQUEST_PROJECT_ID}" ]; then
echo "This merge request has been created from a fork."
if [ "${CI_MERGE_REQUEST_SOURCE_PROJECT_ID}" = "${CI_PROJECT_ID}" ]; then
echo "The merge request pipeline runs in the source project. Downloading tags."
git fetch --depth="${GIT_DEPTH}" --tags "${CI_MERGE_REQUEST_PROJECT_URL}"
else
echo "The merge request pipeline runs in the target project. Not downloading tags."
fi
fi
-
|
# Determine version.
if [ -z "$CI_COMMIT_TAG" ]; then
last_stable_version_sha="$(git tag | grep -E '^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$' | sort -Vr | head -n1)"
version="${last_stable_version_sha}+${CI_COMMIT_SHA}"
version="$(git describe --tags --match 'v*')"
else
version="$CI_COMMIT_TAG"
fi
urlencoded_version="$(jq -rn --arg x "${version}" '$x|@uri')"
-
echo "Generating release notes for ${version} (urlencoded=${urlencoded_version}) ..."
-
'
curl
--fail-with-body
--header
"JOB-TOKEN:
$CI_JOB_TOKEN"
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/changelog?version=${urlencoded_version}"
|
jq
-r
.notes
>
release-notes.md'
echo "Generating release notes for ${version} (urlencoded=${urlencoded_version}) ..."
-
|
# If running in a merge request pipeline, generate the release notes using the target project.
PROJECT_ID="${CI_PROJECT_ID}"
if [ -n "${CI_MERGE_REQUEST_PROJECT_ID}" ]; then
PROJECT_ID="${CI_MERGE_REQUEST_PROJECT_ID}"
fi
-
url="https://gitlab.com/api/v4/projects/${PROJECT_ID}/repository/changelog?version=${urlencoded_version}"; echo "url=\"${url}\""
-
curl --fail-with-body "${url}" | jq -r .notes >release-notes.md
-
cat release-notes.md
artifacts
:
paths
:
...
...
@@ -144,3 +195,11 @@ release:
tag_message
:
'
Version
$CI_COMMIT_TAG'
name
:
'
$CI_COMMIT_TAG'
description
:
release-notes.md
# Update rules on SAST to ensure the jobs show up in the pipeline
# this prevents forks that don't have `ultimate` from skipping SAST scans
# since gitlab-advaced-sast replaces semgrep.
semgrep-sast
:
needs
:
[]
rules
:
-
when
:
always
.gitlab/CODEOWNERS
0 → 100644
View file @
3619f443
*
@timofurrer
@patrickrice
@fforster
.gitlab/changelog_config.yml
View file @
3619f443
# See https://docs.gitlab.com/
ee/
user/project/changelogs
.html
# For API see https://docs.gitlab.com/
ee/
api/repositories
.html
#add-changelog-data-to-a-changelog-file
# See https://docs.gitlab.com/user/project/changelogs
/
# For API see https://docs.gitlab.com/api/repositories
/
#add-changelog-data-to-a-changelog-file
tag_regex
:
'
^v(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<pre>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<meta>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
.gitlab/ci/community-go-runner-tags.gitlab-ci.yml
0 → 100644
View file @
3619f443
.go:runner-tags
:
tags
:
-
saas-linux-medium-amd64
.gitlab/ci/gitlab-go-runner-tags.gitlab-ci.yml
0 → 100644
View file @
3619f443
.go:runner-tags
:
tags
:
-
saas-linux-large-amd64
.golangci.yml
View file @
3619f443
# This file contains all available configuration options
# with their default values.
version
:
"
2"
# Options for analysis running
run
:
concurrency
:
4
timeout
:
10m
issues-exit-code
:
1
tests
:
true
# Output configuration options
output
:
formats
:
-
format
:
line-number
# All available settings of specific linters
linters-settings
:
misspell
:
locale
:
US
ignore-words
:
-
noteable
revive
:
enable-all-rules
:
false
rules
:
-
name
:
deep-exit
text
:
path
:
stdout
colors
:
false
print-issued-lines
:
false
code-climate
:
path
:
gl-code-quality-report.json
linters
:
enable
:
-
asciicheck
-
dogsled
-
errorlint
-
exportloopref
-
goconst
-
gosimple
-
govet
-
ineffassign
-
misspell
-
nakedret
-
nolintlint
-
revive
-
staticcheck
-
typecheck
-
unconvert
-
unused
-
whitespace
disable
:
-
errcheck
disable-all
:
false
fast
:
false
settings
:
misspell
:
locale
:
US
ignore-rules
:
-
noteable
revive
:
enable-all-rules
:
false
rules
:
-
name
:
deep-exit
issues
:
# List of regexps of issue texts to exclude.
exclude
:
-
"
^.*,
make
it
a
constant$"
exclusions
:
generated
:
lax
presets
:
-
comments
-
common-false-positives
-
legacy
-
std-error-handling
rules
:
-
path
:
(.+)\.go$
text
:
^.*, make it a constant$
paths
:
-
third_party$
-
builtin$
-
examples/*
issues
:
# Maximum issues count per one linter (set to 0 to disable)
max-issues-per-linter
:
0
# Maximum count of issues with the same text (set to 0 to disable)
max-same-issues
:
0
formatters
:
enable
:
-
gofumpt
exclusions
:
generated
:
lax
paths
:
-
third_party$
-
builtin$
-
examples$
.tool-versions
View file @
3619f443
golang 1.2
2.10
golang 1.2
3
CONTRIBUTING.md
View file @
3619f443
...
...
@@ -45,19 +45,14 @@ easier to find things.
### Setting up your local development environment to contribute
1.
[
Fork
](
https://gitlab.com/gitlab-org/api/client-go
)
, then clone the repository.
```
sh
git clone https://gitlab.com/<your-username>/client-go.git
# or via ssh
git clone git@gitlab.com:<your-username>/client-go.git
```
1.
Install dependencies:
```
sh
make setup
```
1.
Make your changes on your feature branch
1.
Run the
tests and
`gofumpt`
1.
Make your changes on your feature branch
in the community fork or your personal fork
1.
Run the
reviewable command, which tests, lints and formats the code:
```
sh
make
test
&&
make
fmt
make
reviewable
```
1.
Push your feature branch upstream
1.
Open up your merge request
Dangerfile
View file @
3619f443
require
'gitlab-dangerfiles'
# see https://docs.gitlab.com/
ee/
development/dangerbot
.html
#enable-danger-on-a-project
# see https://docs.gitlab.com/development/dangerbot
/
#enable-danger-on-a-project
# see https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles
Gitlab
::
Dangerfiles
.
for_project
(
self
)
do
|
dangerfiles
|
Gitlab
::
Dangerfiles
.
for_project
(
self
,
'gitlab-api-client-go'
)
do
|
dangerfiles
|
# Import all plugins from the gem
dangerfiles
.
import_plugins
# Import a defined set of danger rules
dangerfiles
.
import_dangerfiles
(
only:
%w[changelog metadata type_label z_add_labels z_retry_link]
)
dangerfiles
.
import_dangerfiles
(
only:
%w[
simple_roulette
changelog metadata type_label z_add_labels z_retry_link]
)
end
Makefile
View file @
3619f443
...
...
@@ -6,17 +6,36 @@ help: ## Display this help
##@ Development
fmt
:
##
Format code
@
gofumpt
-l
-w
.
reviewable
:
setup generate fmt lint test
##
Run before committing.
lint
:
##
Run linter
fmt
:
install-gofumpt
##
Format code
@
gofumpt
-l
-w
*
.go testing/
*
.go examples/
*
.go
lint
:
install-golangci-lint
##
Run linter
@
golangci-lint run
setup
:
##
Setup your local environment
.PHONY
:
setup
setup
:
install-golangci-lint install-gofumpt
##
Setup your local environment
go mod tidy
@
go
install
github.com/golangci/golangci-lint/cmd/golangci-lint@latest
install-golangci-lint
:
@
go
install
github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
install-gofumpt
:
@
go
install
mvdan.cc/gofumpt@latest
.PHONY
:
setup
.PHONY
:
generate
generate
:
install-gofumpt
##
Generate files
./scripts/generate_testing_client.sh
./scripts/generate_service_interface_map.sh
./scripts/generate_mock_api.sh
.PHONY
:
clean
clean
:
##
Remove generated files
rm
-f
\
testing/
*
_mock.go
\
testing/
*
_generated.go
\
*
_generated_test.go
test
:
##
Run tests
go
test
./...
-race
README.md
View file @
3619f443
...
...
@@ -2,6 +2,11 @@
A GitLab API client enabling Go programs to interact with GitLab in a simple and uniform way.
## Table of Contents
[[
_TOC_
]]
## Usage
```
go
...
...
@@ -89,6 +94,69 @@ func main() {
For complete usage of go-gitlab, see the full
[
package docs
](
https://godoc.org/gitlab.com/gitlab-org/api/client-go
)
.
## Installation
To install the library, use the following command:
```
go
go
get
gitlab
.
com
/
gitlab
-
org
/
api
/
client
-
go
```
## Testing
The
`client-go`
project comes with a
`testing`
package at
`gitlab.com/gitlab-org/api/client-go/testing`
which contains a
`TestClient`
with
[
gomock
](
https://github.com/uber-go/mock
)
mocks for the individual services.
You can use them like this:
```
go
func
Test_MyApp
(
t
*
testing
.
T
)
{
client
:=
testing
.
NewTestClient
(
t
)
// Setup expectations
client
.
MockClusterAgents
.
EXPECT
()
.
List
(
gomock
.
Any
(),
123
,
nil
)
.
Return
([]
*
gitlab
.
ClusterAgent
{{
ID
:
1
}},
nil
)
// Use the client in your test
// You'd probably call your own code here that gets the client injected.
// You can also retrieve a `gitlab.Client` object from `client.Client`.
agents
,
err
:=
client
.
ClusterAgents
.
List
(
ctx
,
123
,
nil
)
assert
.
NoError
(
t
,
err
)
assert
.
Len
(
t
,
agents
,
1
)
}
```
### I want to generate my own mocks
You can! You can set up your own
`TestClient`
with mocks pretty easily:
```
go
func
NewTestClient
(
t
*
testing
.
T
)
{
// generate your mocks or instantiate a fake or whatever you like
mockClusterAgentsService
:=
newMockClusterAgentsService
(
t
)
client
:=
&
gitlab
.
Client
{
ClusterAgents
:
mockClusterAgentsService
}
return
tc
}
```
The
`newMockClusterAgentsService`
must return a type that implements
`gitlab.ClusterAgentsInterface`
.
You can have a look at
[
`testing/client.go`
](
/testing.client.go
)
how it's implemented for
`gomock`
.
## Compatibility
The
`client-go`
package will maintain compatibility with the officially supported Go releases
at the time the package is released. According to the
[
Go Release Policy
](
https://go.dev/doc/devel/release#policy
)
,
that's currently the two last major Go releases.
This compatibility is reflected in the
`go`
directive of the
[
`go.mod`
](
/go.mod
)
file
and the unit test matrix in
[
`.gitlab-ci.yml`
](
/.gitlab-ci.yml
)
.
You may also use https://endoflife.date/go to quickly discover the supported Go versions.
## Contributing
Contributions are always welcome. For more information, check out the
...
...
access_requests.go
View file @
3619f443
...
...
@@ -22,10 +22,33 @@ import (
"time"
)
type
(
AccessRequestsServiceInterface
interface
{
ListProjectAccessRequests
(
pid
any
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
ListGroupAccessRequests
(
gid
any
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
RequestProjectAccess
(
pid
any
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
RequestGroupAccess
(
gid
any
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
ApproveProjectAccessRequest
(
pid
any
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
ApproveGroupAccessRequest
(
gid
any
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
DenyProjectAccessRequest
(
pid
any
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
DenyGroupAccessRequest
(
gid
any
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
}
// AccessRequestsService handles communication with the project/group
// access requests related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/api/access_requests/
AccessRequestsService
struct
{
client
*
Client
}
)
var
_
AccessRequestsServiceInterface
=
(
*
AccessRequestsService
)(
nil
)
// AccessRequest represents a access request for a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
// https://docs.gitlab.com/api/access_requests
/
type
AccessRequest
struct
{
ID
int
`json:"id"`
Username
string
`json:"username"`
...
...
@@ -36,27 +59,19 @@ type AccessRequest struct {
AccessLevel
AccessLevelValue
`json:"access_level"`
}
// AccessRequestsService handles communication with the project/group
// access requests related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/access_requests.html
type
AccessRequestsService
struct
{
client
*
Client
}
// ListAccessRequestsOptions represents the available
// ListProjectAccessRequests() or ListGroupAccessRequests() options.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#list-access-requests-for-a-group-or-project
// https://docs.gitlab.com/api/access_requests
/
#list-access-requests-for-a-group-or-project
type
ListAccessRequestsOptions
ListOptions
// ListProjectAccessRequests gets a list of access requests
// viewable by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#list-access-requests-for-a-group-or-project
func
(
s
*
AccessRequestsService
)
ListProjectAccessRequests
(
pid
interface
{}
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#list-access-requests-for-a-group-or-project
func
(
s
*
AccessRequestsService
)
ListProjectAccessRequests
(
pid
any
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -81,8 +96,8 @@ func (s *AccessRequestsService) ListProjectAccessRequests(pid interface{}, opt *
// viewable by the authenticated user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#list-access-requests-for-a-group-or-project
func
(
s
*
AccessRequestsService
)
ListGroupAccessRequests
(
gid
interface
{}
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#list-access-requests-for-a-group-or-project
func
(
s
*
AccessRequestsService
)
ListGroupAccessRequests
(
gid
any
,
opt
*
ListAccessRequestsOptions
,
options
...
RequestOptionFunc
)
([]
*
AccessRequest
,
*
Response
,
error
)
{
group
,
err
:=
parseID
(
gid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -107,8 +122,8 @@ func (s *AccessRequestsService) ListGroupAccessRequests(gid interface{}, opt *Li
// to a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#request-access-to-a-group-or-project
func
(
s
*
AccessRequestsService
)
RequestProjectAccess
(
pid
interface
{}
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#request-access-to-a-group-or-project
func
(
s
*
AccessRequestsService
)
RequestProjectAccess
(
pid
any
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -133,8 +148,8 @@ func (s *AccessRequestsService) RequestProjectAccess(pid interface{}, options ..
// to a group or project.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#request-access-to-a-group-or-project
func
(
s
*
AccessRequestsService
)
RequestGroupAccess
(
gid
interface
{}
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#request-access-to-a-group-or-project
func
(
s
*
AccessRequestsService
)
RequestGroupAccess
(
gid
any
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
group
,
err
:=
parseID
(
gid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -159,7 +174,7 @@ func (s *AccessRequestsService) RequestGroupAccess(gid interface{}, options ...R
// ApproveProjectAccessRequest() and ApproveGroupAccessRequest() options.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#approve-an-access-request
// https://docs.gitlab.com/api/access_requests
/
#approve-an-access-request
type
ApproveAccessRequestOptions
struct
{
AccessLevel
*
AccessLevelValue
`url:"access_level,omitempty" json:"access_level,omitempty"`
}
...
...
@@ -167,8 +182,8 @@ type ApproveAccessRequestOptions struct {
// ApproveProjectAccessRequest approves an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#approve-an-access-request
func
(
s
*
AccessRequestsService
)
ApproveProjectAccessRequest
(
pid
interface
{}
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#approve-an-access-request
func
(
s
*
AccessRequestsService
)
ApproveProjectAccessRequest
(
pid
any
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -192,8 +207,8 @@ func (s *AccessRequestsService) ApproveProjectAccessRequest(pid interface{}, use
// ApproveGroupAccessRequest approves an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#approve-an-access-request
func
(
s
*
AccessRequestsService
)
ApproveGroupAccessRequest
(
gid
interface
{}
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#approve-an-access-request
func
(
s
*
AccessRequestsService
)
ApproveGroupAccessRequest
(
gid
any
,
user
int
,
opt
*
ApproveAccessRequestOptions
,
options
...
RequestOptionFunc
)
(
*
AccessRequest
,
*
Response
,
error
)
{
group
,
err
:=
parseID
(
gid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
...
...
@@ -217,8 +232,8 @@ func (s *AccessRequestsService) ApproveGroupAccessRequest(gid interface{}, user
// DenyProjectAccessRequest denies an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#deny-an-access-request
func
(
s
*
AccessRequestsService
)
DenyProjectAccessRequest
(
pid
interface
{}
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#deny-an-access-request
func
(
s
*
AccessRequestsService
)
DenyProjectAccessRequest
(
pid
any
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -236,8 +251,8 @@ func (s *AccessRequestsService) DenyProjectAccessRequest(pid interface{}, user i
// DenyGroupAccessRequest denies an access request for the given user.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/access_requests
.html
#deny-an-access-request
func
(
s
*
AccessRequestsService
)
DenyGroupAccessRequest
(
gid
interface
{}
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
{
// https://docs.gitlab.com/api/access_requests
/
#deny-an-access-request
func
(
s
*
AccessRequestsService
)
DenyGroupAccessRequest
(
gid
any
,
user
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
{
group
,
err
:=
parseID
(
gid
)
if
err
!=
nil
{
return
nil
,
err
...
...
access_requests_test.go
View file @
3619f443
...
...
@@ -27,6 +27,7 @@ import (
)
func
TestListProjectAccessRequests
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/access_requests"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -71,28 +72,58 @@ func TestListProjectAccessRequests(t *testing.T) {
},
}
requests
,
resp
,
err
:=
client
.
AccessRequests
.
ListProjectAccessRequests
(
1
,
nil
)
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
assert
.
Equal
(
t
,
expected
,
requests
)
tests
:=
[]
struct
{
name
string
projectID
any
expectedErr
string
expectedRes
[]
*
AccessRequest
statusCode
int
}{
{
name
:
"Valid Project ID"
,
projectID
:
1
,
expectedErr
:
""
,
expectedRes
:
expected
,
statusCode
:
http
.
StatusOK
,
},
{
name
:
"Invalid Project ID Type"
,
projectID
:
1.5
,
expectedErr
:
"invalid ID type 1.5, the ID must be an int or a string"
,
expectedRes
:
nil
,
statusCode
:
0
,
},
{
name
:
"Non-Existent Project ID"
,
projectID
:
2
,
expectedErr
:
"404 Not Found"
,
expectedRes
:
nil
,
statusCode
:
http
.
StatusNotFound
,
},
}
requests
,
resp
,
err
=
client
.
AccessRequests
.
ListProjectAccessRequests
(
1.5
,
nil
)
assert
.
EqualError
(
t
,
err
,
"invalid ID type 1.5, the ID must be an int or a string"
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
requests
)
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
requests
,
resp
,
err
:=
client
.
AccessRequests
.
ListProjectAccessRequests
(
tt
.
projectID
,
nil
)
requests
,
resp
,
err
=
client
.
AccessRequests
.
ListProjectAccessRequests
(
2
,
nil
)
assert
.
Error
(
t
,
err
)
assert
.
Equal
(
t
,
http
.
StatusNotFound
,
resp
.
StatusCode
)
if
tt
.
expectedErr
!=
""
{
assert
.
EqualError
(
t
,
err
,
tt
.
expectedErr
)
assert
.
Nil
(
t
,
requests
)
}
else
{
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
assert
.
Equal
(
t
,
tt
.
expectedRes
,
requests
)
}
requests
,
resp
,
err
=
client
.
AccessRequests
.
ListProjectAccessRequests
(
1
,
nil
,
errorOption
)
assert
.
EqualError
(
t
,
err
,
"RequestOptionFunc returns an error"
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
requests
)
if
tt
.
statusCode
!=
0
&&
resp
!=
nil
{
assert
.
Equal
(
t
,
tt
.
statusCode
,
resp
.
StatusCode
)
}
})
}
}
func
TestListGroupAccessRequests
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/groups/1/access_requests"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -143,7 +174,7 @@ func TestListGroupAccessRequests(t *testing.T) {
assert
.
Equal
(
t
,
expected
,
requests
)
requests
,
resp
,
err
=
client
.
AccessRequests
.
ListGroupAccessRequests
(
1.5
,
nil
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
requests
)
...
...
@@ -159,6 +190,7 @@ func TestListGroupAccessRequests(t *testing.T) {
}
func
TestRequestProjectAccess
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/access_requests"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -189,7 +221,7 @@ func TestRequestProjectAccess(t *testing.T) {
assert
.
Equal
(
t
,
expected
,
accessRequest
)
accessRequest
,
resp
,
err
=
client
.
AccessRequests
.
RequestProjectAccess
(
1.5
,
nil
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
accessRequest
)
...
...
@@ -205,6 +237,7 @@ func TestRequestProjectAccess(t *testing.T) {
}
func
TestRequestGroupAccess
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/groups/1/access_requests"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -235,7 +268,7 @@ func TestRequestGroupAccess(t *testing.T) {
assert
.
Equal
(
t
,
expected
,
accessRequest
)
accessRequest
,
resp
,
err
=
client
.
AccessRequests
.
RequestGroupAccess
(
1.5
,
nil
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
accessRequest
)
...
...
@@ -251,6 +284,7 @@ func TestRequestGroupAccess(t *testing.T) {
}
func
TestApproveProjectAccessRequest
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/access_requests/10/approve"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -294,7 +328,7 @@ func TestApproveProjectAccessRequest(t *testing.T) {
assert
.
Equal
(
t
,
expected
,
request
)
request
,
resp
,
err
=
client
.
AccessRequests
.
ApproveProjectAccessRequest
(
1.5
,
10
,
opt
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
request
)
...
...
@@ -310,6 +344,7 @@ func TestApproveProjectAccessRequest(t *testing.T) {
}
func
TestApproveGroupAccessRequest
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/groups/1/access_requests/10/approve"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -353,7 +388,7 @@ func TestApproveGroupAccessRequest(t *testing.T) {
assert
.
Equal
(
t
,
expected
,
request
)
request
,
resp
,
err
=
client
.
AccessRequests
.
ApproveGroupAccessRequest
(
1.5
,
10
,
opt
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
assert
.
Nil
(
t
,
request
)
...
...
@@ -369,6 +404,7 @@ func TestApproveGroupAccessRequest(t *testing.T) {
}
func
TestDenyProjectAccessRequest
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/access_requests/10"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -380,7 +416,7 @@ func TestDenyProjectAccessRequest(t *testing.T) {
assert
.
NotNil
(
t
,
resp
)
resp
,
err
=
client
.
AccessRequests
.
DenyProjectAccessRequest
(
1.5
,
10
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
resp
,
err
=
client
.
AccessRequests
.
DenyProjectAccessRequest
(
2
,
10
)
...
...
@@ -393,6 +429,7 @@ func TestDenyProjectAccessRequest(t *testing.T) {
}
func
TestDenyGroupAccessRequest
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/groups/1/access_requests/10"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -404,7 +441,7 @@ func TestDenyGroupAccessRequest(t *testing.T) {
assert
.
NotNil
(
t
,
resp
)
resp
,
err
=
client
.
AccessRequests
.
DenyGroupAccessRequest
(
1.5
,
10
)
assert
.
Equal
Error
(
t
,
err
,
"i
nvalid
ID
t
ype
1.5, the ID must be an int or a string"
)
assert
.
Error
Is
(
t
,
err
,
ErrI
nvalidID
T
ype
)
assert
.
Nil
(
t
,
resp
)
resp
,
err
=
client
.
AccessRequests
.
DenyGroupAccessRequest
(
2
,
10
)
...
...
alert_management.go
0 → 100644
View file @
3619f443
//
// 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
gitlab
import
(
"fmt"
"io"
"net/http"
"time"
)
type
(
AlertManagementServiceInterface
interface
{
UploadMetricImage
(
pid
any
,
alertIID
int
,
content
io
.
Reader
,
filename
string
,
opt
*
UploadMetricImageOptions
,
options
...
RequestOptionFunc
)
(
*
MetricImage
,
*
Response
,
error
)
ListMetricImages
(
pid
any
,
alertIID
int
,
opt
*
ListMetricImagesOptions
,
options
...
RequestOptionFunc
)
([]
*
MetricImage
,
*
Response
,
error
)
UpdateMetricImage
(
pid
any
,
alertIID
int
,
id
int
,
opt
*
UpdateMetricImageOptions
,
options
...
RequestOptionFunc
)
(
*
MetricImage
,
*
Response
,
error
)
DeleteMetricImage
(
pid
any
,
alertIID
int
,
id
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
}
// AlertManagementService handles communication with the alert management
// related methods of the GitLab API.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/
AlertManagementService
struct
{
client
*
Client
}
)
var
_
AlertManagementServiceInterface
=
(
*
AlertManagementService
)(
nil
)
// MetricImage represents a single metric image file.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/
type
MetricImage
struct
{
ID
int
`json:"id"`
CreatedAt
*
time
.
Time
`json:"created_at"`
Filename
string
`json:"filename"`
FilePath
string
`json:"file_path"`
URL
string
`json:"url"`
URLText
string
`json:"url_text"`
}
// UploadMetricImageOptions represents the available UploadMetricImage() options.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#upload-metric-image
type
UploadMetricImageOptions
struct
{
URL
*
string
`url:"url,omitempty" json:"url,omitempty"`
URLText
*
string
`url:"url_text,omitempty" json:"url_text,omitempty"`
}
// UploadMetricImageOptions uploads a metric image to a project alert.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#upload-metric-image
func
(
s
*
AlertManagementService
)
UploadMetricImage
(
pid
any
,
alertIID
int
,
content
io
.
Reader
,
filename
string
,
opt
*
UploadMetricImageOptions
,
options
...
RequestOptionFunc
)
(
*
MetricImage
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
u
:=
fmt
.
Sprintf
(
"projects/%s/alert_management_alerts/%d/metric_images"
,
PathEscape
(
project
),
alertIID
)
req
,
err
:=
s
.
client
.
UploadRequest
(
http
.
MethodPost
,
u
,
content
,
filename
,
UploadFile
,
opt
,
options
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
mi
:=
new
(
MetricImage
)
resp
,
err
:=
s
.
client
.
Do
(
req
,
mi
)
if
err
!=
nil
{
return
nil
,
resp
,
err
}
return
mi
,
resp
,
nil
}
// ListMetricImagesOptions represents the available ListMetricImages() options.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#list-metric-images
type
ListMetricImagesOptions
struct
{
ListOptions
}
// ListMetricImages lists all the metric images for a project alert.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#list-metric-images
func
(
s
*
AlertManagementService
)
ListMetricImages
(
pid
any
,
alertIID
int
,
opt
*
ListMetricImagesOptions
,
options
...
RequestOptionFunc
)
([]
*
MetricImage
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
u
:=
fmt
.
Sprintf
(
"projects/%s/alert_management_alerts/%d/metric_images"
,
PathEscape
(
project
),
alertIID
)
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodGet
,
u
,
opt
,
options
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
var
mis
[]
*
MetricImage
resp
,
err
:=
s
.
client
.
Do
(
req
,
&
mis
)
if
err
!=
nil
{
return
nil
,
resp
,
err
}
return
mis
,
resp
,
nil
}
// UpdateMetricImageOptions represents the available UpdateMetricImage() options.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#update-metric-image
type
UpdateMetricImageOptions
struct
{
URL
*
string
`url:"url,omitempty" json:"url,omitempty"`
URLText
*
string
`url:"url_text,omitempty" json:"url_text,omitempty"`
}
// UpdateMetricImage updates a metric image for a project alert.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#update-metric-image
func
(
s
*
AlertManagementService
)
UpdateMetricImage
(
pid
any
,
alertIID
int
,
id
int
,
opt
*
UpdateMetricImageOptions
,
options
...
RequestOptionFunc
)
(
*
MetricImage
,
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
u
:=
fmt
.
Sprintf
(
"projects/%s/alert_management_alerts/%d/metric_images/%d"
,
PathEscape
(
project
),
alertIID
,
id
)
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodPut
,
u
,
opt
,
options
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
mi
:=
new
(
MetricImage
)
resp
,
err
:=
s
.
client
.
Do
(
req
,
mi
)
if
err
!=
nil
{
return
nil
,
resp
,
err
}
return
mi
,
resp
,
nil
}
// DeleteMetricImage deletes a metric image for a project alert.
//
// GitLab API docs:
// https://docs.gitlab.com/api/alert_management_alerts/#delete-metric-image
func
(
s
*
AlertManagementService
)
DeleteMetricImage
(
pid
any
,
alertIID
int
,
id
int
,
options
...
RequestOptionFunc
)
(
*
Response
,
error
)
{
project
,
err
:=
parseID
(
pid
)
if
err
!=
nil
{
return
nil
,
err
}
u
:=
fmt
.
Sprintf
(
"projects/%s/alert_management_alerts/%d/metric_images/%d"
,
PathEscape
(
project
),
alertIID
,
id
)
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodDelete
,
u
,
nil
,
options
)
if
err
!=
nil
{
return
nil
,
err
}
return
s
.
client
.
Do
(
req
,
nil
)
}
alert_management_test.go
0 → 100644
View file @
3619f443
package
gitlab
import
(
"fmt"
"net/http"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func
TestAlertManagement_UploadMetricImage
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/alert_management_alerts/2/metric_images"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
testMethod
(
t
,
r
,
http
.
MethodPost
)
fmt
.
Fprint
(
w
,
`
{
"id":17,
"created_at":"2020-11-12T20:07:58.000Z",
"filename":"sample_2054",
"file_path":"/uploads/-/system/alert_metric_image/file/17/sample_2054.png",
"url":"https://example.com/metric",
"url_text":"An example metric"
}
`
)
})
createdAt
:=
time
.
Date
(
2020
,
11
,
12
,
20
,
7
,
58
,
0
,
time
.
UTC
)
want
:=
&
MetricImage
{
ID
:
17
,
CreatedAt
:
&
createdAt
,
Filename
:
"sample_2054"
,
FilePath
:
"/uploads/-/system/alert_metric_image/file/17/sample_2054.png"
,
URL
:
"https://example.com/metric"
,
URLText
:
"An example metric"
,
}
metricImage
,
resp
,
err
:=
client
.
AlertManagement
.
UploadMetricImage
(
1
,
2
,
strings
.
NewReader
(
"image"
),
"sample_2054"
,
&
UploadMetricImageOptions
{
URL
:
Ptr
(
"https://example.com/metric"
),
URLText
:
Ptr
(
"An example metric"
),
})
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
assert
.
Equal
(
t
,
want
,
metricImage
)
}
func
TestAlertManagement_ListMetricImages
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/alert_management_alerts/2/metric_images"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
testMethod
(
t
,
r
,
http
.
MethodGet
)
fmt
.
Fprint
(
w
,
`
[
{
"id":17,
"created_at":"2020-11-12T20:07:58.000Z",
"filename":"sample_2054",
"file_path":"/uploads/-/system/alert_metric_image/file/17/sample_2054.png",
"url":"https://example.com/metric",
"url_text":"An example metric"
},
{
"id":18,
"created_at":"2020-11-12T20:07:58.000Z",
"filename":"sample_2054",
"file_path":"/uploads/-/system/alert_metric_image/file/18/sample_2054.png",
"url":"https://example.com/metric",
"url_text":"An example metric"
}
]
`
)
})
createdAt
:=
time
.
Date
(
2020
,
11
,
12
,
20
,
7
,
58
,
0
,
time
.
UTC
)
want
:=
[]
*
MetricImage
{
{
ID
:
17
,
CreatedAt
:
&
createdAt
,
Filename
:
"sample_2054"
,
FilePath
:
"/uploads/-/system/alert_metric_image/file/17/sample_2054.png"
,
URL
:
"https://example.com/metric"
,
URLText
:
"An example metric"
,
},
{
ID
:
18
,
CreatedAt
:
&
createdAt
,
Filename
:
"sample_2054"
,
FilePath
:
"/uploads/-/system/alert_metric_image/file/18/sample_2054.png"
,
URL
:
"https://example.com/metric"
,
URLText
:
"An example metric"
,
},
}
metricImages
,
resp
,
err
:=
client
.
AlertManagement
.
ListMetricImages
(
1
,
2
,
nil
)
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
assert
.
Equal
(
t
,
want
,
metricImages
)
}
func
TestAlertManagement_UpdateMetricImage
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/alert_management_alerts/2/metric_images/17"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
testMethod
(
t
,
r
,
http
.
MethodPut
)
fmt
.
Fprint
(
w
,
`
{
"id":17,
"created_at":"2020-11-12T20:07:58.000Z",
"filename":"sample_2054",
"file_path":"/uploads/-/system/alert_metric_image/file/17/sample_2054.png",
"url":"https://example.com/metric",
"url_text":"An example metric"
}
`
)
})
createdAt
:=
time
.
Date
(
2020
,
11
,
12
,
20
,
7
,
58
,
0
,
time
.
UTC
)
want
:=
&
MetricImage
{
ID
:
17
,
CreatedAt
:
&
createdAt
,
Filename
:
"sample_2054"
,
FilePath
:
"/uploads/-/system/alert_metric_image/file/17/sample_2054.png"
,
URL
:
"https://example.com/metric"
,
URLText
:
"An example metric"
,
}
metricImage
,
resp
,
err
:=
client
.
AlertManagement
.
UpdateMetricImage
(
1
,
2
,
17
,
&
UpdateMetricImageOptions
{
URL
:
Ptr
(
"https://example.com/metric"
),
URLText
:
Ptr
(
"An example metric"
),
})
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
assert
.
Equal
(
t
,
want
,
metricImage
)
}
func
TestAlertManagement_DeleteMetricImage
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/projects/1/alert_management_alerts/2/metric_images/17"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
testMethod
(
t
,
r
,
http
.
MethodDelete
)
})
resp
,
err
:=
client
.
AlertManagement
.
DeleteMetricImage
(
1
,
2
,
17
)
assert
.
NoError
(
t
,
err
)
assert
.
NotNil
(
t
,
resp
)
}
appearance.go
View file @
3619f443
...
...
@@ -18,16 +18,25 @@ package gitlab
import
"net/http"
type
(
AppearanceServiceInterface
interface
{
GetAppearance
(
options
...
RequestOptionFunc
)
(
*
Appearance
,
*
Response
,
error
)
ChangeAppearance
(
opt
*
ChangeAppearanceOptions
,
options
...
RequestOptionFunc
)
(
*
Appearance
,
*
Response
,
error
)
}
// AppearanceService handles communication with appearance of the Gitlab API.
//
// Gitlab API docs
: https://docs.gitlab.com/
ee/
api/appearance
.html
type
AppearanceService
struct
{
// Gitlab API docs: https://docs.gitlab.com/api/appearance
/
AppearanceService
struct
{
client
*
Client
}
)
var
_
AppearanceServiceInterface
=
(
*
AppearanceService
)(
nil
)
// Appearance represents a GitLab appearance.
//
// Gitlab API docs
: https://docs.gitlab.com/
ee/
api/appearance
.html
// Gitlab API docs: https://docs.gitlab.com/api/appearance
/
type
Appearance
struct
{
Title
string
`json:"title"`
Description
string
`json:"description"`
...
...
@@ -51,7 +60,7 @@ type Appearance struct {
// GetAppearance gets the current appearance configuration of the GitLab instance.
//
// Gitlab API docs:
// https://docs.gitlab.com/
ee/
api/appearance
.html#get-current-appearance-configuration
// https://docs.gitlab.com/api/appearance
/#get-details-on-current-application-appearance
func
(
s
*
AppearanceService
)
GetAppearance
(
options
...
RequestOptionFunc
)
(
*
Appearance
,
*
Response
,
error
)
{
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodGet
,
"application/appearance"
,
nil
,
options
)
if
err
!=
nil
{
...
...
@@ -70,7 +79,7 @@ func (s *AppearanceService) GetAppearance(options ...RequestOptionFunc) (*Appear
// ChangeAppearanceOptions represents the available ChangeAppearance() options.
//
// GitLab API docs:
// https://docs.gitlab.com/
ee/
api/appearance
.html#change-appearance-configuration
// https://docs.gitlab.com/api/appearance
/#update-application-appearance
type
ChangeAppearanceOptions
struct
{
Title
*
string
`url:"title,omitempty" json:"title,omitempty"`
Description
*
string
`url:"description,omitempty" json:"description,omitempty"`
...
...
@@ -95,7 +104,7 @@ type ChangeAppearanceOptions struct {
// ChangeAppearance changes the appearance configuration.
//
// Gitlab API docs:
// https://docs.gitlab.com/
ee/
api/appearance
.html#change-appearance-configuration
// https://docs.gitlab.com/api/appearance
/#update-application-appearance
func
(
s
*
AppearanceService
)
ChangeAppearance
(
opt
*
ChangeAppearanceOptions
,
options
...
RequestOptionFunc
)
(
*
Appearance
,
*
Response
,
error
)
{
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodPut
,
"application/appearance"
,
opt
,
options
)
if
err
!=
nil
{
...
...
appearance_test.go
View file @
3619f443
...
...
@@ -24,6 +24,7 @@ import (
)
func
TestGetAppearance
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/application/appearance"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
@@ -80,6 +81,7 @@ func TestGetAppearance(t *testing.T) {
}
func
TestChangeAppearance
(
t
*
testing
.
T
)
{
t
.
Parallel
()
mux
,
client
:=
setup
(
t
)
mux
.
HandleFunc
(
"/api/v4/application/appearance"
,
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
...
application_statistics.go
0 → 100644
View file @
3619f443
//
// 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
gitlab
import
"net/http"
type
(
ApplicationStatisticsServiceInterface
interface
{
GetApplicationStatistics
(
options
...
RequestOptionFunc
)
(
*
ApplicationStatistics
,
*
Response
,
error
)
}
// ApplicationStatisticsService handles communication with the application
// statistics related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/api/statistics/
ApplicationStatisticsService
struct
{
client
*
Client
}
)
var
_
ApplicationStatisticsServiceInterface
=
(
*
ApplicationStatisticsService
)(
nil
)
// ApplicationStatistics represents application statistics.
//
// GitLab API docs: https://docs.gitlab.com/api/statistics/
type
ApplicationStatistics
struct
{
Forks
int
`url:"forks" json:"forks"`
Issues
int
`url:"issues" json:"issues"`
MergeRequests
int
`url:"merge_requests" json:"merge_requests"`
Notes
int
`url:"notes" json:"notes"`
Snippets
int
`url:"snippets" json:"snippets"`
SSHKeys
int
`url:"ssh_keys" json:"ssh_keys"`
Milestones
int
`url:"milestones" json:"milestones"`
Users
int
`url:"users" json:"users"`
Groups
int
`url:"groups" json:"groups"`
Projects
int
`url:"projects" json:"projects"`
ActiveUsers
int
`url:"active_users" json:"active_users"`
}
// GetApplicationStatistics gets details on the current application statistics.
//
// GitLab API docs:
// https://docs.gitlab.com/api/statistics/#get-details-on-current-application-statistics
func
(
s
*
ApplicationStatisticsService
)
GetApplicationStatistics
(
options
...
RequestOptionFunc
)
(
*
ApplicationStatistics
,
*
Response
,
error
)
{
req
,
err
:=
s
.
client
.
NewRequest
(
http
.
MethodGet
,
"application/statistics"
,
nil
,
options
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
statistics
:=
new
(
ApplicationStatistics
)
resp
,
err
:=
s
.
client
.
Do
(
req
,
statistics
)
if
err
!=
nil
{
return
nil
,
resp
,
err
}
return
statistics
,
resp
,
nil
}
Prev
1
2
3
4
5
…
26
Next