diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 000000000..6c62f5449 --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,13 @@ +image: gitpod/workspace-go +tasks: + - init: go get + - name: Start acceptance Test Environment + command: make testacc-up + openMode: split-right +# Port 8080 is used for acceptance testing, and we don't need to open it when the container comes up +ports: + - port: 8080 + onOpen: ignore +vscode: + extensions: + - golang.Go \ No newline at end of file diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 000000000..55c7fc5da --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,34 @@ +default: test + +GOBIN = $(shell pwd)/bin + +test: ## Run unit tests. + go test -v ./... + +fmt: tool-golangci-lint ## Format files and fix issues. + gofmt -w -s . + $(GOBIN)/golangci-lint run --fix + +lint-golangci: tool-golangci-lint ## Run golangci-lint linter (same as fmt but without modifying files). + $(GOBIN)/golangci-lint run + +SERVICE ?= gitlab-ce +GITLAB_TOKEN ?= ACCTEST1234567890123 +GITLAB_BASE_URL ?= http://127.0.0.1:8080/api/v4 + +testacc-up: ## Launch a GitLab instance. + docker-compose up -d $(SERVICE) + ./scripts/await-healthy.sh + +testacc-down: ## Teardown a GitLab instance. + docker-compose down + +# TOOLS +# Tool dependencies are installed into a project-local /bin folder. + +tool-golangci-lint: + @$(call install-tool, github.com/golangci/golangci-lint/cmd/golangci-lint) + +define install-tool + cd tools && GOBIN=$(GOBIN) go install $(1) +endef diff --git a/README.md b/README.md index 19f6ad2a6..92acc447a 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,47 @@ to add new and/or missing endpoints. Currently, the following services are suppo - [x] Version - [x] Wikis +## Development + +### Use a Remote Environment via GitPod + +You can choose to use your own development environment if desired, however a `.gitpod.yml` file is included within the repository to allow the use of [GitPod](https://gitpod.io/) easily. +This will allow you to use GitPod's integration with GitHub to quickly start a web-based development environment including Go and Docker, which are necessary +for running tests. To use GitPod's integration, you have two different options described below. After you've completed one of the two options, your development environment +will be ready within a minute or two. As part of starting up, your development environment will automatically start up the `gitlab-ce` container necessary for running +tests. + +#### Option 1: Manually navigate to GitPod + +You can manually sign in and open your workspace within GitPod by following these steps: + +1. Navigate to [GitPod](https://gitpod.io/) +1. Click [Login](https://gitpod.io/login/) if you have an account, or [Sign Up](https://www.gitpod.io/#get-started) if you do not. +1. Click on "Continue with GitHub" and authorize GitPod to access your account. +1. After you've signed in, select "Projects" along the top menu, click on your forked `go-gitlab` project +1. Hover over either the main branch for your fork or the branch you created for your fork, and click "New Workspace" + +#### Option 2: Open your GitPod Workspace directly via URL + +1. Navigate to your fork of the `go-gitlab` project in GitHub +1. Select the branch you want to develop +1. Add `https://gitpod.io/#` to the front of your URL + +Your workspace will automatically open the repository and branch that you selected in GitHub. + +### Testing individual go-gitlab services with GitPods + +Once a GitPod has started up with the gitlab-ce container service running, port 8080 will be exposed for API calls where each individual go-gitlab service can be tested against. Please note that the `ce` container service is started by default and to test any `ee` go-gitlab service you will need to have a valid license file provided in the top level directory named `Gitlab-license.txt`. Then modify the `GNUmakefile` to set the `SERVICE` variable to `gitlab-ee` instead of `gitlab-ce`. Once these modifications are done run `make testacc-down` to stop the current ce container service and then run `make testacc-up` to start the new ee container service + +- Connection Information + - PAT/API Token: `ACCTEST1234567890123` + - API URL: `http://127.0.0.1:8080/api/v4/` + +1. Create a dummy testing file (something.go, main.go, etc.) where you will be testing the services you are developing +2. Follow the format of one of the services under the examples folder +3. Set the connection information to the above for the GitLab client +4. On the terminal enter `go run ` to run the test file that was created against the local gitlab container service + ## Usage ```go @@ -142,41 +183,41 @@ contains a couple for clear examples, of which one is partially listed here as w package main import ( - "log" + "log" - "github.com/xanzy/go-gitlab" + "github.com/xanzy/go-gitlab" ) func main() { - git, err := gitlab.NewClient("yourtokengoeshere") - if err != nil { - log.Fatalf("Failed to create client: %v", err) - } - - // Create new project - p := &gitlab.CreateProjectOptions{ - Name: gitlab.String("My Project"), - Description: gitlab.String("Just a test project to play with"), - MergeRequestsEnabled: gitlab.Bool(true), - SnippetsEnabled: gitlab.Bool(true), - Visibility: gitlab.Visibility(gitlab.PublicVisibility), - } - project, _, err := git.Projects.CreateProject(p) - if err != nil { - log.Fatal(err) - } - - // Add a new snippet - s := &gitlab.CreateProjectSnippetOptions{ - Title: gitlab.String("Dummy Snippet"), - FileName: gitlab.String("snippet.go"), - Content: gitlab.String("package main...."), - Visibility: gitlab.Visibility(gitlab.PublicVisibility), - } - _, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s) - if err != nil { - log.Fatal(err) - } + git, err := gitlab.NewClient("yourtokengoeshere") + if err != nil { + log.Fatalf("Failed to create client: %v", err) + } + + // Create new project + p := &gitlab.CreateProjectOptions{ + Name: gitlab.String("My Project"), + Description: gitlab.String("Just a test project to play with"), + MergeRequestsEnabled: gitlab.Bool(true), + SnippetsEnabled: gitlab.Bool(true), + Visibility: gitlab.Visibility(gitlab.PublicVisibility), + } + project, _, err := git.Projects.CreateProject(p) + if err != nil { + log.Fatal(err) + } + + // Add a new snippet + s := &gitlab.CreateProjectSnippetOptions{ + Title: gitlab.String("Dummy Snippet"), + FileName: gitlab.String("snippet.go"), + Content: gitlab.String("package main...."), + Visibility: gitlab.Visibility(gitlab.PublicVisibility), + } + _, _, err = git.ProjectSnippets.CreateSnippet(project.ID, s) + if err != nil { + log.Fatal(err) + } } ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..3755c70a9 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,53 @@ +version: '3' + +# Functional tests depend on a running GitLab instance. +# Only one of these services should be run at a time. +services: + gitlab-ce: + image: gitlab/gitlab-ce + restart: always + ports: + - 8080:80 + environment: + GITLAB_ROOT_PASSWORD: adminadmin + labels: + go-gitlab: '' + volumes: + - config-ce:/etc/gitlab + - logs-ce:/var/log/gitlab + - data-ce:/var/opt/gitlab + - ${PWD}/scripts/healthcheck-and-setup.sh:/healthcheck-and-setup.sh:Z + healthcheck: + test: /healthcheck-and-setup.sh + interval: 10s + timeout: 2m + +# Valid license file must be provided in order to utilize this service + gitlab-ee: + image: gitlab/gitlab-ee + restart: always + ports: + - 8080:80 + environment: + GITLAB_ROOT_PASSWORD: adminadmin + GITLAB_LICENSE_FILE: /Gitlab-license.txt + labels: + go-gitlab: '' + volumes: + - config-ee:/etc/gitlab + - logs-ee:/var/log/gitlab + - data-ee:/var/opt/gitlab + - ${PWD}/scripts/healthcheck-and-setup.sh:/healthcheck-and-setup.sh:Z + - ${PWD}/Gitlab-license.txt:/Gitlab-license.txt:Z + healthcheck: + test: /healthcheck-and-setup.sh + interval: 10s + timeout: 2m + +volumes: + config-ce: + logs-ce: + data-ce: + config-ee: + logs-ee: + data-ee: diff --git a/scripts/await-healthy.sh b/scripts/await-healthy.sh new file mode 100755 index 000000000..56f911d2f --- /dev/null +++ b/scripts/await-healthy.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +printf 'Waiting for GitLab container to become healthy' + +until test -n "$(docker ps --quiet --filter label=go-gitlab --filter health=healthy)"; do + printf '.' + sleep 5 +done + +echo +echo 'GitLab is healthy' + +# Print the version, since it is useful debugging information. +curl --silent --show-error --header 'Authorization: Bearer ACCTEST1234567890123' http://127.0.0.1:8080/api/v4/version +echo diff --git a/scripts/healthcheck-and-setup.sh b/scripts/healthcheck-and-setup.sh new file mode 100755 index 000000000..cbdb7385a --- /dev/null +++ b/scripts/healthcheck-and-setup.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env sh + +# This script is intended to be used as a Docker HEALTHCHECK for the GitLab container. +# It prepares GitLab prior to running acceptance tests. +# +# This is a known workaround for docker-compose lacking lifecycle hooks. +# See: https://github.com/docker/compose/issues/1809#issuecomment-657815188 + +set -e + +# Check for a successful HTTP status code from GitLab. +curl --silent --show-error --fail --output /dev/null 127.0.0.1:80 + +# Because this script runs on a regular health check interval, +# this file functions as a marker that tells us if initialization already finished. +done=/var/gitlab-acctest-initialized + +test -f $done || { + echo 'Initializing GitLab for acceptance tests' + + echo 'Creating access token' + ( + printf 'go_gitlab_token = PersonalAccessToken.create(' + printf 'user_id: 1, ' + printf 'scopes: [:api, :read_user], ' + printf 'name: :go-gitlab);' + printf "go_gitlab_token.set_token('ACCTEST1234567890123');" + printf 'go_gitlab_token.save!;' + ) | gitlab-rails console + + echo 'Creating an instance level template group with a simple template based on rails' + ( + printf 'group_template = Group.new(' + printf 'name: :go-gitlab, ' + printf 'path: :go-gitlab);' + printf 'group_template.save!;' + printf 'application_settings = ApplicationSetting.find_by "";' + printf 'application_settings.custom_project_templates_group_id = group_template.id;' + printf 'application_settings.save!;' + printf 'attrs = {' + printf 'name: :myrails, ' + printf 'path: :myrails, ' + printf 'namespace_id: group_template.id, ' + printf 'template_name: :rails, ' + printf 'id: 999};' + printf 'project = ::Projects::CreateService.new(User.find_by_username("root"), attrs).execute;' + printf 'project.saved?;' + ) | gitlab-rails console + + touch $done +} + +echo 'GitLab is ready for acceptance tests'