├── .github ├── CODEOWNERS ├── CONTRIBUTING.md ├── README.md ├── SUPPORT.md ├── renovate.json └── workflows │ ├── codeql-analysis.yml │ ├── reviewdog.yml │ ├── test.yml │ ├── validate-pr-title.yml │ ├── validate.yml │ └── version_increment.yml ├── .gitignore ├── .golangci.yml ├── LICENSE ├── Makefile ├── codecov.yml ├── go.mod ├── go.sum ├── vela ├── admin.go ├── admin_test.go ├── authentication.go ├── authentication_test.go ├── build.go ├── build_test.go ├── client.go ├── client_test.go ├── context.go ├── context_test.go ├── dashboard.go ├── dashboard_test.go ├── deployment.go ├── deployment_test.go ├── doc.go ├── hook.go ├── hook_test.go ├── jwt.go ├── jwt_test.go ├── log.go ├── log_test.go ├── login.go ├── login_test.go ├── pipeline.go ├── pipeline_test.go ├── queue.go ├── queue_test.go ├── repo.go ├── repo_test.go ├── schedule.go ├── schedule_test.go ├── scm.go ├── scm_test.go ├── secret.go ├── secret_test.go ├── service.go ├── service_test.go ├── step.go ├── step_test.go ├── user.go ├── user_test.go ├── vela.go ├── vela_test.go ├── worker.go └── worker_test.go └── version └── version.go /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo. 2 | * @go-vela/admins 3 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Getting Started 4 | 5 | We'd love to accept your contributions to this project! If you are a first time contributor, please review our [Contributing Guidelines](https://go-vela.github.io/docs/community/contributing_guidelines/) before proceeding. 6 | 7 | ### Prerequisites 8 | 9 | * [Review the commit guide we follow](https://chris.beams.io/posts/git-commit/#seven-rules) - ensure your commits follow our standards 10 | * Review our [style guide](https://go-vela.github.io/docs/community/contributing_guidelines/#style-guide) to ensure your code is clean and consistent. 11 | 12 | ### Setup 13 | 14 | * [Fork](/fork) this repository 15 | 16 | * Clone this repository to your workstation: 17 | 18 | ```bash 19 | # Clone the project 20 | git clone git@github.com:go-vela/sdk-go.git $HOME/go-vela/sdk-go 21 | ``` 22 | 23 | * Navigate to the repository code: 24 | 25 | ```bash 26 | # Change into the project directory 27 | cd $HOME/go-vela/sdk-go 28 | ``` 29 | 30 | * Point the original code at your fork: 31 | 32 | ```bash 33 | # Add a remote branch pointing to your fork 34 | git remote add fork https://github.com/your_fork/sdk-go 35 | ``` 36 | 37 | ### Development 38 | 39 | * Navigate to the repository code: 40 | 41 | ```bash 42 | # Change into the project directory 43 | cd $HOME/go-vela/sdk-go 44 | ``` 45 | 46 | * Write your code and tests to implement the changes you desire. 47 | 48 | * Run the repository tests (ensures your changes perform as you desire): 49 | 50 | ```bash 51 | # Test the code with `go` 52 | go test ./... 53 | ``` 54 | 55 | * Ensure your code meets the project standards: 56 | 57 | ```bash 58 | # Clean the code with `go` 59 | go mod tidy 60 | go fmt ./... 61 | go vet ./... 62 | ``` 63 | 64 | * Push to your fork: 65 | 66 | ```bash 67 | # Push your code up to your fork 68 | git push fork main 69 | ``` 70 | * Make sure to follow our [PR process](https://go-vela.github.io/docs/community/contributing_guidelines/#development-workflow) when opening a pull request 71 | 72 | Thank you for your contribution! 73 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 | # sdk-go 2 | 3 | [![license](https://img.shields.io/crates/l/gl.svg)](../LICENSE) 4 | [![GoDoc](https://godoc.org/github.com/go-vela/sdk-go?status.svg)](https://godoc.org/github.com/go-vela/sdk-go) 5 | [![Go Report Card](https://goreportcard.com/badge/go-vela/sdk-go)](https://goreportcard.com/report/go-vela/sdk-go) 6 | [![codecov](https://codecov.io/gh/go-vela/sdk-go/branch/main/graph/badge.svg)](https://codecov.io/gh/go-vela/sdk-go) 7 | 8 | > Vela is in active development and is a pre-release product. 9 | > 10 | > Feel free to send us feedback at https://github.com/go-vela/community/issues/new. 11 | 12 | Vela is a Pipeline Automation (CI/CD) framework built on [Linux container](https://linuxcontainers.org/) technology written in [Golang](https://golang.org/). 13 | 14 | Vela uses a syntax similar to [Docker Compose](https://docs.docker.com/compose/) to define its configuration. This structure for repeated use, within the application, is called a pipeline and a single execution of a pipeline is referenced as a build. 15 | 16 | ## Documentation 17 | 18 | For installation and usage, please [visit our docs](https://go-vela.github.io/docs). 19 | 20 | ## Contributing 21 | 22 | We are always welcome to new pull requests! 23 | 24 | Please see our [contributing](CONTRIBUTING.md) documentation for further instructions. 25 | 26 | ## Support 27 | 28 | We are always here to help! 29 | 30 | Please see our [support](SUPPORT.md) documentation for further instructions. 31 | 32 | ## Copyright and License 33 | 34 | ``` 35 | Copyright 2019 Target Brands, Inc. 36 | ``` 37 | 38 | [Apache License, Version 2.0](../LICENSE) 39 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | Welcome to Vela! To get help with a specific aspect of Vela, we've provided the below information. 4 | 5 | ## Bugs or Feature Requests 6 | 7 | We use GitHub for tracking bugs and feature requests. 8 | 9 | Please see our [contributing](CONTRIBUTING.md) documentation for further instructions. 10 | 11 | ## Installation and Usage 12 | 13 | We use GitHub pages for hosting our installation and usage documentation. 14 | 15 | Please see our [documentation](https://go-vela.github.io/docs) site for more information. 16 | 17 | ## Questions 18 | 19 | We use Slack for supporting questions not already covered in the above documents. 20 | 21 | Please join the [#vela](https://gophers.slack.com/app_redirect?channel=CNRRKE8KY) channel. 22 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "local>go-vela/renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [main] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [main] 20 | schedule: 21 | - cron: "28 23 * * 0" 22 | 23 | permissions: 24 | contents: read 25 | 26 | jobs: 27 | analyze: 28 | name: Analyze 29 | runs-on: ubuntu-latest 30 | 31 | permissions: 32 | actions: read # for github/codeql-action/init to get workflow details 33 | contents: read # for actions/checkout to fetch code 34 | security-events: write # for github/codeql-action/autobuild to send a status report 35 | 36 | strategy: 37 | fail-fast: false 38 | matrix: 39 | language: ["go"] 40 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 41 | # Learn more: 42 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 43 | 44 | steps: 45 | - name: Checkout repository 46 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 47 | 48 | - name: install go 49 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 50 | with: 51 | # use version from go.mod file 52 | go-version-file: "go.mod" 53 | cache: true 54 | check-latest: true 55 | 56 | # Initializes the CodeQL tools for scanning. 57 | - name: Initialize CodeQL 58 | uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 59 | with: 60 | languages: ${{ matrix.language }} 61 | # If you wish to specify custom queries, you can do so here or in a config file. 62 | # By default, queries listed here will override any specified in a config file. 63 | # Prefix the list here with "+" to use these queries and those in the config file. 64 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 65 | 66 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 67 | # If this step fails, then you should remove it and run the build manually (see below) 68 | - name: Autobuild 69 | uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 70 | 71 | # ℹ️ Command-line programs to run using the OS shell. 72 | # 📚 https://git.io/JvXDl 73 | 74 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 75 | # and modify them (or add more) to build your code if your project 76 | # uses a compiled language 77 | 78 | #- run: | 79 | # make bootstrap 80 | # make release 81 | 82 | - name: Perform CodeQL Analysis 83 | uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11 84 | -------------------------------------------------------------------------------- /.github/workflows/reviewdog.yml: -------------------------------------------------------------------------------- 1 | # name of the action 2 | name: reviewdog 3 | 4 | # trigger on pull_request events 5 | on: 6 | pull_request: 7 | 8 | permissions: 9 | contents: read 10 | 11 | # pipeline to execute 12 | jobs: 13 | diff-review: 14 | runs-on: ubuntu-latest 15 | 16 | permissions: 17 | contents: read # for actions/checkout to fetch code 18 | pull-requests: write # for reviewdog/action-golangci-lint to report issues using PR comments 19 | 20 | steps: 21 | - name: clone 22 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 23 | 24 | - name: install go 25 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 26 | with: 27 | # use version from go.mod file 28 | go-version-file: "go.mod" 29 | cache: true 30 | check-latest: true 31 | 32 | - name: golangci-lint 33 | uses: reviewdog/action-golangci-lint@f9bba13753278f6a73b27a56a3ffb1bfda90ed71 # v2.8.0 34 | with: 35 | github_token: ${{ secrets.github_token }} 36 | golangci_lint_flags: "--config=.golangci.yml --timeout=5m" 37 | fail_level: error 38 | filter_mode: diff_context 39 | reporter: github-pr-review 40 | 41 | full-review: 42 | runs-on: ubuntu-latest 43 | 44 | permissions: 45 | checks: write # for reviewdog/action-golangci-lint to report issues using checks 46 | contents: read # for actions/checkout to fetch code 47 | 48 | steps: 49 | - name: clone 50 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 51 | 52 | - name: install go 53 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 54 | with: 55 | # use version from go.mod file 56 | go-version-file: "go.mod" 57 | cache: true 58 | check-latest: true 59 | 60 | - name: golangci-lint 61 | uses: reviewdog/action-golangci-lint@f9bba13753278f6a73b27a56a3ffb1bfda90ed71 # v2.8.0 62 | with: 63 | github_token: ${{ secrets.github_token }} 64 | golangci_lint_flags: "--config=.golangci.yml --timeout=5m" 65 | fail_level: error 66 | filter_mode: nofilter 67 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # name of the action 2 | name: test 3 | 4 | # trigger on pull_request or push events 5 | on: 6 | pull_request: 7 | push: 8 | 9 | permissions: 10 | contents: read 11 | 12 | # pipeline to execute 13 | jobs: 14 | test: 15 | runs-on: ubuntu-latest 16 | 17 | permissions: 18 | id-token: write # for codecov report upload 19 | 20 | steps: 21 | - name: clone 22 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 23 | 24 | - name: install go 25 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 26 | with: 27 | # use version from go.mod file 28 | go-version-file: "go.mod" 29 | cache: true 30 | check-latest: true 31 | 32 | - name: test 33 | run: | 34 | make test 35 | 36 | - name: coverage 37 | uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0 38 | with: 39 | use_oidc: true 40 | files: coverage.out 41 | -------------------------------------------------------------------------------- /.github/workflows/validate-pr-title.yml: -------------------------------------------------------------------------------- 1 | # name of the action 2 | name: validate PR title 3 | 4 | # trigger on pull_request events of the opened & edited type. 5 | on: 6 | pull_request: 7 | types: [opened, synchronize, edited, reopened] 8 | 9 | permissions: 10 | contents: read 11 | 12 | # pipeline to execute 13 | jobs: 14 | validate: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: validate title 19 | env: 20 | TITLE: ${{ github.event.pull_request.title }} 21 | run: | 22 | echo "$TITLE" | grep -Eq '^(feat|fix|chore|refactor|enhance|test|docs)(\(.*\)|)!?:\s.+$' && (echo "Pass"; exit 0) || (echo "Incorrect Format. Please see https://go-vela.github.io/docs/community/contributing_guidelines/#development-workflow"; exit 1) 23 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | # name of the action 2 | name: validate 3 | 4 | # trigger on pull_request or push events 5 | on: 6 | pull_request: 7 | push: 8 | 9 | permissions: 10 | contents: read 11 | 12 | # pipeline to execute 13 | jobs: 14 | validate: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: clone 18 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 19 | 20 | - name: install go 21 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 22 | with: 23 | # use version from go.mod file 24 | go-version-file: "go.mod" 25 | cache: true 26 | check-latest: true 27 | 28 | - name: validate 29 | run: | 30 | # Check that go mod tidy produces a zero diff; clean up any changes afterwards. 31 | go mod tidy && git diff --exit-code; code=$?; git checkout -- .; (exit $code) 32 | # Check that go vet ./... produces a zero diff; clean up any changes afterwards. 33 | go vet ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) 34 | # Check that go fmt ./... produces a zero diff; clean up any changes afterwards. 35 | go fmt ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) 36 | # Check that go fix ./... produces a zero diff; clean up any changes afterwards. 37 | go fix ./... && git diff --exit-code; code=$?; git checkout -- .; (exit $code) 38 | -------------------------------------------------------------------------------- /.github/workflows/version_increment.yml: -------------------------------------------------------------------------------- 1 | name: Bump Version 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | BumpVersion: 12 | runs-on: ubuntu-latest 13 | 14 | permissions: 15 | contents: write # for creating a new branch for version increment 16 | pull-requests: write # for actions/github-script to open a new PR 17 | 18 | steps: 19 | - name: clone 20 | uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Check if release is a release candidate 25 | run: | 26 | if [[ "${{ github.event.release.tag_name }}" =~ -rc[0-9]+$ ]]; then 27 | echo "This is a release candidate. Skipping version bump." 28 | echo "skip=true" >> $GITHUB_ENV 29 | else 30 | echo "skip=false" >> $GITHUB_ENV 31 | fi 32 | 33 | - name: Check if minor version was incremented 34 | if: env.skip == 'false' 35 | run: | 36 | VERSION_MINOR_OLD=$(grep -oP 'VersionMinor int64 = \K[0-9]+' version/version.go) 37 | VERSION_MINOR_NEW=$(echo "${{ github.event.release.tag_name }}" | cut -d. -f2) 38 | if [[ "$VERSION_MINOR_NEW" -lt "$VERSION_MINOR_OLD" ]]; then 39 | echo "The minor version was not incremented in the release tag. Skipping version bump." 40 | echo "skip=true" >> $GITHUB_ENV 41 | fi 42 | 43 | - name: Bump minor version and push changes 44 | if: env.skip == 'false' 45 | run: | 46 | git config --global user.name 'github-actions[bot]' 47 | git config --global user.email '41898282+github-actions[bot]@users.noreply.github.com' 48 | VERSION_MINOR=$(echo "${{ github.event.release.tag_name }}" | cut -d. -f2) 49 | NEW_VERSION_MINOR=$((VERSION_MINOR + 1)) 50 | echo "NEW_VERSION_MINOR=$NEW_VERSION_MINOR" >> $GITHUB_ENV 51 | git switch -c bump-minor-version-to-$NEW_VERSION_MINOR 52 | sed -i "s|VersionMinor int64 = [0-9]*|VersionMinor int64 = $NEW_VERSION_MINOR|" version/version.go 53 | git commit -am "bump version" 54 | git push origin bump-minor-version-to-$NEW_VERSION_MINOR 55 | 56 | - name: Create Pull Request 57 | if: env.skip == 'false' 58 | uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 59 | with: 60 | script: | 61 | const { owner, repo } = context.repo 62 | const pullRequest = await github.rest.pulls.create({ 63 | owner, 64 | repo, 65 | title: `chore: bump minor version to ${process.env.NEW_VERSION_MINOR}`, 66 | head: `bump-minor-version-to-${process.env.NEW_VERSION_MINOR}`, 67 | base: 'main', 68 | body: `This PR increments the VersionMinor value in version.go to ${process.env.NEW_VERSION_MINOR}.`, 69 | }) 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/go 2 | 3 | ### Go ### 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | ### Go Patch ### 18 | /vendor/ 19 | /Godeps/ 20 | 21 | # End of https://www.gitignore.io/api/go 22 | 23 | # IntelliJ project folder 24 | .idea/ 25 | .DS_Store 26 | 27 | # IntelliJ project files 28 | *.iml 29 | *.ipr 30 | *.iws 31 | *.xml 32 | 33 | # Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode 34 | # Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode 35 | 36 | ### VisualStudioCode ### 37 | .vscode/* 38 | !.vscode/settings.json 39 | !.vscode/tasks.json 40 | !.vscode/launch.json 41 | !.vscode/extensions.json 42 | !.vscode/*.code-snippets 43 | 44 | # Local History for Visual Studio Code 45 | .history/ 46 | 47 | # Built Visual Studio Code Extensions 48 | *.vsix 49 | __debug_bin 50 | 51 | ### VisualStudioCode Patch ### 52 | # Ignore all local history of files 53 | .history 54 | .ionide 55 | 56 | # End of https://www.toptal.com/developers/gitignore/api/visualstudiocode 57 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | output: 3 | formats: 4 | text: 5 | path: stdout 6 | print-linter-name: true 7 | print-issued-lines: true 8 | linters: 9 | default: none 10 | enable: 11 | - bidichk 12 | - bodyclose 13 | - contextcheck 14 | - dupl 15 | - errcheck 16 | - errorlint 17 | - funlen 18 | - goconst 19 | - gocyclo 20 | - godot 21 | - goheader 22 | - gomoddirectives 23 | - goprintffuncname 24 | - gosec 25 | - govet 26 | - ineffassign 27 | - makezero 28 | - misspell 29 | - nakedret 30 | - nilerr 31 | - noctx 32 | - nolintlint 33 | - revive 34 | - staticcheck 35 | - unconvert 36 | - unparam 37 | - unused 38 | - whitespace 39 | - wsl_v5 40 | settings: 41 | dupl: 42 | threshold: 100 43 | funlen: 44 | lines: 160 45 | statements: 70 46 | goheader: 47 | template: "SPDX-License-Identifier: Apache-2.0" 48 | misspell: 49 | locale: US 50 | nolintlint: 51 | require-explanation: true 52 | require-specific: true 53 | allow-unused: false 54 | wsl_v5: 55 | allow-first-in-block: true 56 | allow-whole-block: false 57 | branch-max-lines: 2 58 | exclusions: 59 | generated: lax 60 | presets: 61 | - comments 62 | - common-false-positives 63 | - legacy 64 | - std-error-handling 65 | rules: 66 | - linters: 67 | - dupl 68 | - funlen 69 | - goconst 70 | - gocyclo 71 | - wsl 72 | path: _test\.go 73 | paths: 74 | - third_party$ 75 | - builtin$ 76 | - examples$ 77 | issues: 78 | uniq-by-line: true 79 | formatters: 80 | enable: 81 | - gci 82 | - gofmt 83 | settings: 84 | gci: 85 | sections: 86 | - standard 87 | - default 88 | - blank 89 | - dot 90 | - prefix(github.com/go-vela) 91 | custom-order: true 92 | exclusions: 93 | generated: lax 94 | paths: 95 | - third_party$ 96 | - builtin$ 97 | - examples$ 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2019 Target Brands, Inc. 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # The `clean` target is intended to clean the workspace 4 | # and prepare the local changes for submission. 5 | # 6 | # Usage: `make clean` 7 | .PHONY: clean 8 | clean: tidy vet fmt fix 9 | 10 | # The `tidy` target is intended to clean up 11 | # the Go module files (go.mod & go.sum). 12 | # 13 | # Usage: `make tidy` 14 | .PHONY: tidy 15 | tidy: 16 | @echo 17 | @echo "### Tidying Go module" 18 | @go mod tidy 19 | 20 | # The `vet` target is intended to inspect the 21 | # Go source code for potential issues. 22 | # 23 | # Usage: `make vet` 24 | .PHONY: vet 25 | vet: 26 | @echo 27 | @echo "### Vetting Go code" 28 | @go vet ./... 29 | 30 | # The `fmt` target is intended to format the 31 | # Go source code to meet the language standards. 32 | # 33 | # Usage: `make fmt` 34 | .PHONY: fmt 35 | fmt: 36 | @echo 37 | @echo "### Formatting Go Code" 38 | @go fmt ./... 39 | 40 | # The `fix` target is intended to rewrite the 41 | # Go source code using old APIs. 42 | # 43 | # Usage: `make fix` 44 | .PHONY: fix 45 | fix: 46 | @echo 47 | @echo "### Fixing Go Code" 48 | @go fix ./... 49 | 50 | # The `test` target is intended to run 51 | # the tests for the Go source code. 52 | # 53 | # Usage: `make test` 54 | .PHONY: test 55 | test: 56 | @echo 57 | @echo "### Testing Go Code" 58 | @go test -race -covermode=atomic -coverprofile=coverage.out ./... 59 | 60 | # The `test-cover` target is intended to run 61 | # the tests for the Go source code and then 62 | # open the test coverage report. 63 | # 64 | # Usage: `make test-cover` 65 | .PHONY: test-cover 66 | test-cover: test 67 | @echo 68 | @echo "### Opening test coverage report" 69 | @go tool cover -html=coverage.out 70 | 71 | # The `check` target is intended to output all 72 | # dependencies from the Go module that need updates. 73 | # 74 | # Usage: `make check` 75 | .PHONY: check 76 | check: check-install 77 | @echo 78 | @echo "### Checking dependencies for updates" 79 | @go list -u -m -json all | go-mod-outdated -update 80 | 81 | # The `check-direct` target is intended to output direct 82 | # dependencies from the Go module that need updates. 83 | # 84 | # Usage: `make check-direct` 85 | .PHONY: check-direct 86 | check-direct: check-install 87 | @echo 88 | @echo "### Checking direct dependencies for updates" 89 | @go list -u -m -json all | go-mod-outdated -direct 90 | 91 | # The `check-full` target is intended to output 92 | # all dependencies from the Go module. 93 | # 94 | # Usage: `make check-full` 95 | .PHONY: check-full 96 | check-full: check-install 97 | @echo 98 | @echo "### Checking all dependencies for updates" 99 | @go list -u -m -json all | go-mod-outdated 100 | 101 | # The `check-install` target is intended to download 102 | # the tool used to check dependencies from the Go module. 103 | # 104 | # Usage: `make check-install` 105 | .PHONY: check-install 106 | check-install: 107 | @echo 108 | @echo "### Installing psampaz/go-mod-outdated" 109 | @go get -u github.com/psampaz/go-mod-outdated 110 | 111 | # The `bump-deps` target is intended to upgrade 112 | # non-test dependencies for the Go module. 113 | # 114 | # Usage: `make bump-deps` 115 | .PHONY: bump-deps 116 | bump-deps: check 117 | @echo 118 | @echo "### Upgrading dependencies" 119 | @go get -u ./... 120 | 121 | # The `bump-deps-full` target is intended to upgrade 122 | # all dependencies for the Go module. 123 | # 124 | # Usage: `make bump-deps-full` 125 | .PHONY: bump-deps-full 126 | bump-deps-full: check 127 | @echo 128 | @echo "### Upgrading all dependencies" 129 | @go get -t -u ./... 130 | 131 | # The `lint` target is intended to lint the 132 | # Go source code with golangci-lint. 133 | # 134 | # Usage: `make lint` 135 | .PHONY: lint 136 | lint: 137 | @echo 138 | @echo "### Linting Go Code" 139 | @golangci-lint run ./... 140 | 141 | # The `lintfix` target is intended to lint the 142 | # Go source code with golangci-lint and apply 143 | # any fixes that can be automatically applied. 144 | # 145 | # Usage: `make lintfix` 146 | .PHONY: lintfix 147 | lintfix: 148 | @echo 149 | @echo "### Fixing Go code with linter" 150 | @golangci-lint run ./... --fix 151 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # The is the default codecov.io yaml configuration all projects use 2 | # that do not have their own codecov.yml already in the project. 3 | # 4 | # https://docs.codecov.io/docs/codecov-yaml#section-default-yaml 5 | 6 | # This section provides the generic configuration for codecov. 7 | # 8 | # https://docs.codecov.io/docs/codecovyml-reference#section-codecov 9 | codecov: 10 | 11 | require_ci_to_pass: yes 12 | 13 | # This section provides the configuration for the 14 | # coverage report codecov analyzes for results. 15 | # 16 | # https://docs.codecov.io/docs/codecovyml-reference#section-coverage 17 | coverage: 18 | 19 | precision: 2 20 | round: down 21 | range: "70...100" 22 | 23 | # https://docs.codecov.io/docs/commit-status 24 | status: 25 | # set rules for the project status report 26 | project: 27 | default: 28 | target: 90% 29 | threshold: 0% 30 | # disable the patch status report 31 | patch: off 32 | # disable the changes status report 33 | changes: off 34 | 35 | # This section provides the configuration for the 36 | # parsers codecov uses for the coverage report. 37 | # 38 | # https://docs.codecov.io/docs/codecovyml-reference#section-parsers 39 | parsers: 40 | 41 | gcov: 42 | 43 | branch_detection: 44 | conditional: yes 45 | loop: yes 46 | method: no 47 | macro: no 48 | 49 | # This section provides the configuration for the 50 | # comments codecov makes to open pull requests. 51 | # 52 | # https://docs.codecov.io/docs/codecovyml-reference#section-comment 53 | comment: 54 | 55 | layout: "reach, diff, flags, files" 56 | behavior: default 57 | require_changes: no 58 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-vela/sdk-go 2 | 3 | go 1.24.4 4 | 5 | require ( 6 | github.com/coreos/go-semver v0.3.1 7 | github.com/gin-gonic/gin v1.10.1 8 | github.com/go-vela/server v0.27.1 9 | github.com/golang-jwt/jwt/v5 v5.3.0 10 | github.com/google/go-cmp v0.7.0 11 | github.com/google/go-querystring v1.1.0 12 | github.com/sirupsen/logrus v1.9.3 13 | go.yaml.in/yaml/v3 v3.0.4 14 | ) 15 | 16 | require ( 17 | github.com/bahlo/generic-list-go v0.2.0 // indirect 18 | github.com/buger/jsonparser v1.1.1 // indirect 19 | github.com/buildkite/yaml v0.0.0-20230306222819-0e4e032d4835 // indirect 20 | github.com/bytedance/sonic v1.13.3 // indirect 21 | github.com/bytedance/sonic/loader v0.2.4 // indirect 22 | github.com/cloudwego/base64x v0.1.5 // indirect 23 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect 24 | github.com/drone/envsubst v1.0.3 // indirect 25 | github.com/expr-lang/expr v1.17.6 // indirect 26 | github.com/gabriel-vasile/mimetype v1.4.9 // indirect 27 | github.com/ghodss/yaml v1.0.0 // indirect 28 | github.com/gin-contrib/sse v1.1.0 // indirect 29 | github.com/go-playground/locales v0.14.1 // indirect 30 | github.com/go-playground/universal-translator v0.18.1 // indirect 31 | github.com/go-playground/validator/v10 v10.26.0 // indirect 32 | github.com/goccy/go-json v0.10.5 // indirect 33 | github.com/invopop/jsonschema v0.13.0 // indirect 34 | github.com/json-iterator/go v1.1.12 // indirect 35 | github.com/klauspost/cpuid/v2 v2.2.11 // indirect 36 | github.com/kr/pretty v0.3.0 // indirect 37 | github.com/leodido/go-urn v1.4.0 // indirect 38 | github.com/lestrrat-go/blackmagic v1.0.4 // indirect 39 | github.com/lestrrat-go/httpcc v1.0.1 // indirect 40 | github.com/lestrrat-go/httprc/v3 v3.0.0 // indirect 41 | github.com/lestrrat-go/jwx/v3 v3.0.10 // indirect 42 | github.com/lestrrat-go/option v1.0.1 // indirect 43 | github.com/lestrrat-go/option/v2 v2.0.0 // indirect 44 | github.com/mailru/easyjson v0.9.0 // indirect 45 | github.com/mattn/go-isatty v0.0.20 // indirect 46 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 47 | github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect 48 | github.com/pelletier/go-toml/v2 v2.2.4 // indirect 49 | github.com/rogpeppe/go-internal v1.11.0 // indirect 50 | github.com/segmentio/asm v1.2.0 // indirect 51 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 52 | github.com/ugorji/go/codec v1.3.0 // indirect 53 | github.com/urfave/cli/v3 v3.4.1 // indirect 54 | github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect 55 | golang.org/x/arch v0.18.0 // indirect 56 | golang.org/x/crypto v0.41.0 // indirect 57 | golang.org/x/net v0.42.0 // indirect 58 | golang.org/x/sys v0.35.0 // indirect 59 | golang.org/x/text v0.28.0 // indirect 60 | google.golang.org/protobuf v1.36.6 // indirect 61 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 62 | gopkg.in/yaml.v2 v2.4.0 // indirect 63 | gopkg.in/yaml.v3 v3.0.1 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /vela/admin.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "errors" 7 | "fmt" 8 | "strings" 9 | 10 | api "github.com/go-vela/server/api/types" 11 | "github.com/go-vela/server/api/types/settings" 12 | ) 13 | 14 | type ( 15 | // AdminService handles retrieving resources from 16 | // the server methods of the Vela API. 17 | AdminService struct { 18 | Build *AdminBuildService 19 | Clean *AdminCleanService 20 | Deployment *AdminDeploymentService 21 | Hook *AdminHookService 22 | OIDC *AdminOIDCService 23 | Repo *AdminRepoService 24 | Secret *AdminSecretService 25 | Service *AdminSvcService 26 | Step *AdminStepService 27 | User *AdminUserService 28 | Worker *AdminWorkerService 29 | Settings *AdminSettingsService 30 | } 31 | 32 | // AdminBuildService handles retrieving admin builds from 33 | // the server methods of the Vela API. 34 | AdminBuildService service 35 | 36 | // AdminCleanService handles cleaning resources using 37 | // the server methods of the Vela API. 38 | AdminCleanService service 39 | 40 | // AdminDeploymentService handles retrieving admin deployments from 41 | // the server methods of the Vela API. 42 | AdminDeploymentService service 43 | 44 | // AdminHookService handles retrieving admin hooks from 45 | // the server methods of the Vela API. 46 | AdminHookService service 47 | 48 | // AdminOIDCService handles key rotation for OpenID Connect. 49 | AdminOIDCService service 50 | 51 | // AdminRepoService handles retrieving admin repos from 52 | // the server methods of the Vela API. 53 | AdminRepoService service 54 | 55 | // AdminSecretService handles retrieving admin secrets from 56 | // the server methods of the Vela API. 57 | AdminSecretService service 58 | 59 | // AdminSvcService handles retrieving admin services from 60 | // the server methods of the Vela API. 61 | AdminSvcService service 62 | 63 | // AdminStepService handles retrieving admin steps from 64 | // the server methods of the Vela API. 65 | AdminStepService service 66 | 67 | // AdminUserService handles retrieving admin users from 68 | // the server methods of the Vela API. 69 | AdminUserService service 70 | 71 | // AdminWorkerService handles managing admin worker functionality 72 | // from the server methods of the Vela API. 73 | AdminWorkerService service 74 | 75 | // AdminSettingsService handles managing admin settings functionality 76 | // from the server methods of the Vela API. 77 | AdminSettingsService service 78 | ) 79 | 80 | // GetQueueOptions specifies the optional parameters to the 81 | // AdminBuildService.GetQueue method. 82 | type GetQueueOptions struct { 83 | // Unix timestamp. 84 | // Returns only the builds created since the timestamp. 85 | // Default: 24 hours ago 86 | After string `url:"after,omitempty"` 87 | 88 | ListOptions 89 | } 90 | 91 | // CleanOptions specifies the optional parameters to the 92 | // Clean.Clean method. 93 | type CleanOptions struct { 94 | Before int64 `url:"before,omitempty"` 95 | } 96 | 97 | // Update modifies a build with the provided details. 98 | func (svc *AdminBuildService) Update(b *api.Build) (*api.Build, *Response, error) { 99 | // set the API endpoint path we send the request to 100 | u := "/api/v1/admin/build" 101 | 102 | // API Build type we want to return 103 | v := new(api.Build) 104 | 105 | // send request using client 106 | resp, err := svc.client.Call("PUT", u, b, v) 107 | 108 | return v, resp, err 109 | } 110 | 111 | // Clean sets build resources older than a specified time to a proper canceled / finished state with the provided message. 112 | func (svc *AdminCleanService) Clean(e *api.Error, opt *CleanOptions) (*string, *Response, error) { 113 | // set the API endpoint path we send the request to 114 | u := "/api/v1/admin/clean" 115 | 116 | // add optional arguments if supplied 117 | u, err := addOptions(u, opt) 118 | if err != nil { 119 | return nil, nil, err 120 | } 121 | 122 | v := new(string) 123 | 124 | resp, err := svc.client.Call("PUT", u, e, v) 125 | 126 | return v, resp, err 127 | } 128 | 129 | // GetQueue returns the list of builds in pending and running status. 130 | func (svc *AdminBuildService) GetQueue(opt *GetQueueOptions) (*[]api.QueueBuild, *Response, error) { 131 | // set the API endpoint path we send the request to 132 | u := "/api/v1/admin/builds/queue" 133 | 134 | // add optional arguments if supplied 135 | u, err := addOptions(u, opt) 136 | if err != nil { 137 | return nil, nil, err 138 | } 139 | 140 | // BuildQueue type we want to return 141 | v := new([]api.QueueBuild) 142 | 143 | resp, err := svc.client.Call("GET", u, nil, v) 144 | 145 | return v, resp, err 146 | } 147 | 148 | // Update modifies a deployment with the provided details. 149 | func (svc *AdminDeploymentService) Update(d *api.Deployment) (*api.Deployment, *Response, error) { 150 | // set the API endpoint path we send the request to 151 | u := "/api/v1/admin/deployment" 152 | 153 | // API Deployment type we want to return 154 | v := new(api.Deployment) 155 | 156 | // send request using client 157 | resp, err := svc.client.Call("PUT", u, d, v) 158 | 159 | return v, resp, err 160 | } 161 | 162 | // Update modifies a hook with the provided details. 163 | func (svc *AdminHookService) Update(h *api.Hook) (*api.Hook, *Response, error) { 164 | // set the API endpoint path we send the request to 165 | u := "/api/v1/admin/hook" 166 | 167 | // API Hook type we want to return 168 | v := new(api.Hook) 169 | 170 | // send request using client 171 | resp, err := svc.client.Call("PUT", u, h, v) 172 | 173 | return v, resp, err 174 | } 175 | 176 | // Update modifies a repo with the provided details. 177 | func (svc *AdminRepoService) Update(r *api.Repo) (*api.Repo, *Response, error) { 178 | // set the API endpoint path we send the request to 179 | u := "/api/v1/admin/repo" 180 | 181 | // API Repo type we want to return 182 | v := new(api.Repo) 183 | 184 | // send request using client 185 | resp, err := svc.client.Call("PUT", u, r, v) 186 | 187 | return v, resp, err 188 | } 189 | 190 | // Update modifies a secret with the provided details. 191 | func (svc *AdminSecretService) Update(s *api.Secret) (*api.Secret, *Response, error) { 192 | // set the API endpoint path we send the request to 193 | u := "/api/v1/admin/secret" 194 | 195 | // API Secret type we want to return 196 | v := new(api.Secret) 197 | 198 | // send request using client 199 | resp, err := svc.client.Call("PUT", u, s, v) 200 | 201 | return v, resp, err 202 | } 203 | 204 | // Update modifies a service with the provided details. 205 | func (svc *AdminSvcService) Update(s *api.Service) (*api.Service, *Response, error) { 206 | // set the API endpoint path we send the request to 207 | u := "/api/v1/admin/service" 208 | 209 | // API Service type we want to return 210 | v := new(api.Service) 211 | 212 | // send request using client 213 | resp, err := svc.client.Call("PUT", u, s, v) 214 | 215 | return v, resp, err 216 | } 217 | 218 | // Update modifies a step with the provided details. 219 | func (svc *AdminStepService) Update(s *api.Step) (*api.Step, *Response, error) { 220 | // set the API endpoint path we send the request to 221 | u := "/api/v1/admin/step" 222 | 223 | // API Step type we want to return 224 | v := new(api.Step) 225 | 226 | // send request using client 227 | resp, err := svc.client.Call("PUT", u, s, v) 228 | 229 | return v, resp, err 230 | } 231 | 232 | // Update modifies a user with the provided details. 233 | func (svc *AdminUserService) Update(u *api.User) (*api.User, *Response, error) { 234 | // set the API endpoint path we send the request to 235 | url := "/api/v1/admin/user" 236 | 237 | // API User type we want to return 238 | v := new(api.User) 239 | 240 | // send request using client 241 | resp, err := svc.client.Call("PUT", url, u, v) 242 | 243 | return v, resp, err 244 | } 245 | 246 | // Get retrieves the active platform settings. 247 | func (svc *AdminSettingsService) Get() (*settings.Platform, *Response, error) { 248 | // set the API endpoint path we send the request to 249 | //nolint:goconst // ignore 250 | u := "/api/v1/admin/settings" 251 | 252 | // api Settings type we want to return 253 | v := new(settings.Platform) 254 | 255 | // send request using client 256 | resp, err := svc.client.Call("GET", u, nil, v) 257 | 258 | return v, resp, err 259 | } 260 | 261 | // Update modifies platform settings with the provided details. 262 | func (svc *AdminSettingsService) Update(s *settings.Platform) (*settings.Platform, *Response, error) { 263 | // set the API endpoint path we send the request to 264 | u := "/api/v1/admin/settings" 265 | 266 | // api Settings type we want to return 267 | v := new(settings.Platform) 268 | 269 | // send request using client 270 | resp, err := svc.client.Call("PUT", u, s, v) 271 | 272 | return v, resp, err 273 | } 274 | 275 | // Restore returns the platform settings to the server's environment-provided defaults. 276 | func (svc *AdminSettingsService) Restore() (*settings.Platform, *Response, error) { 277 | // set the API endpoint path we send the request to 278 | u := "/api/v1/admin/settings" 279 | 280 | // api Settings type we want to return 281 | v := new(settings.Platform) 282 | 283 | // send request using client 284 | resp, err := svc.client.Call("DELETE", u, nil, v) 285 | 286 | return v, resp, err 287 | } 288 | 289 | // RegisterToken generates a worker registration token with the provided details. 290 | func (svc *AdminWorkerService) RegisterToken(hostname string) (*api.Token, *Response, error) { 291 | // validate input 292 | if strings.EqualFold(hostname, "") { 293 | return nil, nil, errors.New("bad request, no hostname provided") 294 | } 295 | 296 | // set the API endpoint path we send the request to 297 | url := fmt.Sprintf("/api/v1/admin/workers/%s/register", hostname) 298 | 299 | // API Token type we want to return 300 | t := new(api.Token) 301 | 302 | // send request using client 303 | resp, err := svc.client.Call("POST", url, nil, t) 304 | 305 | return t, resp, err 306 | } 307 | 308 | // RotateOIDCKeys sends a request to rotate the private keys used for creating ID tokens. 309 | func (svc *AdminOIDCService) RotateOIDCKeys() (*string, *Response, error) { 310 | // set the API endpoint path we send the request to 311 | url := "/api/v1/admin/rotate_oidc_keys" 312 | 313 | v := new(string) 314 | 315 | // send request using client 316 | resp, err := svc.client.Call("POST", url, nil, v) 317 | 318 | return v, resp, err 319 | } 320 | -------------------------------------------------------------------------------- /vela/authentication.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "context" 7 | "errors" 8 | "fmt" 9 | "net/http" 10 | 11 | api "github.com/go-vela/server/api/types" 12 | "github.com/go-vela/server/constants" 13 | ) 14 | 15 | type AuthenticationType int 16 | 17 | const ( 18 | // AuthenticationToken defines the 19 | // authentication type for auth tokens. 20 | AuthenticationToken AuthenticationType = iota + 1 21 | PersonalAccessToken 22 | AccessAndRefreshToken 23 | BuildToken 24 | ) 25 | 26 | // AuthenticationService contains 27 | // authentication related functions. 28 | type AuthenticationService struct { 29 | client *Client 30 | token *string 31 | personalAccessToken *string 32 | accessToken *string 33 | refreshToken *string 34 | scmToken *string 35 | authType AuthenticationType 36 | } 37 | 38 | // SetTokenAuth sets the authentication type as a plain token. 39 | func (svc *AuthenticationService) SetTokenAuth(token string) { 40 | svc.token = String(token) 41 | svc.authType = AuthenticationToken 42 | } 43 | 44 | // SetBuildTokenAuth sets the authentication type and the two tokens used. 45 | func (svc *AuthenticationService) SetBuildTokenAuth(buildTkn, scmTkn string) { 46 | svc.token = String(buildTkn) 47 | svc.scmToken = String(scmTkn) 48 | svc.authType = BuildToken 49 | } 50 | 51 | // SetPersonalAccessTokenAuth sets the authentication type as personal access token. 52 | func (svc *AuthenticationService) SetPersonalAccessTokenAuth(token string) { 53 | svc.personalAccessToken = String(token) 54 | svc.authType = PersonalAccessToken 55 | } 56 | 57 | // SetAccessAndRefreshAuth sets the authentication type as oauth token pair. 58 | func (svc *AuthenticationService) SetAccessAndRefreshAuth(access, refresh string) { 59 | svc.accessToken = String(access) 60 | svc.refreshToken = String(refresh) 61 | svc.authType = AccessAndRefreshToken 62 | } 63 | 64 | // HasAuth checks if the authentication type is set. 65 | func (svc *AuthenticationService) HasAuth() bool { 66 | return svc.authType > 0 67 | } 68 | 69 | // HasTokenAuth checks if the authentication type is a plain token. 70 | func (svc *AuthenticationService) HasTokenAuth() bool { 71 | return svc.authType == AuthenticationToken 72 | } 73 | 74 | // HasBuildTokenAuth checks if the authentication type is a build and scm token. 75 | func (svc *AuthenticationService) HasBuildTokenAuth() bool { 76 | return svc.authType == BuildToken 77 | } 78 | 79 | // HasPersonalAccessTokenAuth checks if the authentication type is a personal access token. 80 | func (svc *AuthenticationService) HasPersonalAccessTokenAuth() bool { 81 | return svc.authType == PersonalAccessToken 82 | } 83 | 84 | // HasAccessAndRefreshAuth checks if the authentication type is oauth token pair. 85 | func (svc *AuthenticationService) HasAccessAndRefreshAuth() bool { 86 | return svc.authType == AccessAndRefreshToken 87 | } 88 | 89 | // IsTokenAuthExpired returns whether or not the authentication token has expired. 90 | func (svc *AuthenticationService) IsTokenAuthExpired() (bool, error) { 91 | // verify that the auth type is valid for this type of validation 92 | if !svc.HasTokenAuth() { 93 | return true, errors.New("client auth type is not set to auth token") 94 | } 95 | 96 | // verify a token exists in the client 97 | if svc.token == nil { 98 | return true, errors.New("no token in client") 99 | } 100 | 101 | // check auth token expiration 102 | return IsTokenExpired(*svc.token), nil 103 | } 104 | 105 | // RefreshAccessToken uses the supplied refresh token to attempt and refresh 106 | // the access token. 107 | func (svc *AuthenticationService) RefreshAccessToken(refreshToken string) (*Response, error) { 108 | // set the API endpoint path we send the request to 109 | u := "/token-refresh" 110 | 111 | v := new(api.Token) 112 | 113 | // building a custom request - 114 | // we can't use svc.client.NewRequest because 115 | // that's what can send us here 116 | url, err := svc.client.buildURLForRequest(u) 117 | if err != nil { 118 | return nil, err 119 | } 120 | 121 | req, err := http.NewRequestWithContext(context.Background(), "GET", url, nil) 122 | if err != nil { 123 | return nil, err 124 | } 125 | 126 | // set a minimal cookie with the refresh token value 127 | cookie := &http.Cookie{ 128 | Name: constants.RefreshTokenName, 129 | Value: refreshToken, 130 | } 131 | 132 | req.AddCookie(cookie) 133 | 134 | // send the request 135 | resp, err := svc.client.Do(req, v) 136 | 137 | // set the received access token 138 | svc.accessToken = v.Token 139 | 140 | return resp, err 141 | } 142 | 143 | // AuthenticateWithToken attempts to authenticate with the provided token, typically 144 | // a personal access token created in the source provider, eg. GitHub. It will 145 | // return a short-lived Vela Access Token, if successful. 146 | func (svc *AuthenticationService) AuthenticateWithToken(token string) (string, *Response, error) { 147 | // set the API endpoint path we send the request to 148 | u := "/authenticate/token" 149 | 150 | // check for token 151 | if len(token) == 0 { 152 | return "", nil, fmt.Errorf("token must not be empty") 153 | } 154 | 155 | // will hold access token 156 | v := new(api.Token) 157 | 158 | // building a custom request - 159 | // we can't use svc.client.NewRequest because 160 | // that's what can send us here 161 | url, err := svc.client.buildURLForRequest(u) 162 | if err != nil { 163 | return "", nil, err 164 | } 165 | 166 | // create a new request that we can attach a header to 167 | req, err := http.NewRequestWithContext(context.Background(), "POST", url, nil) 168 | if err != nil { 169 | return "", nil, err 170 | } 171 | 172 | // add the token as a header 173 | req.Header.Add("Token", token) 174 | 175 | // send the request 176 | resp, err := svc.client.Do(req, v) 177 | 178 | return v.GetToken(), resp, err 179 | } 180 | 181 | // ExchangeTokens handles the last part of the OAuth flow. It uses the supplied 182 | // code and state values to attempt to exchange them for Vela Access and 183 | // Refresh tokens. 184 | func (svc *AuthenticationService) ExchangeTokens(opt *OAuthExchangeOptions) (string, string, *Response, error) { 185 | // set the API endpoint path we send the request to 186 | u := "/authenticate" 187 | 188 | // will hold access token 189 | v := new(api.Token) 190 | 191 | // check required arguments 192 | if len(opt.Code) == 0 || len(opt.State) == 0 { 193 | return "", "", nil, fmt.Errorf("code and state must be provided") 194 | } 195 | 196 | // add required arguments 197 | u, err := addOptions(u, opt) 198 | if err != nil { 199 | return "", "", nil, err 200 | } 201 | 202 | // attempt to exchange code + state for tokens 203 | resp, err := svc.client.Call("GET", u, nil, v) 204 | if err != nil { 205 | return "", "", resp, err 206 | } 207 | 208 | // the refresh token will be in a cookie in the response 209 | rt := extractRefreshToken(resp.Cookies()) 210 | 211 | // get the access token 212 | at := v.GetToken() 213 | 214 | // set the received tokens 215 | svc.accessToken = &at 216 | svc.refreshToken = &rt 217 | 218 | return at, rt, resp, err 219 | } 220 | 221 | // extractRefreshToken is a helper function to extract 222 | // the refresh token from the supplied cookie slice. 223 | func extractRefreshToken(cookies []*http.Cookie) string { 224 | c := "" 225 | 226 | // loop over the cookies to find the refresh cookie 227 | for _, cookie := range cookies { 228 | if cookie.Name == constants.RefreshTokenName { 229 | c = cookie.Value 230 | } 231 | } 232 | 233 | return c 234 | } 235 | 236 | // ValidateToken makes a request to validate tokens with the Vela server. 237 | func (svc *AuthenticationService) ValidateToken() (*Response, error) { 238 | // set the API endpoint path we send the request to 239 | u := "/validate-token" 240 | 241 | // attempt to validate a server token 242 | resp, err := svc.client.Call("GET", u, nil, nil) 243 | 244 | return resp, err 245 | } 246 | 247 | // ValidateOAuthToken makes a request to validate user oauth tokens with the Vela server. 248 | func (svc *AuthenticationService) ValidateOAuthToken() (*Response, error) { 249 | // set the API endpoint path we send the request to 250 | u := "/validate-oauth" 251 | 252 | // attempt to validate an oauth token 253 | resp, err := svc.client.Call("GET", u, nil, nil) 254 | 255 | return resp, err 256 | } 257 | -------------------------------------------------------------------------------- /vela/authentication_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "net/http" 8 | "net/http/httptest" 9 | "testing" 10 | 11 | "github.com/gin-gonic/gin" 12 | 13 | api "github.com/go-vela/server/api/types" 14 | "github.com/go-vela/server/mock/server" 15 | ) 16 | 17 | func TestVela_Authentication_SetTokenAuth(t *testing.T) { 18 | // setup types 19 | c, _ := NewClient("http://localhost:8080", "", nil) 20 | 21 | // run test 22 | c.Authentication.SetTokenAuth("someToken") 23 | 24 | if !c.Authentication.HasAuth() { 25 | t.Errorf("SetTokenAuth did not set an authentication type") 26 | } 27 | 28 | if !c.Authentication.HasTokenAuth() { 29 | t.Errorf("SetTokenAuth did not set AuthenticationToken type") 30 | } 31 | } 32 | 33 | func TestVela_Authentication_SetBuildTokenAuth(t *testing.T) { 34 | // setup types 35 | c, _ := NewClient("http://localhost:8080", "", nil) 36 | 37 | c.Authentication.SetBuildTokenAuth("buildToken", "scmToken") 38 | 39 | if !c.Authentication.HasAuth() { 40 | t.Errorf("SetBuildTokenAuth did not set an authentication type") 41 | } 42 | 43 | if !c.Authentication.HasBuildTokenAuth() { 44 | t.Errorf("SetBuildTokenAuth did not set BuildToken type") 45 | } 46 | } 47 | 48 | func TestVela_Authentication_SetAccessAndRefreshAuth(t *testing.T) { 49 | // setup types 50 | c, _ := NewClient("http://localhost:8080", "", nil) 51 | 52 | // run test 53 | c.Authentication.SetAccessAndRefreshAuth("someAccessToken", "someRefreshToken") 54 | 55 | if !c.Authentication.HasAuth() { 56 | t.Errorf("SetAccessAndRefreshAuth did not set an authentication type") 57 | } 58 | 59 | if !c.Authentication.HasAccessAndRefreshAuth() { 60 | t.Errorf("SetAccessAndRefreshAuth did not set AccessAndRefreshToken type") 61 | } 62 | } 63 | 64 | func TestVela_Authentication_IsTokenAuthExpired_ValidAuthToken(t *testing.T) { 65 | // setup types 66 | c, _ := NewClient("http://localhost:8080", "", nil) 67 | 68 | // run test 69 | c.Authentication.SetTokenAuth(TestTokenGood) 70 | 71 | expired, err := c.Authentication.IsTokenAuthExpired() 72 | if err != nil { 73 | t.Errorf("IsTokenAuthExpired returned err: %v", err) 74 | } 75 | 76 | if expired { 77 | t.Error("IsTokenAuthExpired returned expired for expired token") 78 | } 79 | } 80 | 81 | func TestVela_Authentication_IsTokenAuthExpired_ExpiredAuthToken(t *testing.T) { 82 | // setup types 83 | c, _ := NewClient("http://localhost:8080", "", nil) 84 | 85 | // run test 86 | c.Authentication.SetTokenAuth(TestTokenExpired) 87 | 88 | expired, err := c.Authentication.IsTokenAuthExpired() 89 | if err != nil { 90 | t.Errorf("IsTokenAuthExpired returned err: %v", err) 91 | } 92 | 93 | if !expired { 94 | t.Error("IsTokenAuthExpired did not return expired for expired token") 95 | } 96 | } 97 | 98 | func TestVela_Authentication_IsTokenAuthExpired_InvalidAuthToken(t *testing.T) { 99 | // setup types 100 | c, _ := NewClient("http://localhost:8080", "", nil) 101 | 102 | // run test 103 | c.Authentication.SetTokenAuth("someToken") 104 | 105 | expired, err := c.Authentication.IsTokenAuthExpired() 106 | if err != nil { 107 | t.Errorf("IsTokenAuthExpired returned err: %v", err) 108 | } 109 | 110 | if !expired { 111 | t.Error("IsTokenAuthExpired did not return expired for invalid token") 112 | } 113 | } 114 | 115 | func TestVela_Authentication_IsTokenAuthExpired_InvalidAuthType(t *testing.T) { 116 | // setup types 117 | c, _ := NewClient("http://localhost:8080", "", nil) 118 | 119 | // run test 120 | c.Authentication.SetPersonalAccessTokenAuth("somePersonalAccessToken") 121 | 122 | expired, err := c.Authentication.IsTokenAuthExpired() 123 | if err == nil { 124 | t.Error("IsTokenAuthExpired did not return err") 125 | } 126 | 127 | if !expired { 128 | t.Error("IsTokenAuthExpired did not return expired for invalid token type") 129 | } 130 | 131 | // run test 132 | c.Authentication.SetAccessAndRefreshAuth("someAccessToken", "someRefreshToken") 133 | 134 | expired, err = c.Authentication.IsTokenAuthExpired() 135 | if err == nil { 136 | t.Error("IsTokenAuthExpired did not return err") 137 | } 138 | 139 | if !expired { 140 | t.Error("IsTokenAuthExpired did not return expired for invalid token type") 141 | } 142 | } 143 | 144 | func TestVela_Authentication_RefreshAccessToken(t *testing.T) { 145 | // setup context 146 | gin.SetMode(gin.TestMode) 147 | 148 | s := httptest.NewServer(server.FakeHandler()) 149 | c, _ := NewClient(s.URL, "", nil) 150 | 151 | data := []byte(server.TokenRefreshResp) 152 | 153 | var want api.Token 154 | 155 | _ = json.Unmarshal(data, &want) 156 | 157 | // run test 158 | resp, err := c.Authentication.RefreshAccessToken("refreshToken") 159 | if err != nil { 160 | t.Errorf("RefreshAccessToken returned err: %v", err) 161 | } 162 | 163 | if resp.StatusCode != http.StatusOK { 164 | t.Errorf("RefreshAccessToken returned %v, want %v", resp.StatusCode, http.StatusOK) 165 | } 166 | 167 | if *c.Authentication.accessToken != want.GetToken() { 168 | t.Errorf("RefreshAccessToken didn't return token") 169 | } 170 | } 171 | 172 | func TestVela_Authentication_AuthenticateWithToken(t *testing.T) { 173 | // setup context 174 | gin.SetMode(gin.TestMode) 175 | 176 | s := httptest.NewServer(server.FakeHandler()) 177 | c, _ := NewClient(s.URL, "", nil) 178 | 179 | data := []byte(server.TokenRefreshResp) 180 | 181 | var want api.Token 182 | 183 | _ = json.Unmarshal(data, &want) 184 | 185 | // run test 186 | at, resp, err := c.Authentication.AuthenticateWithToken("personalaccesstoken") 187 | if err != nil { 188 | t.Errorf("AuthenticateWithToken returned err: %v", err) 189 | } 190 | 191 | if resp.StatusCode != http.StatusOK { 192 | t.Errorf("AuthenticateWithToken returned %v, want %v", resp.StatusCode, http.StatusOK) 193 | } 194 | 195 | if at != want.GetToken() { 196 | t.Errorf("AuthenticateWithToken didn't produce the right Access Token") 197 | } 198 | } 199 | 200 | func TestVela_Authentication_AuthenticateWithToken_NoToken(t *testing.T) { 201 | // setup context 202 | gin.SetMode(gin.TestMode) 203 | 204 | s := httptest.NewServer(server.FakeHandler()) 205 | c, _ := NewClient(s.URL, "", nil) 206 | 207 | // run test 208 | _, resp, err := c.Authentication.AuthenticateWithToken("") 209 | if err == nil { 210 | t.Errorf("AuthenticateWithToken should have returned error") 211 | } 212 | 213 | if resp != nil { 214 | t.Errorf("AuthenticateWithToken should be nil") 215 | } 216 | 217 | if c.Authentication.token != nil { 218 | t.Errorf("AuthenticateWithToken should not be set") 219 | } 220 | } 221 | 222 | func TestVela_Authentication_ExchangeTokens(t *testing.T) { 223 | // setup context 224 | gin.SetMode(gin.TestMode) 225 | 226 | s := httptest.NewServer(server.FakeHandler()) 227 | c, _ := NewClient(s.URL, "", nil) 228 | 229 | data := []byte(server.TokenRefreshResp) 230 | 231 | var want api.Token 232 | 233 | _ = json.Unmarshal(data, &want) 234 | 235 | // create options 236 | opt := &OAuthExchangeOptions{ 237 | Code: "42", 238 | State: "411", 239 | } 240 | 241 | // hardcoded value in mock 242 | wantRefresh := "refresh" 243 | 244 | // run test 245 | at, rt, resp, err := c.Authentication.ExchangeTokens(opt) 246 | if err != nil { 247 | t.Errorf("ExchangeTokens returned err: %v", err) 248 | } 249 | 250 | if resp.StatusCode != http.StatusOK { 251 | t.Errorf("ExchangeTokens returned %v, want %v", resp.StatusCode, http.StatusOK) 252 | } 253 | 254 | if at != want.GetToken() { 255 | t.Errorf("ExchangeTokens didn't produce the right Access Token") 256 | } 257 | 258 | if rt != wantRefresh { 259 | t.Errorf("ExchangeTokens returned unexpected Refresh Token value") 260 | } 261 | 262 | if *c.Authentication.accessToken != want.GetToken() { 263 | t.Errorf("ExchangeTokens didn't produce the right Access Token") 264 | } 265 | 266 | if *c.Authentication.refreshToken != wantRefresh { 267 | t.Errorf("ExchangeTokens didn't produce the right Refresh Token") 268 | } 269 | } 270 | 271 | func TestVela_Authentication_ExchangeTokens_BadInput(t *testing.T) { 272 | // setup context 273 | gin.SetMode(gin.TestMode) 274 | 275 | s := httptest.NewServer(server.FakeHandler()) 276 | c, _ := NewClient(s.URL, "", nil) 277 | 278 | // create options 279 | opt := &OAuthExchangeOptions{} 280 | 281 | // run test 282 | _, _, resp, err := c.Authentication.ExchangeTokens(opt) 283 | if err == nil { 284 | t.Errorf("ExchangeTokens should have returned error: %v", err) 285 | } 286 | 287 | if resp != nil { 288 | t.Errorf("ExchangeTokens should not return resp") 289 | } 290 | 291 | if c.Authentication.accessToken != nil { 292 | t.Errorf("ExchangeTokens should not set Access Token") 293 | } 294 | 295 | if c.Authentication.refreshToken != nil { 296 | t.Errorf("ExchangeTokens should not set Refresh Token") 297 | } 298 | } 299 | 300 | func TestVela_Authentication_ValidateToken_200(t *testing.T) { 301 | // setup context 302 | gin.SetMode(gin.TestMode) 303 | 304 | s := httptest.NewServer(server.FakeHandler()) 305 | c, _ := NewClient(s.URL, "", nil) 306 | 307 | c.Authentication.SetTokenAuth("foo") 308 | 309 | // run test 310 | resp, err := c.Authentication.ValidateToken() 311 | if err != nil { 312 | t.Errorf("ValidateToken returned error %v", err) 313 | } 314 | 315 | if resp.StatusCode != http.StatusOK { 316 | t.Errorf("ValidateToken returned %v, want %v", resp.StatusCode, http.StatusOK) 317 | } 318 | } 319 | 320 | func TestVela_Authentication_ValidateToken_NoToken(t *testing.T) { 321 | // setup context 322 | gin.SetMode(gin.TestMode) 323 | 324 | s := httptest.NewServer(server.FakeHandler()) 325 | c, _ := NewClient(s.URL, "", nil) 326 | 327 | c.Authentication.SetTokenAuth("") 328 | 329 | // run test 330 | resp, err := c.Authentication.ValidateToken() 331 | if err == nil { 332 | t.Error("ValidateToken should have returned error") 333 | } 334 | 335 | if resp != nil { 336 | t.Error("ValidateToken response should be nil") 337 | } 338 | } 339 | 340 | func TestVela_Authentication_ValidateOAuthToken_200(t *testing.T) { 341 | // setup context 342 | gin.SetMode(gin.TestMode) 343 | 344 | s := httptest.NewServer(server.FakeHandler()) 345 | c, _ := NewClient(s.URL, "", nil) 346 | 347 | c.Authentication.SetTokenAuth("foo") 348 | 349 | // run test 350 | resp, err := c.Authentication.ValidateOAuthToken() 351 | if err != nil { 352 | t.Errorf("ValidateOAuthToken returned error %v", err) 353 | } 354 | 355 | if resp.StatusCode != http.StatusOK { 356 | t.Errorf("ValidateOAuthToken returned %v, want %v", resp.StatusCode, http.StatusOK) 357 | } 358 | } 359 | 360 | func TestVela_Authentication_ValidateOAuthToken_NoToken(t *testing.T) { 361 | // setup context 362 | gin.SetMode(gin.TestMode) 363 | 364 | s := httptest.NewServer(server.FakeHandler()) 365 | c, _ := NewClient(s.URL, "", nil) 366 | 367 | c.Authentication.SetTokenAuth("") 368 | 369 | // run test 370 | resp, err := c.Authentication.ValidateOAuthToken() 371 | if err == nil { 372 | t.Error("ValidateOAuthToken should have returned error") 373 | } 374 | 375 | if resp != nil { 376 | t.Error("ValidateOAuthToken response should be nil") 377 | } 378 | } 379 | -------------------------------------------------------------------------------- /vela/build.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // BuildService handles retrieving builds from 12 | // the server methods of the Vela API. 13 | type BuildService service 14 | 15 | // BuildListOptions specifies the optional parameters to the 16 | // Build.GetAll method. 17 | type BuildListOptions struct { 18 | Branch string `url:"branch,omitempty"` 19 | Event string `url:"event,omitempty"` 20 | Status string `url:"status,omitempty"` 21 | Before int64 `url:"before,omitempty"` 22 | After int64 `url:"after,omitempty"` 23 | 24 | ListOptions 25 | } 26 | 27 | // RequestTokenOptions specifies the required parameters to the 28 | // Build.GetIDRequestToken method. 29 | type RequestTokenOptions struct { 30 | Image string `url:"image,omitempty"` 31 | Request string `url:"request,omitempty"` 32 | Commands bool `url:"commands,omitempty"` 33 | } 34 | 35 | // IDTokenOptions specifies the required parameters to the 36 | // Build.GetIDToken method. 37 | type IDTokenOptions struct { 38 | Audience []string `url:"audience,omitempty"` 39 | } 40 | 41 | // Get returns the provided build. 42 | func (svc *BuildService) Get(org, repo string, build int64) (*api.Build, *Response, error) { 43 | // set the API endpoint path we send the request to 44 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d", org, repo, build) 45 | 46 | // API Build type we want to return 47 | v := new(api.Build) 48 | 49 | // send request using client 50 | resp, err := svc.client.Call("GET", u, nil, v) 51 | 52 | return v, resp, err 53 | } 54 | 55 | // GetBuildExecutable returns the executable for the provided build. 56 | func (svc *BuildService) GetBuildExecutable(org, repo string, build int64) (*api.BuildExecutable, *Response, error) { 57 | // set the API endpoint path we send the request to 58 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/executable", org, repo, build) 59 | 60 | // API Build type we want to return 61 | v := new(api.BuildExecutable) 62 | 63 | // send request using client 64 | resp, err := svc.client.Call("GET", u, nil, v) 65 | 66 | return v, resp, err 67 | } 68 | 69 | // GetAll returns a list of all builds. 70 | func (svc *BuildService) GetAll(org, repo string, opt *BuildListOptions) (*[]api.Build, *Response, error) { 71 | // set the API endpoint path we send the request to 72 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds", org, repo) 73 | 74 | // add optional arguments if supplied 75 | u, err := addOptions(u, opt) 76 | if err != nil { 77 | return nil, nil, err 78 | } 79 | 80 | // slice API Build type we want to return 81 | v := new([]api.Build) 82 | 83 | // send request using client 84 | resp, err := svc.client.Call("GET", u, nil, v) 85 | 86 | return v, resp, err 87 | } 88 | 89 | // GetLogs returns the provided build logs. 90 | func (svc *BuildService) GetLogs(org, repo string, build int64, opt *ListOptions) (*[]api.Log, *Response, error) { 91 | // set the API endpoint path we send the request to 92 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/logs", org, repo, build) 93 | 94 | // add optional arguments if supplied 95 | u, err := addOptions(u, opt) 96 | if err != nil { 97 | return nil, nil, err 98 | } 99 | 100 | // slice database Log type we want to return 101 | v := new([]api.Log) 102 | 103 | // send request using client 104 | resp, err := svc.client.Call("GET", u, nil, v) 105 | 106 | return v, resp, err 107 | } 108 | 109 | // Add constructs a build with the provided details. 110 | func (svc *BuildService) Add(b *api.Build) (*api.Build, *Response, error) { 111 | // set the API endpoint path we send the request to 112 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds", b.GetRepo().GetOrg(), b.GetRepo().GetName()) 113 | 114 | // API Build type we want to return 115 | v := new(api.Build) 116 | 117 | // send request using client 118 | resp, err := svc.client.Call("POST", u, b, v) 119 | 120 | return v, resp, err 121 | } 122 | 123 | // Update modifies a build with the provided details. 124 | func (svc *BuildService) Update(b *api.Build) (*api.Build, *Response, error) { 125 | // set the API endpoint path we send the request to 126 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d", b.GetRepo().GetOrg(), b.GetRepo().GetName(), b.GetNumber()) 127 | 128 | // API Build type we want to return 129 | v := new(api.Build) 130 | 131 | // send request using client 132 | resp, err := svc.client.Call("PUT", u, b, v) 133 | 134 | return v, resp, err 135 | } 136 | 137 | // Remove deletes the provided build. 138 | func (svc *BuildService) Remove(org, repo string, build int) (*string, *Response, error) { 139 | // set the API endpoint path we send the request to 140 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d", org, repo, build) 141 | 142 | // string type we want to return 143 | v := new(string) 144 | 145 | // send request using client 146 | resp, err := svc.client.Call("DELETE", u, nil, v) 147 | 148 | return v, resp, err 149 | } 150 | 151 | // Restart takes the build provided and restarts it. 152 | func (svc *BuildService) Restart(org, repo string, build int64) (*api.Build, *Response, error) { 153 | // set the API endpoint path we send the request to 154 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d", org, repo, build) 155 | 156 | // API Build type we want to return 157 | v := new(api.Build) 158 | 159 | // send request using client 160 | resp, err := svc.client.Call("POST", u, nil, v) 161 | 162 | return v, resp, err 163 | } 164 | 165 | // Cancel takes the build provided and cancels it. 166 | func (svc *BuildService) Cancel(org, repo string, build int64) (*api.Build, *Response, error) { 167 | // set the API endpoint path we send the request to 168 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/cancel", org, repo, build) 169 | 170 | // API Build type we want to return 171 | v := new(api.Build) 172 | 173 | // send request using client 174 | resp, err := svc.client.Call("DELETE", u, nil, v) 175 | 176 | return v, resp, err 177 | } 178 | 179 | // Approve takes the build provided and approves it as an admin. 180 | func (svc *BuildService) Approve(org, repo string, build int64) (*Response, error) { 181 | // set the API endpoint path we send the request to 182 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/approve", org, repo, build) 183 | 184 | return svc.client.Call("POST", u, nil, nil) 185 | } 186 | 187 | // GetBuildToken returns an auth token for updating build resources. 188 | func (svc *BuildService) GetBuildToken(org, repo string, build int64) (*api.Token, *Response, error) { 189 | // set the API endpoint path we send the request to 190 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/token", org, repo, build) 191 | 192 | // API Token type we want to return 193 | t := new(api.Token) 194 | 195 | // send request using client 196 | resp, err := svc.client.Call("GET", u, nil, t) 197 | 198 | return t, resp, err 199 | } 200 | 201 | // GetIDRequestToken returns an id request token for integrating with build OIDC. 202 | func (svc *BuildService) GetIDRequestToken(org, repo string, build int64, opt *RequestTokenOptions) (*api.Token, *Response, error) { 203 | // set the API endpoint path we send the request to 204 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/id_request_token", org, repo, build) 205 | 206 | // add optional arguments if supplied 207 | u, err := addOptions(u, opt) 208 | if err != nil { 209 | return nil, nil, err 210 | } 211 | 212 | // API Token type we want to return 213 | t := new(api.Token) 214 | 215 | // send request using client 216 | resp, err := svc.client.Call("GET", u, nil, t) 217 | 218 | return t, resp, err 219 | } 220 | 221 | // GetIDToken returns an ID token corresponding to the request token during a build. 222 | func (svc *BuildService) GetIDToken(org, repo string, build int, opt *IDTokenOptions) (*api.Token, *Response, error) { 223 | // set the API endpoint path we send the request to 224 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/id_token", org, repo, build) 225 | 226 | // add optional arguments if supplied 227 | u, err := addOptions(u, opt) 228 | if err != nil { 229 | return nil, nil, err 230 | } 231 | 232 | // API Token type we want to return 233 | t := new(api.Token) 234 | 235 | // send request using client 236 | resp, err := svc.client.Call("GET", u, nil, t) 237 | 238 | return t, resp, err 239 | } 240 | -------------------------------------------------------------------------------- /vela/context.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "context" 7 | ) 8 | 9 | // contextKey defines the key type for 10 | // storing database types in a context. 11 | type contextKey int 12 | 13 | // key defines the key type for 14 | // storing the Vela client type in a context. 15 | const key contextKey = iota 16 | 17 | // FromContext returns the Client associated with this context. 18 | func FromContext(c context.Context) *Client { 19 | // get client value from context 20 | v := c.Value(key) 21 | if v == nil { 22 | return nil 23 | } 24 | 25 | // cast client value to expected Client type 26 | cli, ok := v.(*Client) 27 | if !ok { 28 | return nil 29 | } 30 | 31 | return cli 32 | } 33 | 34 | // ToContext adds the Client to the context. 35 | func ToContext(c context.Context, cli *Client) context.Context { 36 | return context.WithValue(c, key, cli) 37 | } 38 | -------------------------------------------------------------------------------- /vela/context_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "context" 7 | "testing" 8 | ) 9 | 10 | func TestVela_FromContext(t *testing.T) { 11 | // setup types 12 | want := &Client{} 13 | 14 | // setup context 15 | ctx := context.Background() 16 | ctx = context.WithValue(ctx, key, want) 17 | 18 | // run test 19 | got := FromContext(ctx) 20 | 21 | if got != want { 22 | t.Errorf("FromContext is %v, want %v", got, want) 23 | } 24 | } 25 | 26 | func TestVela_FromContext_InvalidType(t *testing.T) { 27 | // setup context 28 | ctx := context.Background() 29 | ctx = context.WithValue(ctx, key, "foobar") 30 | 31 | // run test 32 | got := FromContext(ctx) 33 | 34 | if got != nil { 35 | t.Errorf("FromContext is %v, want nil", got) 36 | } 37 | } 38 | 39 | func TestVela_FromContext_Empty(t *testing.T) { 40 | // setup context 41 | ctx := context.Background() 42 | 43 | // run test 44 | got := FromContext(ctx) 45 | 46 | if got != nil { 47 | t.Errorf("FromContext is %v, want nil", got) 48 | } 49 | } 50 | 51 | func TestVela_ToContext(t *testing.T) { 52 | // setup types 53 | want := &Client{} 54 | 55 | // setup context 56 | ctx := context.Background() 57 | ctx = ToContext(ctx, want) 58 | 59 | // run test 60 | got := ctx.Value(key).(*Client) 61 | 62 | if got != want { 63 | t.Errorf("ToContext is %v, want %v", got, want) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /vela/dashboard.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // DashboardService handles retrieving Dashboards from 12 | // the server methods of the Vela API. 13 | type DashboardService service 14 | 15 | // Get returns the provided Dashboard. 16 | func (svc *DashboardService) Get(dashboard string) (*api.DashCard, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/dashboards/%s", dashboard) 19 | 20 | // API Dashboard type we want to return 21 | v := new(api.DashCard) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetAllUser returns a list of all dashboards for the authenticated user. 30 | func (svc *DashboardService) GetAllUser() (*[]api.DashCard, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := "/api/v1/user/dashboards" 33 | 34 | // slice API Dashboard type we want to return 35 | v := new([]api.DashCard) 36 | 37 | // send request using client 38 | resp, err := svc.client.Call("GET", u, nil, v) 39 | 40 | return v, resp, err 41 | } 42 | 43 | // Add constructs a Dashboard with the provided details. 44 | func (svc *DashboardService) Add(d *api.Dashboard) (*api.Dashboard, *Response, error) { 45 | // set the API endpoint path we send the request to 46 | u := "/api/v1/dashboards" 47 | 48 | // api dashboard type we want to return 49 | v := new(api.Dashboard) 50 | 51 | // send request using client 52 | resp, err := svc.client.Call("POST", u, d, v) 53 | 54 | return v, resp, err 55 | } 56 | 57 | // Update modifies a dashboard with the provided details. 58 | func (svc *DashboardService) Update(d *api.Dashboard) (*api.Dashboard, *Response, error) { 59 | // set the API endpoint path we send the request to 60 | u := fmt.Sprintf("/api/v1/dashboards/%s", d.GetID()) 61 | 62 | // API dashboard type we want to return 63 | v := new(api.Dashboard) 64 | 65 | // send request using client 66 | resp, err := svc.client.Call("PUT", u, d, v) 67 | 68 | return v, resp, err 69 | } 70 | -------------------------------------------------------------------------------- /vela/dashboard_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "net/http" 8 | "net/http/httptest" 9 | "reflect" 10 | "testing" 11 | 12 | "github.com/gin-gonic/gin" 13 | 14 | api "github.com/go-vela/server/api/types" 15 | "github.com/go-vela/server/mock/server" 16 | ) 17 | 18 | func TestDashboard_Get_200(t *testing.T) { 19 | // setup context 20 | gin.SetMode(gin.TestMode) 21 | 22 | s := httptest.NewServer(server.FakeHandler()) 23 | c, _ := NewClient(s.URL, "", nil) 24 | 25 | data := []byte(server.DashCardResp) 26 | 27 | var want api.DashCard 28 | 29 | err := json.Unmarshal(data, &want) 30 | if err != nil { 31 | t.Errorf("unable to unmarshal data: %v", err) 32 | } 33 | 34 | // run test 35 | got, resp, err := c.Dashboard.Get("c976470d-34c1-49b2-9a98-1035871c576b") 36 | if err != nil { 37 | t.Errorf("New returned err: %v", err) 38 | } 39 | 40 | if resp.StatusCode != http.StatusOK { 41 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 42 | } 43 | 44 | if !reflect.DeepEqual(got, &want) { 45 | t.Errorf("Get is %v, want %v", got, want) 46 | } 47 | } 48 | 49 | func TestDashboard_Get_404(t *testing.T) { 50 | // setup context 51 | gin.SetMode(gin.TestMode) 52 | 53 | s := httptest.NewServer(server.FakeHandler()) 54 | c, _ := NewClient(s.URL, "", nil) 55 | 56 | want := api.DashCard{} 57 | 58 | // run test 59 | got, resp, err := c.Dashboard.Get("0") 60 | if err == nil { 61 | t.Errorf("Get returned err: %v", err) 62 | } 63 | 64 | if resp.StatusCode != http.StatusNotFound { 65 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 66 | } 67 | 68 | if !reflect.DeepEqual(got, &want) { 69 | t.Errorf("Get is %v, want %v", got, want) 70 | } 71 | } 72 | 73 | func TestDashboard_GetAllUser_200(t *testing.T) { 74 | // setup context 75 | gin.SetMode(gin.TestMode) 76 | 77 | s := httptest.NewServer(server.FakeHandler()) 78 | c, _ := NewClient(s.URL, "", nil) 79 | 80 | data := []byte(server.DashCardsResp) 81 | 82 | var want []api.DashCard 83 | 84 | _ = json.Unmarshal(data, &want) 85 | 86 | // run test 87 | got, resp, err := c.Dashboard.GetAllUser() 88 | if err != nil { 89 | t.Errorf("GetAllUser returned err: %v", err) 90 | } 91 | 92 | if resp.StatusCode != http.StatusOK { 93 | t.Errorf("GetAllUser returned %v, want %v", resp.StatusCode, http.StatusOK) 94 | } 95 | 96 | if !reflect.DeepEqual(got, &want) { 97 | t.Errorf("GetAllUser is %v, want %v", got, want) 98 | } 99 | } 100 | 101 | func TestDashboard_Add_201(t *testing.T) { 102 | // setup context 103 | gin.SetMode(gin.TestMode) 104 | 105 | s := httptest.NewServer(server.FakeHandler()) 106 | c, _ := NewClient(s.URL, "", nil) 107 | 108 | data := []byte(server.DashboardResp) 109 | 110 | var want api.Dashboard 111 | 112 | _ = json.Unmarshal(data, &want) 113 | 114 | // run test 115 | got, resp, err := c.Dashboard.Add(&want) 116 | if err != nil { 117 | t.Errorf("Add returned err: %v", err) 118 | } 119 | 120 | if resp.StatusCode != http.StatusCreated { 121 | t.Errorf("Add returned %v, want %v", resp.StatusCode, http.StatusOK) 122 | } 123 | 124 | if !reflect.DeepEqual(got, &want) { 125 | t.Errorf("Add is %v, want %v", got, want) 126 | } 127 | } 128 | 129 | func TestDashboard_Update_200(t *testing.T) { 130 | // setup context 131 | gin.SetMode(gin.TestMode) 132 | 133 | s := httptest.NewServer(server.FakeHandler()) 134 | c, _ := NewClient(s.URL, "", nil) 135 | 136 | data := []byte(server.DashboardResp) 137 | 138 | var want api.Dashboard 139 | 140 | _ = json.Unmarshal(data, &want) 141 | 142 | // run test 143 | got, resp, err := c.Dashboard.Update(&want) 144 | if err != nil { 145 | t.Errorf("Update returned err: %v", err) 146 | } 147 | 148 | if resp.StatusCode != http.StatusOK { 149 | t.Errorf("Update returned %v, want %v", resp.StatusCode, http.StatusOK) 150 | } 151 | 152 | if !reflect.DeepEqual(got, &want) { 153 | t.Errorf("Update is %v, want %v", got, want) 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /vela/deployment.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // DeploymentService handles retrieving deployments from 12 | // the server methods of the Vela API. 13 | type DeploymentService service 14 | 15 | // Get returns the provided deployment. 16 | func (svc *DeploymentService) Get(org, repo string, deployment int64) (*api.Deployment, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/deployments/%s/%s/%d", org, repo, deployment) 19 | 20 | // API Deployment type we want to return 21 | v := new(api.Deployment) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetAll returns a list of all deployments. 30 | func (svc *DeploymentService) GetAll(org, repo string, opt *ListOptions) (*[]api.Deployment, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := fmt.Sprintf("/api/v1/deployments/%s/%s", org, repo) 33 | 34 | // add optional arguments if supplied 35 | u, err := addOptions(u, opt) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | // slice API Deployment type we want to return 41 | v := new([]api.Deployment) 42 | 43 | // send request using client 44 | resp, err := svc.client.Call("GET", u, nil, v) 45 | 46 | return v, resp, err 47 | } 48 | 49 | // Add constructs a deployment with the provided details. 50 | func (svc *DeploymentService) Add(org, repo string, d *api.Deployment) (*api.Deployment, *Response, error) { 51 | // set the API endpoint path we send the request to 52 | u := fmt.Sprintf("/api/v1/deployments/%s/%s", org, repo) 53 | 54 | // API Deployment type we want to return 55 | v := new(api.Deployment) 56 | 57 | // send request using client 58 | resp, err := svc.client.Call("POST", u, d, v) 59 | 60 | return v, resp, err 61 | } 62 | -------------------------------------------------------------------------------- /vela/deployment_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/gin-gonic/gin" 14 | "github.com/google/go-cmp/cmp" 15 | 16 | api "github.com/go-vela/server/api/types" 17 | "github.com/go-vela/server/mock/server" 18 | ) 19 | 20 | func TestDeployment_Get_200(t *testing.T) { 21 | // setup context 22 | gin.SetMode(gin.TestMode) 23 | 24 | s := httptest.NewServer(server.FakeHandler()) 25 | c, _ := NewClient(s.URL, "", nil) 26 | 27 | data := []byte(server.DeploymentResp) 28 | 29 | var want api.Deployment 30 | 31 | _ = json.Unmarshal(data, &want) 32 | 33 | // run test 34 | got, resp, err := c.Deployment.Get("github", "octocat", 1) 35 | if err != nil { 36 | t.Errorf("New returned err: %v", err) 37 | } 38 | 39 | if resp.StatusCode != http.StatusOK { 40 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 41 | } 42 | 43 | if diff := cmp.Diff(&want, got); diff != "" { 44 | t.Errorf("Get mismatch (-want +got):\n%s", diff) 45 | } 46 | } 47 | 48 | func TestDeployment_Get_404(t *testing.T) { 49 | // setup context 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | want := api.Deployment{} 56 | 57 | // run test 58 | got, resp, err := c.Deployment.Get("github", "octocat", 0) 59 | if err == nil { 60 | t.Errorf("New returned err: %v", err) 61 | } 62 | 63 | if resp.StatusCode != http.StatusNotFound { 64 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 65 | } 66 | 67 | if !reflect.DeepEqual(got, &want) { 68 | t.Errorf("Get is %v, want %v", got, want) 69 | } 70 | } 71 | 72 | func TestDeployment_GetAll_200(t *testing.T) { 73 | // setup context 74 | gin.SetMode(gin.TestMode) 75 | 76 | s := httptest.NewServer(server.FakeHandler()) 77 | c, _ := NewClient(s.URL, "", nil) 78 | 79 | data := []byte(server.DeploymentsResp) 80 | 81 | var want []api.Deployment 82 | 83 | _ = json.Unmarshal(data, &want) 84 | 85 | // run test 86 | got, resp, err := c.Deployment.GetAll("github", "octocat", nil) 87 | if err != nil { 88 | t.Errorf("New returned err: %v", err) 89 | } 90 | 91 | if resp.StatusCode != http.StatusOK { 92 | t.Errorf("GetAll returned %v, want %v", resp.StatusCode, http.StatusOK) 93 | } 94 | 95 | if !reflect.DeepEqual(got, &want) { 96 | t.Errorf("GetAll is %v, want %v", got, want) 97 | } 98 | } 99 | 100 | func TestDeployment_Add_201(t *testing.T) { 101 | // setup context 102 | gin.SetMode(gin.TestMode) 103 | 104 | s := httptest.NewServer(server.FakeHandler()) 105 | c, _ := NewClient(s.URL, "", nil) 106 | 107 | data := []byte(server.DeploymentResp) 108 | 109 | var want api.Deployment 110 | 111 | _ = json.Unmarshal(data, &want) 112 | 113 | req := api.Deployment{ 114 | Commit: String("48afb5bdc41ad69bf22588491333f7cf71135163"), 115 | Ref: String("refs/heads/main"), 116 | Task: String("vela-deploy"), 117 | Target: String("production"), 118 | Description: String("Deployment request from Vela"), 119 | } 120 | 121 | // run test 122 | got, resp, err := c.Deployment.Add("github", "octocat", &req) 123 | if err != nil { 124 | t.Errorf("New returned err: %v", err) 125 | } 126 | 127 | if resp.StatusCode != http.StatusCreated { 128 | t.Errorf("Add returned %v, want %v", resp.StatusCode, http.StatusOK) 129 | } 130 | 131 | if !reflect.DeepEqual(got, &want) { 132 | t.Errorf("Add is %v, want %v", got, want) 133 | } 134 | } 135 | 136 | func ExampleDeploymentService_Get() { 137 | // Create a new vela client for interacting with server 138 | c, _ := NewClient("http://localhost:8080", "", nil) 139 | 140 | // Set new token in existing client 141 | c.Authentication.SetPersonalAccessTokenAuth("token") 142 | 143 | // Get a build from the server 144 | deployment, resp, err := c.Deployment.Get("github", "octocat", 1) 145 | if err != nil { 146 | fmt.Println(err) 147 | } 148 | 149 | fmt.Printf("Received response code %d, for deployment %+v", resp.StatusCode, deployment) 150 | } 151 | 152 | func ExampleDeploymentService_GetAll() { 153 | // Create a new vela client for interacting with server 154 | c, _ := NewClient("http://localhost:8080", "", nil) 155 | 156 | // Set new token in existing client 157 | c.Authentication.SetPersonalAccessTokenAuth("token") 158 | 159 | // Get all the deployments from the server 160 | deployments, resp, err := c.Deployment.GetAll("github", "octocat", nil) 161 | if err != nil { 162 | fmt.Println(err) 163 | } 164 | 165 | fmt.Printf("Received response code %d, for deployments %+v", resp.StatusCode, deployments) 166 | } 167 | 168 | func ExampleDeploymentService_Add() { 169 | // Create a new vela client for interacting with server 170 | c, _ := NewClient("http://localhost:8080", "", nil) 171 | 172 | // Set new token in existing client 173 | c.Authentication.SetPersonalAccessTokenAuth("token") 174 | 175 | req := api.Deployment{ 176 | Commit: String("48afb5bdc41ad69bf22588491333f7cf71135163"), 177 | Ref: String("refs/heads/main"), 178 | Task: String("vela-deploy"), 179 | Target: String("production"), 180 | Description: String("Deployment request from Vela"), 181 | } 182 | 183 | // Create the deployment in the server 184 | deployment, resp, err := c.Deployment.Add("github", "octocat", &req) 185 | if err != nil { 186 | fmt.Println(err) 187 | } 188 | 189 | fmt.Printf("Received response code %d, for deployment %+v", resp.StatusCode, deployment) 190 | } 191 | -------------------------------------------------------------------------------- /vela/doc.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | // Package vela provides a client for using the Vela API. 4 | // 5 | // Usage: 6 | // 7 | // import "github.com/go-vela/sdk-go/vela" 8 | package vela 9 | -------------------------------------------------------------------------------- /vela/hook.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // HookService handles retrieving hooks from 12 | // the server methods of the Vela API. 13 | type HookService service 14 | 15 | // Get returns the provided hook. 16 | func (svc *HookService) Get(org, repo string, hook int64) (*api.Hook, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/hooks/%s/%s/%d", org, repo, hook) 19 | 20 | // API Hook type we want to return 21 | v := new(api.Hook) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetAll returns a list of all hooks. 30 | func (svc *HookService) GetAll(org, repo string, opt *ListOptions) (*[]api.Hook, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := fmt.Sprintf("/api/v1/hooks/%s/%s", org, repo) 33 | 34 | // add optional arguments if supplied 35 | u, err := addOptions(u, opt) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | // slice API Hook type we want to return 41 | v := new([]api.Hook) 42 | 43 | // send request using client 44 | resp, err := svc.client.Call("GET", u, nil, v) 45 | 46 | return v, resp, err 47 | } 48 | 49 | // Add constructs a hook with the provided details. 50 | func (svc *HookService) Add(org, repo string, h *api.Hook) (*api.Hook, *Response, error) { 51 | // set the API endpoint path we send the request to 52 | u := fmt.Sprintf("/api/v1/hooks/%s/%s", org, repo) 53 | 54 | // API Hook type we want to return 55 | v := new(api.Hook) 56 | 57 | // send request using client 58 | resp, err := svc.client.Call("POST", u, h, v) 59 | 60 | return v, resp, err 61 | } 62 | 63 | // Update modifies a hook with the provided details. 64 | func (svc *HookService) Update(org, repo string, h *api.Hook) (*api.Hook, *Response, error) { 65 | // set the API endpoint path we send the request to 66 | u := fmt.Sprintf("/api/v1/hooks/%s/%s/%d", org, repo, h.GetNumber()) 67 | 68 | // API Hook type we want to return 69 | v := new(api.Hook) 70 | 71 | // send request using client 72 | resp, err := svc.client.Call("PUT", u, h, v) 73 | 74 | return v, resp, err 75 | } 76 | 77 | // Remove deletes the provided hook. 78 | func (svc *HookService) Remove(org, repo string, hook int64) (*string, *Response, error) { 79 | // set the API endpoint path we send the request to 80 | u := fmt.Sprintf("/api/v1/hooks/%s/%s/%d", org, repo, hook) 81 | 82 | // string type we want to return 83 | v := new(string) 84 | 85 | // send request using client 86 | resp, err := svc.client.Call("DELETE", u, nil, v) 87 | 88 | return v, resp, err 89 | } 90 | -------------------------------------------------------------------------------- /vela/hook_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/gin-gonic/gin" 14 | 15 | api "github.com/go-vela/server/api/types" 16 | "github.com/go-vela/server/mock/server" 17 | ) 18 | 19 | func TestHook_Get_200(t *testing.T) { 20 | // setup context 21 | gin.SetMode(gin.TestMode) 22 | 23 | s := httptest.NewServer(server.FakeHandler()) 24 | c, _ := NewClient(s.URL, "", nil) 25 | 26 | data := []byte(server.HookResp) 27 | 28 | var want api.Hook 29 | 30 | _ = json.Unmarshal(data, &want) 31 | 32 | // run test 33 | got, resp, err := c.Hook.Get("github", "octocat", 1) 34 | if err != nil { 35 | t.Errorf("New returned err: %v", err) 36 | } 37 | 38 | if resp.StatusCode != http.StatusOK { 39 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 40 | } 41 | 42 | if !reflect.DeepEqual(got, &want) { 43 | t.Errorf("Get is %v, want %v", got, want) 44 | } 45 | } 46 | 47 | func TestHook_Get_404(t *testing.T) { 48 | // setup context 49 | gin.SetMode(gin.TestMode) 50 | 51 | s := httptest.NewServer(server.FakeHandler()) 52 | c, _ := NewClient(s.URL, "", nil) 53 | 54 | want := api.Hook{} 55 | 56 | // run test 57 | got, resp, err := c.Hook.Get("github", "octocat", 0) 58 | if err == nil { 59 | t.Errorf("New returned err: %v", err) 60 | } 61 | 62 | if resp.StatusCode != http.StatusNotFound { 63 | t.Errorf("Get returned %v, want %v", resp.StatusCode, http.StatusOK) 64 | } 65 | 66 | if !reflect.DeepEqual(got, &want) { 67 | t.Errorf("Get is %v, want %v", got, want) 68 | } 69 | } 70 | 71 | func TestHook_GetAll_200(t *testing.T) { 72 | // setup context 73 | gin.SetMode(gin.TestMode) 74 | 75 | s := httptest.NewServer(server.FakeHandler()) 76 | c, _ := NewClient(s.URL, "", nil) 77 | 78 | data := []byte(server.HooksResp) 79 | 80 | var want []api.Hook 81 | 82 | _ = json.Unmarshal(data, &want) 83 | 84 | // run test 85 | got, resp, err := c.Hook.GetAll("github", "octocat", nil) 86 | if err != nil { 87 | t.Errorf("New returned err: %v", err) 88 | } 89 | 90 | if resp.StatusCode != http.StatusOK { 91 | t.Errorf("GetAll returned %v, want %v", resp.StatusCode, http.StatusOK) 92 | } 93 | 94 | if !reflect.DeepEqual(got, &want) { 95 | t.Errorf("GetAll is %v, want %v", got, want) 96 | } 97 | } 98 | 99 | func TestHook_Add_201(t *testing.T) { 100 | // setup context 101 | gin.SetMode(gin.TestMode) 102 | 103 | s := httptest.NewServer(server.FakeHandler()) 104 | c, _ := NewClient(s.URL, "", nil) 105 | 106 | data := []byte(server.HookResp) 107 | 108 | var want api.Hook 109 | 110 | _ = json.Unmarshal(data, &want) 111 | 112 | req := api.Hook{ 113 | Number: Int64(1), 114 | SourceID: String("c8da1302-07d6-11ea-882f-4893bca275b8"), 115 | Event: String("push"), 116 | Status: String("created"), 117 | Error: String(""), 118 | Created: Int64(1563474076), 119 | Link: String("https://github.com/github/octocat/settings/hooks/1"), 120 | Branch: String("main"), 121 | Host: String("github.com"), 122 | } 123 | 124 | // run test 125 | got, resp, err := c.Hook.Add("github", "octocat", &req) 126 | if err != nil { 127 | t.Errorf("New returned err: %v", err) 128 | } 129 | 130 | if resp.StatusCode != http.StatusCreated { 131 | t.Errorf("Add returned %v, want %v", resp.StatusCode, http.StatusOK) 132 | } 133 | 134 | if !reflect.DeepEqual(got, &want) { 135 | t.Errorf("Add add is %v, want %v", got, want) 136 | } 137 | } 138 | 139 | func TestHook_Update_200(t *testing.T) { 140 | // setup context 141 | gin.SetMode(gin.TestMode) 142 | 143 | s := httptest.NewServer(server.FakeHandler()) 144 | c, _ := NewClient(s.URL, "", nil) 145 | 146 | data := []byte(server.HookResp) 147 | 148 | var want api.Hook 149 | 150 | _ = json.Unmarshal(data, &want) 151 | 152 | req := api.Hook{ 153 | Number: Int64(1), 154 | Event: String("push"), 155 | Status: String("success"), 156 | } 157 | 158 | // run test 159 | got, resp, err := c.Hook.Update("github", "octocat", &req) 160 | if err != nil { 161 | t.Errorf("New returned err: %v", err) 162 | } 163 | 164 | if resp.StatusCode != http.StatusOK { 165 | t.Errorf("Update returned %v, want %v", resp.StatusCode, http.StatusOK) 166 | } 167 | 168 | if !reflect.DeepEqual(got, &want) { 169 | t.Errorf("Update is %v, want %v", got, want) 170 | } 171 | } 172 | 173 | func TestHook_Update_404(t *testing.T) { 174 | // setup context 175 | gin.SetMode(gin.TestMode) 176 | 177 | s := httptest.NewServer(server.FakeHandler()) 178 | c, _ := NewClient(s.URL, "", nil) 179 | 180 | want := api.Hook{} 181 | 182 | req := api.Hook{ 183 | Number: Int64(0), 184 | Event: String("push"), 185 | Status: String("running"), 186 | } 187 | 188 | // run test 189 | got, resp, err := c.Hook.Update("github", "octocat", &req) 190 | if err == nil { 191 | t.Errorf("New returned err: %v", err) 192 | } 193 | 194 | if resp.StatusCode != http.StatusNotFound { 195 | t.Errorf("Update returned %v, want %v", resp.StatusCode, http.StatusOK) 196 | } 197 | 198 | if !reflect.DeepEqual(got, &want) { 199 | t.Errorf("Update is %v, want %v", got, want) 200 | } 201 | } 202 | 203 | func TestHook_Remove_200(t *testing.T) { 204 | // setup context 205 | gin.SetMode(gin.TestMode) 206 | 207 | s := httptest.NewServer(server.FakeHandler()) 208 | c, _ := NewClient(s.URL, "", nil) 209 | 210 | // run test 211 | _, resp, err := c.Hook.Remove("github", "octocat", 1) 212 | if err != nil { 213 | t.Errorf("New returned err: %v", err) 214 | } 215 | 216 | if resp.StatusCode != http.StatusOK { 217 | t.Errorf("Remove returned %v, want %v", resp.StatusCode, http.StatusOK) 218 | } 219 | } 220 | 221 | func TestHook_Remove_404(t *testing.T) { 222 | // setup context 223 | gin.SetMode(gin.TestMode) 224 | 225 | s := httptest.NewServer(server.FakeHandler()) 226 | c, _ := NewClient(s.URL, "", nil) 227 | 228 | // run test 229 | _, resp, err := c.Hook.Remove("github", "octocat", 0) 230 | if err == nil { 231 | t.Errorf("New returned err: %v", err) 232 | } 233 | 234 | if resp.StatusCode != http.StatusNotFound { 235 | t.Errorf("Remove returned %v, want %v", resp.StatusCode, http.StatusOK) 236 | } 237 | } 238 | 239 | func ExampleHookService_Get() { 240 | // Create a new vela client for interacting with server 241 | c, _ := NewClient("http://localhost:8080", "", nil) 242 | 243 | // Set new token in existing client 244 | c.Authentication.SetPersonalAccessTokenAuth("token") 245 | 246 | // Get a hook from the server 247 | hook, resp, err := c.Hook.Get("github", "octocat", 1) 248 | if err != nil { 249 | fmt.Println(err) 250 | } 251 | 252 | fmt.Printf("Received response code %d, for hook %+v", resp.StatusCode, hook) 253 | } 254 | 255 | func ExampleHookService_GetAll() { 256 | // Create a new vela client for interacting with server 257 | c, _ := NewClient("http://localhost:8080", "", nil) 258 | 259 | // Set new token in existing client 260 | c.Authentication.SetPersonalAccessTokenAuth("token") 261 | 262 | // Get all the hooks from the server 263 | hooks, resp, err := c.Hook.GetAll("github", "octocat", nil) 264 | if err != nil { 265 | fmt.Println(err) 266 | } 267 | 268 | fmt.Printf("Received response code %d, for hooks %+v", resp.StatusCode, hooks) 269 | } 270 | 271 | func ExampleHookService_Add() { 272 | // Create a new vela client for interacting with server 273 | c, _ := NewClient("http://localhost:8080", "", nil) 274 | 275 | // Set new token in existing client 276 | c.Authentication.SetPersonalAccessTokenAuth("token") 277 | 278 | req := api.Hook{ 279 | Number: Int64(1), 280 | SourceID: String("c8da1302-07d6-11ea-882f-4893bca275b8"), 281 | Event: String("push"), 282 | Status: String("created"), 283 | Error: String(""), 284 | Created: Int64(1563474076), 285 | Link: String("https://github.com/github/octocat/settings/hooks/1"), 286 | Branch: String("main"), 287 | Host: String("github.com"), 288 | } 289 | 290 | // Create the hook in the server 291 | hook, resp, err := c.Hook.Add("github", "octocat", &req) 292 | if err != nil { 293 | fmt.Println(err) 294 | } 295 | 296 | fmt.Printf("Received response code %d, for hook %+v", resp.StatusCode, hook) 297 | } 298 | 299 | func ExampleHookService_Update() { 300 | // Create a new vela client for interacting with server 301 | c, _ := NewClient("http://localhost:8080", "", nil) 302 | 303 | // Set new token in existing client 304 | c.Authentication.SetPersonalAccessTokenAuth("token") 305 | 306 | req := api.Hook{ 307 | Status: String("error"), 308 | Error: String(""), 309 | } 310 | 311 | // Update the step in the server 312 | hook, resp, err := c.Hook.Update("github", "octocat", &req) 313 | if err != nil { 314 | fmt.Println(err) 315 | } 316 | 317 | fmt.Printf("Received response code %d, for hook %+v", resp.StatusCode, hook) 318 | } 319 | 320 | func ExampleHookService_Remove() { 321 | // Create a new vela client for interacting with server 322 | c, _ := NewClient("http://localhost:8080", "", nil) 323 | 324 | // Set new token in existing client 325 | c.Authentication.SetPersonalAccessTokenAuth("token") 326 | 327 | // Remove the hook in the server 328 | hook, resp, err := c.Hook.Remove("github", "octocat", 1) 329 | if err != nil { 330 | fmt.Println(err) 331 | } 332 | 333 | fmt.Printf("Received response code %d, for step %+v", resp.StatusCode, hook) 334 | } 335 | -------------------------------------------------------------------------------- /vela/jwt.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "time" 7 | 8 | jwt "github.com/golang-jwt/jwt/v5" 9 | ) 10 | 11 | // IsTokenExpired will parse the expiration of the the given 12 | // token and return a boolean depending on whether the is 13 | // expired given the delta. 14 | func IsTokenExpired(token string) bool { 15 | minTimeLeft := 10 * time.Second 16 | 17 | // if the token is empty, we treat it as expired 18 | if len(token) == 0 { 19 | return true 20 | } 21 | 22 | // parse the token, we just want to check expiration - 23 | // the server will handle verification 24 | t, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{}) 25 | if err != nil { 26 | return true 27 | } 28 | 29 | // get the claims 30 | c, ok := t.Claims.(jwt.MapClaims) 31 | if !ok { 32 | return true 33 | } 34 | 35 | // if there is no expiration set, it's expired 36 | if _, ok := c["exp"]; !ok { 37 | return true 38 | } 39 | 40 | // check the expiration 41 | expiration := time.Unix(int64(c["exp"].(float64)), 0) 42 | 43 | // get the difference 44 | timeLeft := time.Until(expiration) 45 | 46 | // return whether we are within the delta time padding 47 | return timeLeft.Seconds() <= minTimeLeft.Seconds() 48 | } 49 | -------------------------------------------------------------------------------- /vela/jwt_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | "time" 9 | 10 | jwt "github.com/golang-jwt/jwt/v5" 11 | ) 12 | 13 | var ( 14 | TestTokenGood = makeSampleToken(jwt.MapClaims{"exp": float64(time.Now().Unix() + 100)}) 15 | TestTokenExpired = makeSampleToken(jwt.MapClaims{"exp": float64(time.Now().Unix() - 100)}) 16 | ) 17 | 18 | func TestIsTokenExpired(t *testing.T) { 19 | // run tests 20 | type args struct { 21 | token string 22 | } 23 | 24 | tests := []struct { 25 | name string 26 | args args 27 | want bool 28 | }{ 29 | { 30 | name: "expired token", 31 | args: args{ 32 | token: TestTokenExpired, 33 | }, 34 | want: true, 35 | }, 36 | { 37 | name: "good token", 38 | args: args{ 39 | token: TestTokenGood, 40 | }, 41 | want: false, 42 | }, 43 | { 44 | name: "empty token", 45 | args: args{ 46 | token: "", 47 | }, 48 | want: true, 49 | }, 50 | { 51 | name: "bad token", 52 | args: args{ 53 | token: "/65", 54 | }, 55 | want: true, 56 | }, 57 | { 58 | name: "no exp", 59 | args: args{ 60 | token: makeSampleToken(jwt.MapClaims{}), 61 | }, 62 | want: true, 63 | }, 64 | } 65 | 66 | for _, tt := range tests { 67 | t.Run(tt.name, func(t *testing.T) { 68 | if got := IsTokenExpired(tt.args.token); got != tt.want { 69 | t.Errorf("IsTokenExpired() = %v, want %v", got, tt.want) 70 | } 71 | }) 72 | } 73 | } 74 | 75 | // makeSampleToken is a helper to create test tokens 76 | // with the given claims. 77 | func makeSampleToken(c jwt.Claims) string { 78 | // create a new token 79 | t := jwt.NewWithClaims(jwt.SigningMethodRS256, c) 80 | 81 | // get the signing string (header + claims) 82 | s, e := t.SigningString() 83 | if e != nil { 84 | return "" 85 | } 86 | 87 | // add bogus signature 88 | s = fmt.Sprintf("%s.abcdef", s) 89 | 90 | return s 91 | } 92 | -------------------------------------------------------------------------------- /vela/log.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // LogService handles retrieving logs for builds 12 | // from the server methods of the Vela API. 13 | type LogService service 14 | 15 | // GetService returns the provided service log. 16 | func (svc *LogService) GetService(org, repo string, build int64, service int32) (*api.Log, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d/logs", org, repo, build, service) 19 | 20 | // API Log type we want to return 21 | v := new(api.Log) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // AddService constructs a service log with the provided details. 30 | func (svc *LogService) AddService(org, repo string, build, service int, l *api.Log) (*Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d/logs", org, repo, build, service) 33 | 34 | // send request using client 35 | resp, err := svc.client.Call("POST", u, l, nil) 36 | 37 | return resp, err 38 | } 39 | 40 | // UpdateService modifies a service log with the provided details. 41 | func (svc *LogService) UpdateService(org, repo string, build int64, service int32, l *api.Log) (*Response, error) { 42 | // set the API endpoint path we send the request to 43 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d/logs", org, repo, build, service) 44 | 45 | // send request using client 46 | resp, err := svc.client.Call("PUT", u, l, nil) 47 | 48 | return resp, err 49 | } 50 | 51 | // RemoveService deletes the provided service log. 52 | func (svc *LogService) RemoveService(org, repo string, build, service int) (*string, *Response, error) { 53 | // set the API endpoint path we send the request to 54 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d/logs", org, repo, build, service) 55 | 56 | // string type we want to return 57 | v := new(string) 58 | 59 | // send request using client 60 | resp, err := svc.client.Call("DELETE", u, nil, v) 61 | 62 | return v, resp, err 63 | } 64 | 65 | // GetStep returns the provided step log. 66 | func (svc *LogService) GetStep(org, repo string, build int64, step int32) (*api.Log, *Response, error) { 67 | // set the API endpoint path we send the request to 68 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d/logs", org, repo, build, step) 69 | 70 | // API Log type we want to return 71 | v := new(api.Log) 72 | 73 | // send request using client 74 | resp, err := svc.client.Call("GET", u, nil, v) 75 | 76 | return v, resp, err 77 | } 78 | 79 | // AddStep constructs a step log with the provided details. 80 | func (svc *LogService) AddStep(org, repo string, build, step int, l *api.Log) (*Response, error) { 81 | // set the API endpoint path we send the request to 82 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d/logs", org, repo, build, step) 83 | 84 | // send request using client 85 | resp, err := svc.client.Call("POST", u, l, nil) 86 | 87 | return resp, err 88 | } 89 | 90 | // UpdateStep modifies a step log with the provided details. 91 | func (svc *LogService) UpdateStep(org, repo string, build int64, step int32, l *api.Log) (*Response, error) { 92 | // set the API endpoint path we send the request to 93 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d/logs", org, repo, build, step) 94 | 95 | // send request using client 96 | resp, err := svc.client.Call("PUT", u, l, nil) 97 | 98 | return resp, err 99 | } 100 | 101 | // RemoveStep deletes the provided step log. 102 | func (svc *LogService) RemoveStep(org, repo string, build, step int) (*string, *Response, error) { 103 | // set the API endpoint path we send the request to 104 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d/logs", org, repo, build, step) 105 | 106 | // string type we want to return 107 | v := new(string) 108 | 109 | // send request using client 110 | resp, err := svc.client.Call("DELETE", u, nil, v) 111 | 112 | return v, resp, err 113 | } 114 | -------------------------------------------------------------------------------- /vela/login.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | // AuthorizationService handles user login actions 10 | // against the server methods of the Vela API. 11 | type AuthorizationService service 12 | 13 | // GetLoginURL returns the login url with the give login options. 14 | func (svc *AuthorizationService) GetLoginURL(opt *LoginOptions) (string, error) { 15 | var err error 16 | 17 | // set the API endpoint path we send the request to 18 | l := "/login" 19 | 20 | // add the login options to the request 21 | if opt != nil && len(opt.Type) > 0 { 22 | l, err = addOptions(l, opt) 23 | if err != nil { 24 | return "", err 25 | } 26 | } 27 | 28 | // check that we have a client 29 | if svc.client == nil { 30 | return "", fmt.Errorf("client not found") 31 | } 32 | 33 | // build the url 34 | loginURL, err := svc.client.buildURLForRequest(l) 35 | if err != nil { 36 | return "", err 37 | } 38 | 39 | // return the url 40 | return loginURL, nil 41 | } 42 | -------------------------------------------------------------------------------- /vela/login_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | ) 9 | 10 | func TestAuthorizationService_GetLoginURL(t *testing.T) { 11 | // setup types 12 | addr := "http://localhost:8080" 13 | client, _ := NewClient(addr, "vela", nil) 14 | badClient, _ := NewClient("", "vela", nil) 15 | 16 | type fields struct { 17 | client *Client 18 | } 19 | 20 | type args struct { 21 | opt *LoginOptions 22 | } 23 | 24 | tests := []struct { 25 | name string 26 | fields fields 27 | args args 28 | want string 29 | wantErr bool 30 | }{ 31 | { 32 | name: "basic", 33 | fields: fields{client: client}, 34 | args: args{opt: &LoginOptions{Type: "", Port: ""}}, 35 | want: fmt.Sprintf("%s/login", addr), 36 | wantErr: false, 37 | }, 38 | { 39 | name: "cli", 40 | fields: fields{client: client}, 41 | args: args{opt: &LoginOptions{Type: "cli", Port: "123"}}, 42 | want: fmt.Sprintf("%s/login?port=123&type=cli", addr), 43 | wantErr: false, 44 | }, 45 | { 46 | name: "web", 47 | fields: fields{client: client}, 48 | args: args{opt: &LoginOptions{Type: "web", Port: ""}}, 49 | want: fmt.Sprintf("%s/login?type=web", addr), 50 | wantErr: false, 51 | }, 52 | { 53 | name: "basic bad", 54 | fields: fields{client: badClient}, 55 | args: args{opt: &LoginOptions{Type: "", Port: ""}}, 56 | want: "", 57 | wantErr: true, 58 | }, 59 | } 60 | 61 | for _, tt := range tests { 62 | t.Run(tt.name, func(t *testing.T) { 63 | svc := &AuthorizationService{ 64 | client: tt.fields.client, 65 | } 66 | 67 | got, err := svc.GetLoginURL(tt.args.opt) 68 | if (err != nil) != tt.wantErr { 69 | t.Errorf("AuthorizationService.GetLoginURL() error = %v, wantErr %v", err, tt.wantErr) 70 | return 71 | } 72 | 73 | if got != tt.want { 74 | t.Errorf("AuthorizationService.GetLoginURL() = %v, want %v", got, tt.want) 75 | } 76 | }) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /vela/pipeline.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | "github.com/go-vela/server/compiler/types/yaml/yaml" 10 | ) 11 | 12 | // PipelineService handles retrieving pipelines from 13 | // the server methods of the Vela API. 14 | type PipelineService service 15 | 16 | // PipelineOptions represents the optional parameters 17 | // to the PipelineService. 18 | type PipelineOptions struct { 19 | // Output of the pipeline being returned. 20 | // 21 | // Can be: json or yaml 22 | // 23 | // Default: yaml 24 | Output string `url:"output,omitempty"` 25 | 26 | // Ruledata options 27 | Branch string `url:"branch,omitempty"` 28 | Comment string `url:"comment,omitempty"` 29 | Event string `url:"event,omitempty"` 30 | Repo string `url:"repo,omitempty"` 31 | Status string `url:"status,omitempty"` 32 | Tag string `url:"tag,omitempty"` 33 | Target string `url:"target,omitempty"` 34 | Path []string `url:"path,omitempty"` 35 | } 36 | 37 | // Get returns the provided pipeline. 38 | func (svc *PipelineService) Get(org, repo, ref string) (*api.Pipeline, *Response, error) { 39 | // set the API endpoint path we send the request to 40 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s", org, repo, ref) 41 | 42 | // API Pipeline type we want to return 43 | v := new(api.Pipeline) 44 | 45 | // send request using client 46 | resp, err := svc.client.Call("GET", u, nil, v) 47 | 48 | return v, resp, err 49 | } 50 | 51 | // GetAll returns a list of all pipelines. 52 | func (svc *PipelineService) GetAll(org, repo string, opt *ListOptions) (*[]api.Pipeline, *Response, error) { 53 | // set the API endpoint path we send the request to 54 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s", org, repo) 55 | 56 | // add optional arguments if supplied 57 | u, err := addOptions(u, opt) 58 | if err != nil { 59 | return nil, nil, err 60 | } 61 | 62 | // slice API Pipeline type we want to return 63 | v := new([]api.Pipeline) 64 | 65 | // send request using client 66 | resp, err := svc.client.Call("GET", u, nil, v) 67 | 68 | return v, resp, err 69 | } 70 | 71 | // Add constructs a pipeline with the provided details. 72 | func (svc *PipelineService) Add(org, repo string, h *api.Pipeline) (*api.Pipeline, *Response, error) { 73 | // set the API endpoint path we send the request to 74 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s", org, repo) 75 | 76 | // API Pipeline type we want to return 77 | v := new(api.Pipeline) 78 | 79 | // send request using client 80 | resp, err := svc.client.Call("POST", u, h, v) 81 | 82 | return v, resp, err 83 | } 84 | 85 | // Update modifies a pipeline with the provided details. 86 | func (svc *PipelineService) Update(org, repo string, p *api.Pipeline) (*api.Pipeline, *Response, error) { 87 | // set the API endpoint path we send the request to 88 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s", org, repo, p.GetCommit()) 89 | 90 | // API Pipeline type we want to return 91 | v := new(api.Pipeline) 92 | 93 | // send request using client 94 | resp, err := svc.client.Call("PUT", u, p, v) 95 | 96 | return v, resp, err 97 | } 98 | 99 | // Remove deletes the provided pipeline. 100 | func (svc *PipelineService) Remove(org, repo string, pipeline string) (*string, *Response, error) { 101 | // set the API endpoint path we send the request to 102 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s", org, repo, pipeline) 103 | 104 | // string type we want to return 105 | v := new(string) 106 | 107 | // send request using client 108 | resp, err := svc.client.Call("DELETE", u, nil, v) 109 | 110 | return v, resp, err 111 | } 112 | 113 | // Compile returns the provided fully compiled pipeline. 114 | func (svc *PipelineService) Compile(org, repo, ref string, opt *PipelineOptions) (*yaml.Build, *Response, error) { 115 | // set the API endpoint path we send the request to 116 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s/compile", org, repo, ref) 117 | 118 | // add optional arguments if supplied 119 | u, err := addOptions(u, opt) 120 | if err != nil { 121 | return nil, nil, err 122 | } 123 | 124 | // yaml Build type we want to return 125 | v := new(yaml.Build) 126 | 127 | // send request using client 128 | resp, err := svc.client.Call("POST", u, nil, v) 129 | 130 | return v, resp, err 131 | } 132 | 133 | // Expand returns the provided pipeline fully compiled. 134 | func (svc *PipelineService) Expand(org, repo, ref string, opt *PipelineOptions) (*yaml.Build, *Response, error) { 135 | // set the API endpoint path we send the request to 136 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s/expand", org, repo, ref) 137 | 138 | // add optional arguments if supplied 139 | u, err := addOptions(u, opt) 140 | if err != nil { 141 | return nil, nil, err 142 | } 143 | 144 | // yaml Build type we want to return 145 | v := new(yaml.Build) 146 | 147 | // send request using client 148 | resp, err := svc.client.Call("POST", u, nil, v) 149 | 150 | return v, resp, err 151 | } 152 | 153 | // Templates returns the provided templates for a pipeline. 154 | func (svc *PipelineService) Templates(org, repo, ref string, opt *PipelineOptions) (map[string]*yaml.Template, *Response, error) { 155 | // set the API endpoint path we send the request to 156 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s/templates", org, repo, ref) 157 | 158 | // add optional arguments if supplied 159 | u, err := addOptions(u, opt) 160 | if err != nil { 161 | return nil, nil, err 162 | } 163 | 164 | // yaml Templates type we want to return 165 | v := make(map[string]*yaml.Template) 166 | 167 | // send request using client 168 | resp, err := svc.client.Call("GET", u, nil, v) 169 | 170 | return v, resp, err 171 | } 172 | 173 | // Validate returns the validation status of the provided pipeline. 174 | func (svc *PipelineService) Validate(org, repo, ref string, opt *PipelineOptions) (*string, *Response, error) { 175 | // set the API endpoint path we send the request to 176 | u := fmt.Sprintf("/api/v1/pipelines/%s/%s/%s/validate", org, repo, ref) 177 | 178 | // add optional arguments if supplied 179 | u, err := addOptions(u, opt) 180 | if err != nil { 181 | return nil, nil, err 182 | } 183 | 184 | // string type we want to return 185 | v := new(string) 186 | 187 | // send request using client 188 | resp, err := svc.client.Call("POST", u, nil, v) 189 | 190 | return v, resp, err 191 | } 192 | 193 | func (svc *PipelineService) ValidateRaw(b64Pipeline string, opt *PipelineOptions) (*string, *Response, error) { 194 | // set the API endpoint path we send the request to 195 | u := "/api/v1/pipeline/raw" 196 | 197 | // add optional arguments if supplied 198 | u, err := addOptions(u, opt) 199 | if err != nil { 200 | return nil, nil, err 201 | } 202 | 203 | // string type we want to return 204 | v := new(string) 205 | 206 | // send request using client 207 | resp, err := svc.client.Call("POST", u, b64Pipeline, v) 208 | 209 | return v, resp, err 210 | } 211 | -------------------------------------------------------------------------------- /vela/queue.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | api "github.com/go-vela/server/api/types" 7 | ) 8 | 9 | // QueueService handles retrieving queue info from 10 | // the server methods of the Vela API. 11 | type QueueService service 12 | 13 | // GetInfo fetches queue info, primarily used during worker onboarding. 14 | func (qvc *QueueService) GetInfo() (*api.QueueInfo, *Response, error) { 15 | // set the API endpoint path we send the request to 16 | url := "/api/v1/queue/info" 17 | 18 | // API QueueInfo type we want to return 19 | t := new(api.QueueInfo) 20 | 21 | // send request using client 22 | resp, err := qvc.client.Call("GET", url, nil, t) 23 | 24 | return t, resp, err 25 | } 26 | -------------------------------------------------------------------------------- /vela/queue_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "net/http" 8 | "net/http/httptest" 9 | "testing" 10 | 11 | "github.com/gin-gonic/gin" 12 | "github.com/google/go-cmp/cmp" 13 | 14 | api "github.com/go-vela/server/api/types" 15 | "github.com/go-vela/server/mock/server" 16 | ) 17 | 18 | func TestQueue_GetInfo_200(t *testing.T) { 19 | gin.SetMode(gin.TestMode) 20 | 21 | s := httptest.NewServer(server.FakeHandler()) 22 | c, _ := NewClient(s.URL, "", nil) 23 | c.Authentication.SetPersonalAccessTokenAuth("token") 24 | 25 | data := []byte(server.QueueInfoResp) 26 | 27 | var want *api.QueueInfo 28 | 29 | err := json.Unmarshal(data, &want) 30 | if err != nil { 31 | t.Error(err) 32 | } 33 | 34 | // run test 35 | got, resp, err := c.Queue.GetInfo() 36 | if err != nil { 37 | t.Errorf("GetInfo returned err: %v", err) 38 | } 39 | 40 | if resp.StatusCode != http.StatusCreated { 41 | t.Errorf("GetInfo returned %v, want %v", resp.StatusCode, http.StatusCreated) 42 | } 43 | 44 | if diff := cmp.Diff(want, got); diff != "" { 45 | t.Errorf("GetInfo mismatch (-want +got):\n%s", diff) 46 | } 47 | } 48 | 49 | func TestQueue_GetInfo_401(t *testing.T) { 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | // run test 56 | _, resp, err := c.Queue.GetInfo() 57 | if err == nil { 58 | t.Errorf("GetInfo should have returned err %v", resp.StatusCode) 59 | } 60 | 61 | if resp.StatusCode != http.StatusUnauthorized { 62 | t.Errorf("GetInfo returned %v, want %v", resp.StatusCode, http.StatusUnauthorized) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /vela/repo.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // RepoService handles retrieving repos from 12 | // the server methods of the Vela API. 13 | type RepoService service 14 | 15 | // Get returns the provided repo. 16 | func (svc *RepoService) Get(org, repo string) (*api.Repo, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/repos/%s/%s", org, repo) 19 | 20 | // API Repo type we want to return 21 | v := new(api.Repo) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetAll returns a list of all repos. 30 | func (svc *RepoService) GetAll(opt *ListOptions) (*[]api.Repo, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := "/api/v1/repos" 33 | 34 | // add optional arguments if supplied 35 | u, err := addOptions(u, opt) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | // slice API Repo type we want to return 41 | v := new([]api.Repo) 42 | 43 | // send request using client 44 | resp, err := svc.client.Call("GET", u, nil, v) 45 | 46 | return v, resp, err 47 | } 48 | 49 | // Add constructs a repo with the provided details. 50 | func (svc *RepoService) Add(r *api.Repo) (*api.Repo, *Response, error) { 51 | // set the API endpoint path we send the request to 52 | u := "/api/v1/repos" 53 | 54 | // API Repo type we want to return 55 | v := new(api.Repo) 56 | 57 | // send request using client 58 | resp, err := svc.client.Call("POST", u, r, v) 59 | 60 | return v, resp, err 61 | } 62 | 63 | // Update modifies a repo with the provided details. 64 | func (svc *RepoService) Update(org, repo string, r *api.Repo) (*api.Repo, *Response, error) { 65 | // set the API endpoint path we send the request to 66 | u := fmt.Sprintf("/api/v1/repos/%s/%s", org, repo) 67 | 68 | // API Repo type we want to return 69 | v := new(api.Repo) 70 | 71 | // send request using client 72 | resp, err := svc.client.Call("PUT", u, r, v) 73 | 74 | return v, resp, err 75 | } 76 | 77 | // Remove deletes the provided repo. 78 | func (svc *RepoService) Remove(org, repo string) (*string, *Response, error) { 79 | // set the API endpoint path we send the request to 80 | u := fmt.Sprintf("/api/v1/repos/%s/%s", org, repo) 81 | 82 | // string type we want to return 83 | v := new(string) 84 | 85 | // send request using client 86 | resp, err := svc.client.Call("DELETE", u, nil, v) 87 | 88 | return v, resp, err 89 | } 90 | 91 | // Repair modifies a damaged repo webhook. 92 | func (svc *RepoService) Repair(org, repo string) (*string, *Response, error) { 93 | // set the API endpoint path we send the request to 94 | u := fmt.Sprintf("/api/v1/repos/%s/%s/repair", org, repo) 95 | 96 | // string type we want to return 97 | v := new(string) 98 | 99 | // send request using client 100 | resp, err := svc.client.Call("PATCH", u, nil, v) 101 | 102 | return v, resp, err 103 | } 104 | 105 | // Chown modifies the org of a repo. 106 | func (svc *RepoService) Chown(org, repo string) (*string, *Response, error) { 107 | // set the API endpoint path we send the request to 108 | u := fmt.Sprintf("/api/v1/repos/%s/%s/chown", org, repo) 109 | 110 | // string type we want to return 111 | v := new(string) 112 | 113 | // send request using client 114 | resp, err := svc.client.Call("PATCH", u, nil, v) 115 | 116 | return v, resp, err 117 | } 118 | -------------------------------------------------------------------------------- /vela/repo_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/gin-gonic/gin" 14 | 15 | api "github.com/go-vela/server/api/types" 16 | "github.com/go-vela/server/api/types/actions" 17 | "github.com/go-vela/server/mock/server" 18 | ) 19 | 20 | func TestRepo_Get_200(t *testing.T) { 21 | // setup context 22 | gin.SetMode(gin.TestMode) 23 | 24 | s := httptest.NewServer(server.FakeHandler()) 25 | c, _ := NewClient(s.URL, "", nil) 26 | 27 | data := []byte(server.RepoResp) 28 | 29 | var want api.Repo 30 | 31 | _ = json.Unmarshal(data, &want) 32 | 33 | // run test 34 | got, resp, err := c.Repo.Get("github", "octocat") 35 | if err != nil { 36 | t.Errorf("New returned err: %v", err) 37 | } 38 | 39 | if resp.StatusCode != http.StatusOK { 40 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 41 | } 42 | 43 | if !reflect.DeepEqual(got, &want) { 44 | t.Errorf("Repo get is %v, want %v", got, want) 45 | } 46 | } 47 | 48 | func TestRepo_Get_404(t *testing.T) { 49 | // setup context 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | want := api.Repo{} 56 | 57 | // run test 58 | got, resp, err := c.Repo.Get("github", "not-found") 59 | if err == nil { 60 | t.Errorf("New returned err: %v", err) 61 | } 62 | 63 | if resp.StatusCode != http.StatusNotFound { 64 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 65 | } 66 | 67 | if !reflect.DeepEqual(got, &want) { 68 | t.Errorf("Repo get is %v, want %v", got, want) 69 | } 70 | } 71 | 72 | func TestRepo_GetAll_200(t *testing.T) { 73 | // setup context 74 | gin.SetMode(gin.TestMode) 75 | 76 | s := httptest.NewServer(server.FakeHandler()) 77 | c, _ := NewClient(s.URL, "", nil) 78 | 79 | data := []byte(server.ReposResp) 80 | 81 | var want []api.Repo 82 | 83 | _ = json.Unmarshal(data, &want) 84 | 85 | // run test 86 | got, resp, err := c.Repo.GetAll(nil) 87 | if err != nil { 88 | t.Errorf("New returned err: %v", err) 89 | } 90 | 91 | if resp.StatusCode != http.StatusOK { 92 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 93 | } 94 | 95 | if !reflect.DeepEqual(got, &want) { 96 | t.Errorf("Repo getall is %v, want %v", got, want) 97 | } 98 | } 99 | 100 | func TestRepo_Add_201(t *testing.T) { 101 | // setup context 102 | gin.SetMode(gin.TestMode) 103 | 104 | s := httptest.NewServer(server.FakeHandler()) 105 | c, _ := NewClient(s.URL, "", nil) 106 | 107 | data := []byte(server.RepoResp) 108 | 109 | var want api.Repo 110 | 111 | _ = json.Unmarshal(data, &want) 112 | 113 | req := api.Repo{ 114 | Org: String("github"), 115 | Name: String("octocat"), 116 | FullName: String("github/octocat"), 117 | Link: String("https://github.com/github/octocat"), 118 | Clone: String("https://github.com/github/octocat.git"), 119 | Branch: String("main"), 120 | Timeout: Int32(60), 121 | Visibility: String("public"), 122 | Private: Bool(false), 123 | Trusted: Bool(false), 124 | Active: Bool(true), 125 | AllowEvents: testEvents(), 126 | } 127 | 128 | // run test 129 | got, resp, err := c.Repo.Add(&req) 130 | if err != nil { 131 | t.Errorf("New returned err: %v", err) 132 | } 133 | 134 | if resp.StatusCode != http.StatusCreated { 135 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 136 | } 137 | 138 | if !reflect.DeepEqual(got, &want) { 139 | t.Errorf("Repo add is %v, want %v", got, want) 140 | } 141 | } 142 | 143 | func TestRepo_Update_200(t *testing.T) { 144 | // setup context 145 | gin.SetMode(gin.TestMode) 146 | 147 | s := httptest.NewServer(server.FakeHandler()) 148 | c, _ := NewClient(s.URL, "", nil) 149 | 150 | data := []byte(server.RepoResp) 151 | 152 | var want api.Repo 153 | 154 | _ = json.Unmarshal(data, &want) 155 | 156 | req := api.Repo{ 157 | Private: Bool(true), 158 | Trusted: Bool(true), 159 | Active: Bool(true), 160 | AllowEvents: testEvents(), 161 | } 162 | 163 | // run test 164 | got, resp, err := c.Repo.Update("github", "octocat", &req) 165 | if err != nil { 166 | t.Errorf("New returned err: %v", err) 167 | } 168 | 169 | if resp.StatusCode != http.StatusOK { 170 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 171 | } 172 | 173 | if !reflect.DeepEqual(got, &want) { 174 | t.Errorf("Repo create is %v, want %v", got, want) 175 | } 176 | } 177 | 178 | func TestRepo_Update_404(t *testing.T) { 179 | // setup context 180 | gin.SetMode(gin.TestMode) 181 | 182 | s := httptest.NewServer(server.FakeHandler()) 183 | c, _ := NewClient(s.URL, "", nil) 184 | 185 | want := api.Repo{} 186 | 187 | req := api.Repo{ 188 | Private: Bool(true), 189 | Trusted: Bool(true), 190 | Active: Bool(true), 191 | AllowEvents: testEvents(), 192 | } 193 | 194 | // run test 195 | got, resp, err := c.Repo.Update("github", "not-found", &req) 196 | if err == nil { 197 | t.Errorf("New returned err: %v", err) 198 | } 199 | 200 | if resp.StatusCode != http.StatusNotFound { 201 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 202 | } 203 | 204 | if !reflect.DeepEqual(got, &want) { 205 | t.Errorf("Repo update is %v, want %v", got, want) 206 | } 207 | } 208 | 209 | func TestRepo_Remove_200(t *testing.T) { 210 | // setup context 211 | gin.SetMode(gin.TestMode) 212 | 213 | s := httptest.NewServer(server.FakeHandler()) 214 | c, _ := NewClient(s.URL, "", nil) 215 | 216 | // run test 217 | _, resp, err := c.Repo.Remove("github", "octocat") 218 | if err != nil { 219 | t.Errorf("New returned err: %v", err) 220 | } 221 | 222 | if resp.StatusCode != http.StatusOK { 223 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 224 | } 225 | } 226 | 227 | func TestRepo_Remove_404(t *testing.T) { 228 | // setup context 229 | gin.SetMode(gin.TestMode) 230 | 231 | s := httptest.NewServer(server.FakeHandler()) 232 | c, _ := NewClient(s.URL, "", nil) 233 | 234 | // run test 235 | _, resp, err := c.Repo.Remove("github", "not-found") 236 | if err == nil { 237 | t.Errorf("New returned err: %v", err) 238 | } 239 | 240 | if resp.StatusCode != http.StatusNotFound { 241 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 242 | } 243 | } 244 | 245 | func TestRepo_Repair_200(t *testing.T) { 246 | // setup context 247 | gin.SetMode(gin.TestMode) 248 | 249 | s := httptest.NewServer(server.FakeHandler()) 250 | c, _ := NewClient(s.URL, "", nil) 251 | 252 | // run test 253 | _, resp, err := c.Repo.Repair("github", "octocat") 254 | if err != nil { 255 | t.Errorf("New returned err: %v", err) 256 | } 257 | 258 | if resp.StatusCode != http.StatusOK { 259 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 260 | } 261 | } 262 | 263 | func TestRepo_Repair_404(t *testing.T) { 264 | // setup context 265 | gin.SetMode(gin.TestMode) 266 | 267 | s := httptest.NewServer(server.FakeHandler()) 268 | c, _ := NewClient(s.URL, "", nil) 269 | 270 | // run test 271 | _, resp, err := c.Repo.Repair("github", "not-found") 272 | if err == nil { 273 | t.Errorf("New returned err: %v", err) 274 | } 275 | 276 | if resp.StatusCode != http.StatusNotFound { 277 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 278 | } 279 | } 280 | 281 | func TestRepo_Chown_200(t *testing.T) { 282 | // setup context 283 | gin.SetMode(gin.TestMode) 284 | 285 | s := httptest.NewServer(server.FakeHandler()) 286 | c, _ := NewClient(s.URL, "", nil) 287 | 288 | // run test 289 | _, resp, err := c.Repo.Chown("github", "octocat") 290 | if err != nil { 291 | t.Errorf("New returned err: %v", err) 292 | } 293 | 294 | if resp.StatusCode != http.StatusOK { 295 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 296 | } 297 | } 298 | 299 | func TestRepo_Chown_404(t *testing.T) { 300 | // setup context 301 | gin.SetMode(gin.TestMode) 302 | 303 | s := httptest.NewServer(server.FakeHandler()) 304 | c, _ := NewClient(s.URL, "", nil) 305 | 306 | // run test 307 | _, resp, err := c.Repo.Chown("github", "not-found") 308 | if err == nil { 309 | t.Errorf("New returned err: %v", err) 310 | } 311 | 312 | if resp.StatusCode != http.StatusNotFound { 313 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusNotFound) 314 | } 315 | } 316 | 317 | func ExampleRepoService_Get() { 318 | // Create a new vela client for interacting with server 319 | c, _ := NewClient("http://localhost:8080", "", nil) 320 | 321 | // Set new token in existing client 322 | c.Authentication.SetPersonalAccessTokenAuth("token") 323 | 324 | // Get a repo from the server 325 | repo, resp, err := c.Repo.Get("github", "octocat") 326 | if err != nil { 327 | fmt.Println(err) 328 | } 329 | 330 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 331 | } 332 | 333 | func ExampleRepoService_GetAll() { 334 | // Create a new vela client for interacting with server 335 | c, _ := NewClient("http://localhost:8080", "", nil) 336 | 337 | // Set new token in existing client 338 | c.Authentication.SetPersonalAccessTokenAuth("token") 339 | 340 | // Get all the repos from the server 341 | repos, resp, err := c.Repo.GetAll(nil) 342 | if err != nil { 343 | fmt.Println(err) 344 | } 345 | 346 | fmt.Printf("Received response code %d, for repos %+v", resp.StatusCode, repos) 347 | } 348 | 349 | func ExampleRepoService_Add() { 350 | // Create a new vela client for interacting with server 351 | c, _ := NewClient("http://localhost:8080", "", nil) 352 | 353 | // Set new token in existing client 354 | c.Authentication.SetPersonalAccessTokenAuth("token") 355 | 356 | req := api.Repo{ 357 | Org: String("github"), 358 | Name: String("octocat"), 359 | FullName: String("github/octocat"), 360 | Link: String("https://github.com/github/octocat"), 361 | Clone: String("https://github.com/github/octocat.git"), 362 | Branch: String("main"), 363 | Timeout: Int32(60), 364 | Visibility: String("public"), 365 | Private: Bool(false), 366 | Trusted: Bool(false), 367 | Active: Bool(true), 368 | AllowEvents: testEvents(), 369 | } 370 | 371 | // Create the repo in the server 372 | repo, resp, err := c.Repo.Add(&req) 373 | if err != nil { 374 | fmt.Println(err) 375 | } 376 | 377 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 378 | } 379 | 380 | func ExampleRepoService_Update() { 381 | // Create a new vela client for interacting with server 382 | c, _ := NewClient("http://localhost:8080", "", nil) 383 | 384 | // Set new token in existing client 385 | c.Authentication.SetPersonalAccessTokenAuth("token") 386 | 387 | req := api.Repo{ 388 | AllowEvents: testEvents(), 389 | } 390 | 391 | // Update the repo in the server 392 | repo, resp, err := c.Repo.Update("github", "octocat", &req) 393 | if err != nil { 394 | fmt.Println(err) 395 | } 396 | 397 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 398 | } 399 | 400 | func ExampleRepoService_Remove() { 401 | // Create a new vela client for interacting with server 402 | c, _ := NewClient("http://localhost:8080", "", nil) 403 | 404 | // Set new token in existing client 405 | c.Authentication.SetPersonalAccessTokenAuth("token") 406 | 407 | // Remove the repo in the server 408 | repo, resp, err := c.Repo.Remove("github", "octocat") 409 | if err != nil { 410 | fmt.Println(err) 411 | } 412 | 413 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 414 | } 415 | 416 | func ExampleRepoService_Repair() { 417 | // Create a new vela client for interacting with server 418 | c, _ := NewClient("http://localhost:8080", "", nil) 419 | 420 | // Set new token in existing client 421 | c.Authentication.SetPersonalAccessTokenAuth("token") 422 | 423 | // Repair the repo in the server 424 | repo, resp, err := c.Repo.Repair("github", "octocat") 425 | if err != nil { 426 | fmt.Println(err) 427 | } 428 | 429 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 430 | } 431 | 432 | func ExampleRepoService_Chown() { 433 | // Create a new vela client for interacting with server 434 | c, _ := NewClient("http://localhost:8080", "", nil) 435 | 436 | // Set new token in existing client 437 | c.Authentication.SetPersonalAccessTokenAuth("token") 438 | 439 | // Change orgship of the repo in the server 440 | repo, resp, err := c.Repo.Chown("github", "octocat") 441 | if err != nil { 442 | fmt.Println(err) 443 | } 444 | 445 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 446 | } 447 | 448 | func testEvents() *api.Events { 449 | return &api.Events{ 450 | Push: &actions.Push{ 451 | Branch: Bool(true), 452 | Tag: Bool(true), 453 | DeleteBranch: Bool(true), 454 | DeleteTag: Bool(true), 455 | }, 456 | PullRequest: &actions.Pull{ 457 | Opened: Bool(true), 458 | Edited: Bool(true), 459 | Synchronize: Bool(true), 460 | Reopened: Bool(true), 461 | }, 462 | Deployment: &actions.Deploy{ 463 | Created: Bool(true), 464 | }, 465 | Comment: &actions.Comment{ 466 | Created: Bool(true), 467 | Edited: Bool(true), 468 | }, 469 | Schedule: &actions.Schedule{ 470 | Run: Bool(true), 471 | }, 472 | } 473 | } 474 | -------------------------------------------------------------------------------- /vela/schedule.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // ScheduleService handles retrieving schedules from the server methods of the Vela API. 12 | type ScheduleService service 13 | 14 | // Get returns the provided schedule from the repo. 15 | func (svc *ScheduleService) Get(org, repo, schedule string) (*api.Schedule, *Response, error) { 16 | // set the API endpoint path we send the request to 17 | u := fmt.Sprintf("/api/v1/schedules/%s/%s/%s", org, repo, schedule) 18 | 19 | // API Schedule type we want to return 20 | v := new(api.Schedule) 21 | 22 | // send request using client 23 | resp, err := svc.client.Call("GET", u, nil, v) 24 | 25 | return v, resp, err 26 | } 27 | 28 | // GetAll returns a list of all schedules from the repo. 29 | func (svc *ScheduleService) GetAll(org, repo string, opt *ListOptions) (*[]api.Schedule, *Response, error) { 30 | // set the API endpoint path we send the request to 31 | u := fmt.Sprintf("/api/v1/schedules/%s/%s", org, repo) 32 | 33 | // add optional arguments if supplied 34 | u, err := addOptions(u, opt) 35 | if err != nil { 36 | return nil, nil, err 37 | } 38 | 39 | // slice API Schedule type we want to return 40 | v := new([]api.Schedule) 41 | 42 | // send request using client 43 | resp, err := svc.client.Call("GET", u, nil, v) 44 | 45 | return v, resp, err 46 | } 47 | 48 | // Add constructs a schedule with the provided details. 49 | func (svc *ScheduleService) Add(org, repo string, s *api.Schedule) (*api.Schedule, *Response, error) { 50 | // set the API endpoint path we send the request to 51 | u := fmt.Sprintf("/api/v1/schedules/%s/%s", org, repo) 52 | 53 | // API Schedule type we want to return 54 | v := new(api.Schedule) 55 | 56 | // send request using client 57 | resp, err := svc.client.Call("POST", u, s, v) 58 | 59 | return v, resp, err 60 | } 61 | 62 | // Update modifies a schedule with the provided details. 63 | func (svc *ScheduleService) Update(org, repo string, s *api.Schedule) (*api.Schedule, *Response, error) { 64 | // set the API endpoint path we send the request to 65 | u := fmt.Sprintf("/api/v1/schedules/%s/%s/%s", org, repo, s.GetName()) 66 | 67 | // API Schedule type we want to return 68 | v := new(api.Schedule) 69 | 70 | // send request using client 71 | resp, err := svc.client.Call("PUT", u, s, v) 72 | 73 | return v, resp, err 74 | } 75 | 76 | // Remove deletes the provided schedule. 77 | func (svc *ScheduleService) Remove(org, repo, schedule string) (*string, *Response, error) { 78 | // set the API endpoint path we send the request to 79 | u := fmt.Sprintf("/api/v1/schedules/%s/%s/%s", org, repo, schedule) 80 | 81 | // string type we want to return 82 | v := new(string) 83 | 84 | // send request using client 85 | resp, err := svc.client.Call("DELETE", u, nil, v) 86 | 87 | return v, resp, err 88 | } 89 | -------------------------------------------------------------------------------- /vela/schedule_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | api "github.com/go-vela/server/api/types" 14 | "github.com/go-vela/server/mock/server" 15 | ) 16 | 17 | func TestSchedule_Get(t *testing.T) { 18 | s := httptest.NewServer(server.FakeHandler()) 19 | 20 | c, err := NewClient(s.URL, "", nil) 21 | if err != nil { 22 | t.Errorf("unable to create test client: %v", err) 23 | } 24 | 25 | var schedule api.Schedule 26 | 27 | err = json.Unmarshal([]byte(server.ScheduleResp), &schedule) 28 | if err != nil { 29 | t.Errorf("unable to create test schedule: %v", err) 30 | } 31 | 32 | type args struct { 33 | org string 34 | repo string 35 | schedule string 36 | } 37 | 38 | tests := []struct { 39 | failure bool 40 | name string 41 | args args 42 | want *api.Schedule 43 | wantResp int 44 | }{ 45 | { 46 | failure: false, 47 | name: "success with 200", 48 | args: args{ 49 | org: "github", 50 | repo: "octocat", 51 | schedule: "foo", 52 | }, 53 | want: &schedule, 54 | wantResp: http.StatusOK, 55 | }, 56 | { 57 | failure: true, 58 | name: "failure with 404", 59 | args: args{ 60 | org: "github", 61 | repo: "octocat", 62 | schedule: "not-found", 63 | }, 64 | want: new(api.Schedule), 65 | wantResp: http.StatusNotFound, 66 | }, 67 | } 68 | for _, test := range tests { 69 | t.Run(test.name, func(t *testing.T) { 70 | got, gotResp, err := c.Schedule.Get(test.args.org, test.args.repo, test.args.schedule) 71 | 72 | if test.failure { 73 | if err == nil { 74 | t.Errorf("Get for %s should have returned err", test.name) 75 | } 76 | 77 | return 78 | } 79 | 80 | if err != nil { 81 | t.Errorf("Get for %s returned err: %v", test.name, err) 82 | } 83 | 84 | if !reflect.DeepEqual(gotResp.StatusCode, test.wantResp) { 85 | t.Errorf("Get for %s is %v, want %v", test.name, gotResp.StatusCode, test.wantResp) 86 | } 87 | 88 | if !reflect.DeepEqual(got, test.want) { 89 | t.Errorf("Get for %s is %v, want %v", test.name, got, test.want) 90 | } 91 | }) 92 | } 93 | } 94 | 95 | func TestSchedule_GetAll(t *testing.T) { 96 | t.Skip() // server.SchedulesResp is a poorly formatted string. TODO: fix in v0.24 97 | 98 | s := httptest.NewServer(server.FakeHandler()) 99 | 100 | c, err := NewClient(s.URL, "", nil) 101 | if err != nil { 102 | t.Errorf("unable to create test client: %v", err) 103 | } 104 | 105 | var schedules []api.Schedule 106 | 107 | err = json.Unmarshal([]byte(server.SchedulesResp), &schedules) 108 | if err != nil { 109 | t.Errorf("unable to create test schedules: %v", err) 110 | } 111 | 112 | type args struct { 113 | org string 114 | repo string 115 | opts *ListOptions 116 | } 117 | 118 | tests := []struct { 119 | failure bool 120 | name string 121 | args args 122 | want []api.Schedule 123 | wantResp int 124 | }{ 125 | { 126 | failure: false, 127 | name: "success with 200", 128 | args: args{ 129 | org: "github", 130 | repo: "octocat", 131 | opts: nil, 132 | }, 133 | want: schedules, 134 | wantResp: http.StatusOK, 135 | }, 136 | } 137 | for _, test := range tests { 138 | t.Run(test.name, func(t *testing.T) { 139 | got, gotResp, err := c.Schedule.GetAll(test.args.org, test.args.repo, test.args.opts) 140 | 141 | if test.failure { 142 | if err == nil { 143 | t.Errorf("GetAll for %s should have returned err", test.name) 144 | } 145 | 146 | return 147 | } 148 | 149 | if err != nil { 150 | t.Errorf("GetAll for %s returned err: %v", test.name, err) 151 | } 152 | 153 | if !reflect.DeepEqual(gotResp.StatusCode, test.wantResp) { 154 | t.Errorf("GetAll for %s is %v, want %v", test.name, gotResp.StatusCode, test.wantResp) 155 | } 156 | 157 | if !reflect.DeepEqual(*got, test.want) { 158 | t.Errorf("GetAll for %s is %v, want %v", test.name, got, test.want) 159 | } 160 | }) 161 | } 162 | } 163 | 164 | func TestSchedule_Add(t *testing.T) { 165 | s := httptest.NewServer(server.FakeHandler()) 166 | 167 | c, err := NewClient(s.URL, "", nil) 168 | if err != nil { 169 | t.Errorf("unable to create test client: %v", err) 170 | } 171 | 172 | var schedule api.Schedule 173 | 174 | err = json.Unmarshal([]byte(server.ScheduleResp), &schedule) 175 | if err != nil { 176 | t.Errorf("unable to create test schedule: %v", err) 177 | } 178 | 179 | type args struct { 180 | org string 181 | repo string 182 | schedule *api.Schedule 183 | } 184 | 185 | tests := []struct { 186 | failure bool 187 | name string 188 | args args 189 | want *api.Schedule 190 | wantResp int 191 | }{ 192 | { 193 | failure: false, 194 | name: "success with 201", 195 | args: args{ 196 | org: "github", 197 | repo: "octocat", 198 | schedule: &api.Schedule{ 199 | Active: Bool(true), 200 | Name: String("foo"), 201 | Entry: String("@weekly"), 202 | }, 203 | }, 204 | want: &schedule, 205 | wantResp: http.StatusCreated, 206 | }, 207 | } 208 | for _, test := range tests { 209 | t.Run(test.name, func(t *testing.T) { 210 | got, gotResp, err := c.Schedule.Add(test.args.org, test.args.repo, test.args.schedule) 211 | 212 | if test.failure { 213 | if err == nil { 214 | t.Errorf("Add for %s should have returned err", test.name) 215 | } 216 | 217 | return 218 | } 219 | 220 | if err != nil { 221 | t.Errorf("Add for %s returned err: %v", test.name, err) 222 | } 223 | 224 | if !reflect.DeepEqual(gotResp.StatusCode, test.wantResp) { 225 | t.Errorf("Add for %s is %v, want %v", test.name, gotResp.StatusCode, test.wantResp) 226 | } 227 | 228 | if !reflect.DeepEqual(got, test.want) { 229 | t.Errorf("Add for %s is %v, want %v", test.name, got, test.want) 230 | } 231 | }) 232 | } 233 | } 234 | 235 | func TestSchedule_Update(t *testing.T) { 236 | s := httptest.NewServer(server.FakeHandler()) 237 | 238 | c, err := NewClient(s.URL, "", nil) 239 | if err != nil { 240 | t.Errorf("unable to create test client: %v", err) 241 | } 242 | 243 | var schedule api.Schedule 244 | 245 | err = json.Unmarshal([]byte(server.ScheduleResp), &schedule) 246 | if err != nil { 247 | t.Errorf("unable to create test schedule: %v", err) 248 | } 249 | 250 | type args struct { 251 | org string 252 | repo string 253 | schedule *api.Schedule 254 | } 255 | 256 | tests := []struct { 257 | failure bool 258 | name string 259 | args args 260 | want *api.Schedule 261 | wantResp int 262 | }{ 263 | { 264 | failure: false, 265 | name: "success with 200", 266 | args: args{ 267 | org: "github", 268 | repo: "octocat", 269 | schedule: &api.Schedule{ 270 | Active: Bool(true), 271 | Name: String("foo"), 272 | Entry: String("@weekly"), 273 | }, 274 | }, 275 | want: &schedule, 276 | wantResp: http.StatusOK, 277 | }, 278 | { 279 | failure: true, 280 | name: "failure with 404", 281 | args: args{ 282 | org: "github", 283 | repo: "octocat", 284 | schedule: &api.Schedule{ 285 | Name: String("not-found"), 286 | }, 287 | }, 288 | want: new(api.Schedule), 289 | wantResp: http.StatusNotFound, 290 | }, 291 | } 292 | for _, test := range tests { 293 | t.Run(test.name, func(t *testing.T) { 294 | got, gotResp, err := c.Schedule.Update(test.args.org, test.args.repo, test.args.schedule) 295 | 296 | if test.failure { 297 | if err == nil { 298 | t.Errorf("Update for %s should have returned err", test.name) 299 | } 300 | 301 | return 302 | } 303 | 304 | if err != nil { 305 | t.Errorf("Update for %s returned err: %v", test.name, err) 306 | } 307 | 308 | if !reflect.DeepEqual(gotResp.StatusCode, test.wantResp) { 309 | t.Errorf("Update for %s is %v, want %v", test.name, gotResp.StatusCode, test.wantResp) 310 | } 311 | 312 | if !reflect.DeepEqual(got, test.want) { 313 | t.Errorf("Update for %s is %v, want %v", test.name, got, test.want) 314 | } 315 | }) 316 | } 317 | } 318 | 319 | func TestSchedule_Remove(t *testing.T) { 320 | s := httptest.NewServer(server.FakeHandler()) 321 | 322 | c, err := NewClient(s.URL, "", nil) 323 | if err != nil { 324 | t.Errorf("unable to create test client: %v", err) 325 | } 326 | 327 | type args struct { 328 | org string 329 | repo string 330 | schedule string 331 | } 332 | 333 | tests := []struct { 334 | failure bool 335 | name string 336 | args args 337 | want *string 338 | wantResp int 339 | }{ 340 | { 341 | failure: false, 342 | name: "success with 200", 343 | args: args{ 344 | org: "github", 345 | repo: "octocat", 346 | schedule: "foo", 347 | }, 348 | want: String("schedule foo deleted"), 349 | wantResp: http.StatusOK, 350 | }, 351 | { 352 | failure: true, 353 | name: "failure with 404", 354 | args: args{ 355 | org: "github", 356 | repo: "octocat", 357 | schedule: "not-found", 358 | }, 359 | want: String("Schedule not-found does not exist"), 360 | wantResp: http.StatusNotFound, 361 | }, 362 | } 363 | for _, test := range tests { 364 | t.Run(test.name, func(t *testing.T) { 365 | got, gotResp, err := c.Schedule.Remove(test.args.org, test.args.repo, test.args.schedule) 366 | 367 | if test.failure { 368 | if err == nil { 369 | t.Errorf("Remove for %s should have returned err", test.name) 370 | } 371 | 372 | return 373 | } 374 | 375 | if err != nil { 376 | t.Errorf("Remove for %s returned err: %v", test.name, err) 377 | } 378 | 379 | if !reflect.DeepEqual(gotResp.StatusCode, test.wantResp) { 380 | t.Errorf("Remove for %s is %v, want %v", test.name, gotResp.StatusCode, test.wantResp) 381 | } 382 | 383 | if !reflect.DeepEqual(got, test.want) { 384 | t.Errorf("Remove for %s is %v, want %v", test.name, got, test.want) 385 | } 386 | }) 387 | } 388 | } 389 | 390 | func ExampleScheduleService_Get() { 391 | // create a new vela client for interacting with server 392 | c, err := NewClient("http://localhost:8080", "", nil) 393 | if err != nil { 394 | fmt.Println(err) 395 | } 396 | 397 | // set new token in existing client 398 | c.Authentication.SetPersonalAccessTokenAuth("token") 399 | 400 | // get a schedule from a repo in the server 401 | schedule, resp, err := c.Schedule.Get("github", "octocat", "nightly") 402 | if err != nil { 403 | fmt.Println(err) 404 | } 405 | 406 | fmt.Printf("received response code %d, for schedule %+v", resp.StatusCode, schedule) 407 | } 408 | 409 | func ExampleScheduleService_GetAll() { 410 | // create a new vela client for interacting with server 411 | c, err := NewClient("http://localhost:8080", "", nil) 412 | if err != nil { 413 | fmt.Println(err) 414 | } 415 | 416 | // set new token in existing client 417 | c.Authentication.SetPersonalAccessTokenAuth("token") 418 | 419 | // get all the schedules from a repo in the server 420 | schedules, resp, err := c.Schedule.GetAll("github", "octocat", nil) 421 | if err != nil { 422 | fmt.Println(err) 423 | } 424 | 425 | fmt.Printf("received response code %d, for schedules %+v", resp.StatusCode, schedules) 426 | } 427 | 428 | func ExampleScheduleService_Add() { 429 | // create a new vela client for interacting with server 430 | c, err := NewClient("http://localhost:8080", "", nil) 431 | if err != nil { 432 | fmt.Println(err) 433 | } 434 | 435 | // set new token in existing client 436 | c.Authentication.SetPersonalAccessTokenAuth("token") 437 | 438 | req := api.Schedule{ 439 | Active: Bool(true), 440 | Name: String("nightly"), 441 | Entry: String("0 0 * * *"), 442 | } 443 | 444 | // create the schedule in the server 445 | schedule, resp, err := c.Schedule.Add("github", "octocat", &req) 446 | if err != nil { 447 | fmt.Println(err) 448 | } 449 | 450 | fmt.Printf("received response code %d, for schedule %+v", resp.StatusCode, schedule) 451 | } 452 | 453 | func ExampleScheduleService_Update() { 454 | // create a new vela client for interacting with server 455 | c, err := NewClient("http://localhost:8080", "", nil) 456 | if err != nil { 457 | fmt.Println(err) 458 | } 459 | 460 | // set new token in existing client 461 | c.Authentication.SetPersonalAccessTokenAuth("token") 462 | 463 | req := api.Schedule{ 464 | Active: Bool(false), 465 | Name: String("nightly"), 466 | Entry: String("0 0 * * *"), 467 | } 468 | 469 | // update the schedule in the server 470 | schedule, resp, err := c.Schedule.Update("github", "octocat", &req) 471 | if err != nil { 472 | fmt.Println(err) 473 | } 474 | 475 | fmt.Printf("received response code %d, for schedule %+v", resp.StatusCode, schedule) 476 | } 477 | 478 | func ExampleScheduleService_Remove() { 479 | // create a new vela client for interacting with server 480 | c, err := NewClient("http://localhost:8080", "", nil) 481 | if err != nil { 482 | fmt.Println(err) 483 | } 484 | 485 | // set new token in existing client 486 | c.Authentication.SetPersonalAccessTokenAuth("token") 487 | 488 | // remove the schedule from the server 489 | schedule, resp, err := c.Schedule.Remove("github", "octocat", "nightly") 490 | if err != nil { 491 | fmt.Println(err) 492 | } 493 | 494 | fmt.Printf("received response code %d, for step %+v", resp.StatusCode, schedule) 495 | } 496 | -------------------------------------------------------------------------------- /vela/scm.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | // SCMService handles syncing repos from 10 | // the server methods of the Vela API. 11 | type SCMService service 12 | 13 | // Sync synchronizes a repo between the database and the SCM. 14 | func (svc *SCMService) Sync(org, repo string) (*string, *Response, error) { 15 | u := fmt.Sprintf("/api/v1/scm/repos/%s/%s/sync", org, repo) 16 | v := new(string) 17 | resp, err := svc.client.Call("PATCH", u, nil, v) 18 | 19 | return v, resp, err 20 | } 21 | 22 | // Sync synchronizes all org repos between the database and the SCM. 23 | func (svc *SCMService) SyncAll(org string) (*string, *Response, error) { 24 | u := fmt.Sprintf("/api/v1/scm/orgs/%s/sync", org) 25 | v := new(string) 26 | resp, err := svc.client.Call("PATCH", u, nil, v) 27 | 28 | return v, resp, err 29 | } 30 | -------------------------------------------------------------------------------- /vela/scm_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | "net/http/httptest" 9 | "testing" 10 | 11 | "github.com/gin-gonic/gin" 12 | 13 | "github.com/go-vela/server/mock/server" 14 | ) 15 | 16 | func TestSCM_Sync_200(t *testing.T) { 17 | gin.SetMode(gin.TestMode) 18 | 19 | s := httptest.NewServer(server.FakeHandler()) 20 | c, _ := NewClient(s.URL, "", nil) 21 | 22 | // run test 23 | _, resp, err := c.SCM.Sync("github", "octocat") 24 | if err != nil { 25 | t.Errorf("New returned err: %v", err) 26 | } 27 | 28 | if resp.StatusCode != http.StatusOK { 29 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 30 | } 31 | } 32 | 33 | func TestSCM_Sync_404(t *testing.T) { 34 | gin.SetMode(gin.TestMode) 35 | 36 | s := httptest.NewServer(server.FakeHandler()) 37 | c, _ := NewClient(s.URL, "", nil) 38 | 39 | // run test 40 | _, resp, err := c.SCM.Sync("github", "not-found") 41 | if err == nil { 42 | t.Errorf("New returned err: %v", err) 43 | } 44 | 45 | if resp.StatusCode != http.StatusNotFound { 46 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusNotFound) 47 | } 48 | } 49 | 50 | func TestSCM_SyncAll_200(t *testing.T) { 51 | gin.SetMode(gin.TestMode) 52 | 53 | s := httptest.NewServer(server.FakeHandler()) 54 | c, _ := NewClient(s.URL, "", nil) 55 | 56 | // run test 57 | _, resp, err := c.SCM.SyncAll("github") 58 | if err != nil { 59 | t.Errorf("New returned err: %v", err) 60 | } 61 | 62 | if resp.StatusCode != http.StatusOK { 63 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 64 | } 65 | } 66 | 67 | func TestSCM_SyncAll_404(t *testing.T) { 68 | gin.SetMode(gin.TestMode) 69 | 70 | s := httptest.NewServer(server.FakeHandler()) 71 | c, _ := NewClient(s.URL, "", nil) 72 | 73 | // run test 74 | _, resp, err := c.SCM.SyncAll("not-found") 75 | if err == nil { 76 | t.Errorf("New returned err: %v", err) 77 | } 78 | 79 | if resp.StatusCode != http.StatusNotFound { 80 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusNotFound) 81 | } 82 | } 83 | 84 | func ExampleSCMService_Sync() { 85 | // Create a new vela client for interacting with server 86 | c, _ := NewClient("http://localhost:8080", "", nil) 87 | 88 | // Set new token in existing client 89 | c.Authentication.SetPersonalAccessTokenAuth("token") 90 | 91 | // Change orgship of the repo in the server 92 | repo, resp, err := c.SCM.Sync("github", "octocat") 93 | if err != nil { 94 | fmt.Println(err) 95 | } 96 | 97 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, repo) 98 | } 99 | 100 | func ExampleSCMService_SyncAll() { 101 | // Create a new vela client for interacting with server 102 | c, _ := NewClient("http://localhost:8080", "", nil) 103 | 104 | // Set new token in existing client 105 | c.Authentication.SetPersonalAccessTokenAuth("token") 106 | 107 | // Change orgship of the repo in the server 108 | org, resp, err := c.SCM.SyncAll("github") 109 | if err != nil { 110 | fmt.Println(err) 111 | } 112 | 113 | fmt.Printf("Received response code %d, for repo %+v", resp.StatusCode, org) 114 | } 115 | -------------------------------------------------------------------------------- /vela/secret.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // SecretService handles retrieving secrets from 12 | // the server methods of the Vela API. 13 | type SecretService service 14 | 15 | // Get returns the provided secret. 16 | func (svc *SecretService) Get(engine, sType, org, name, secret string) (*api.Secret, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/secrets/%s/%s/%s/%s/%s", engine, sType, org, name, secret) 19 | 20 | // API Secret type we want to return 21 | v := new(api.Secret) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetAll returns a list of all secrets. 30 | func (svc *SecretService) GetAll(engine, sType, org, name string, opt *ListOptions) (*[]api.Secret, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := fmt.Sprintf("/api/v1/secrets/%s/%s/%s/%s", engine, sType, org, name) 33 | 34 | // add optional arguments if supplied 35 | u, err := addOptions(u, opt) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | 40 | // slice API Secret type we want to return 41 | v := new([]api.Secret) 42 | 43 | // send request using client 44 | resp, err := svc.client.Call("GET", u, nil, v) 45 | 46 | return v, resp, err 47 | } 48 | 49 | // Add constructs a secret with the provided details. 50 | func (svc *SecretService) Add(engine, sType, org, name string, s *api.Secret) (*api.Secret, *Response, error) { 51 | // set the API endpoint path we send the request to 52 | u := fmt.Sprintf("/api/v1/secrets/%s/%s/%s/%s", engine, sType, org, name) 53 | 54 | // API Secret type we want to return 55 | v := new(api.Secret) 56 | 57 | // send request using client 58 | resp, err := svc.client.Call("POST", u, s, v) 59 | 60 | return v, resp, err 61 | } 62 | 63 | // Update modifies a secret with the provided details. 64 | func (svc *SecretService) Update(engine, sType, org, name string, s *api.Secret) (*api.Secret, *Response, error) { 65 | // set the API endpoint path we send the request to 66 | u := fmt.Sprintf("/api/v1/secrets/%s/%s/%s/%s/%s", engine, sType, org, name, s.GetName()) 67 | 68 | // API Secret type we want to return 69 | v := new(api.Secret) 70 | 71 | // send request using client 72 | resp, err := svc.client.Call("PUT", u, s, v) 73 | 74 | return v, resp, err 75 | } 76 | 77 | // Remove deletes the provided secret. 78 | func (svc *SecretService) Remove(engine, sType, org, name, secret string) (*string, *Response, error) { 79 | // set the API endpoint path we send the request to 80 | u := fmt.Sprintf("/api/v1/secrets/%s/%s/%s/%s/%s", engine, sType, org, name, secret) 81 | 82 | // string type we want to return 83 | v := new(string) 84 | 85 | // send request using client 86 | resp, err := svc.client.Call("DELETE", u, nil, v) 87 | 88 | return v, resp, err 89 | } 90 | -------------------------------------------------------------------------------- /vela/secret_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/gin-gonic/gin" 14 | "github.com/google/go-cmp/cmp" 15 | 16 | api "github.com/go-vela/server/api/types" 17 | "github.com/go-vela/server/mock/server" 18 | ) 19 | 20 | func TestSecret_Get_200(t *testing.T) { 21 | // setup context 22 | gin.SetMode(gin.TestMode) 23 | 24 | s := httptest.NewServer(server.FakeHandler()) 25 | c, _ := NewClient(s.URL, "", nil) 26 | 27 | data := []byte(server.SecretResp) 28 | 29 | var want api.Secret 30 | 31 | _ = json.Unmarshal(data, &want) 32 | 33 | // run test 34 | got, resp, err := c.Secret.Get("native", "repo", "github", "octocat", "foo") 35 | if err != nil { 36 | t.Errorf("New returned err: %v", err) 37 | } 38 | 39 | if resp.StatusCode != http.StatusOK { 40 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 41 | } 42 | 43 | if diff := cmp.Diff(&want, got); diff != "" { 44 | t.Errorf("Secret get mismatch (-want +got):\n%s", diff) 45 | } 46 | } 47 | 48 | func TestSecret_Get_404(t *testing.T) { 49 | // setup context 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | want := api.Secret{} 56 | 57 | // run test 58 | got, resp, err := c.Secret.Get("native", "repo", "github", "not-found", "not-found") 59 | if err == nil { 60 | t.Errorf("New returned err: %v", err) 61 | } 62 | 63 | if resp.StatusCode != http.StatusNotFound { 64 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 65 | } 66 | 67 | if !reflect.DeepEqual(got, &want) { 68 | t.Errorf("Secret get is %v, want %v", got, want) 69 | } 70 | } 71 | 72 | func TestSecret_GetAll_200(t *testing.T) { 73 | // setup context 74 | gin.SetMode(gin.TestMode) 75 | 76 | s := httptest.NewServer(server.FakeHandler()) 77 | c, _ := NewClient(s.URL, "", nil) 78 | 79 | data := []byte(server.SecretsResp) 80 | 81 | var want []api.Secret 82 | 83 | _ = json.Unmarshal(data, &want) 84 | 85 | // run test 86 | got, resp, err := c.Secret.GetAll("native", "repo", "github", "octocat", nil) 87 | if err != nil { 88 | t.Errorf("New returned err: %v", err) 89 | } 90 | 91 | if resp.StatusCode != http.StatusOK { 92 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 93 | } 94 | 95 | if !reflect.DeepEqual(got, &want) { 96 | t.Errorf("Secret get is %v, want %v", got, want) 97 | } 98 | } 99 | 100 | func TestSecret_Add_201(t *testing.T) { 101 | // setup context 102 | gin.SetMode(gin.TestMode) 103 | 104 | s := httptest.NewServer(server.FakeHandler()) 105 | c, _ := NewClient(s.URL, "", nil) 106 | 107 | data := []byte(server.SecretResp) 108 | 109 | var want api.Secret 110 | 111 | _ = json.Unmarshal(data, &want) 112 | 113 | req := api.Secret{ 114 | Org: String("github"), 115 | Repo: String("octocat"), 116 | Name: String("foo"), 117 | Value: String("bar"), 118 | Images: &[]string{"foo", "bar"}, 119 | AllowEvents: testEvents(), 120 | } 121 | 122 | // run test 123 | got, resp, err := c.Secret.Add("native", "repo", "github", "octocat", &req) 124 | if err != nil { 125 | t.Errorf("New returned err: %v", err) 126 | } 127 | 128 | if resp.StatusCode != http.StatusCreated { 129 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 130 | } 131 | 132 | if !reflect.DeepEqual(got, &want) { 133 | t.Errorf("Secret add is %v, want %v", got, want) 134 | } 135 | } 136 | 137 | func TestSecret_Update_200(t *testing.T) { 138 | // setup context 139 | gin.SetMode(gin.TestMode) 140 | 141 | s := httptest.NewServer(server.FakeHandler()) 142 | c, _ := NewClient(s.URL, "", nil) 143 | 144 | data := []byte(server.SecretResp) 145 | 146 | var want api.Secret 147 | 148 | _ = json.Unmarshal(data, &want) 149 | 150 | req := api.Secret{ 151 | Name: String("foo"), 152 | Value: String("bar"), 153 | AllowEvents: testEvents(), 154 | } 155 | 156 | // run test 157 | got, resp, err := c.Secret.Update("native", "repo", "github", "octocat", &req) 158 | if err != nil { 159 | t.Errorf("New returned err: %v", err) 160 | } 161 | 162 | if resp.StatusCode != http.StatusOK { 163 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 164 | } 165 | 166 | if !reflect.DeepEqual(got, &want) { 167 | t.Errorf("Secret get is %v, want %v", got, want) 168 | } 169 | } 170 | 171 | func TestSecret_Update_404(t *testing.T) { 172 | // setup context 173 | gin.SetMode(gin.TestMode) 174 | 175 | s := httptest.NewServer(server.FakeHandler()) 176 | c, _ := NewClient(s.URL, "", nil) 177 | 178 | want := api.Secret{} 179 | 180 | req := api.Secret{ 181 | Name: String("foo"), 182 | Value: String("bar"), 183 | AllowEvents: testEvents(), 184 | } 185 | 186 | // run test 187 | got, resp, err := c.Secret.Update("native", "repo", "github", "not-found", &req) 188 | if err == nil { 189 | t.Errorf("New returned err: %v", err) 190 | } 191 | 192 | if resp.StatusCode != http.StatusNotFound { 193 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 194 | } 195 | 196 | if !reflect.DeepEqual(got, &want) { 197 | t.Errorf("Secret get is %v, want %v", got, want) 198 | } 199 | } 200 | 201 | func TestSecret_Remove_200(t *testing.T) { 202 | // setup context 203 | gin.SetMode(gin.TestMode) 204 | 205 | s := httptest.NewServer(server.FakeHandler()) 206 | c, _ := NewClient(s.URL, "", nil) 207 | 208 | // run test 209 | _, resp, err := c.Secret.Remove("native", "repo", "github", "octocat", "foo") 210 | if err != nil { 211 | t.Errorf("New returned err: %v", err) 212 | } 213 | 214 | if resp.StatusCode != http.StatusOK { 215 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 216 | } 217 | } 218 | 219 | func TestSecret_Remove_404(t *testing.T) { 220 | // setup context 221 | gin.SetMode(gin.TestMode) 222 | 223 | s := httptest.NewServer(server.FakeHandler()) 224 | c, _ := NewClient(s.URL, "", nil) 225 | 226 | // run test 227 | _, resp, err := c.Secret.Remove("native", "repo", "github", "not-found", "not-found") 228 | if err == nil { 229 | t.Errorf("New returned err: %v", err) 230 | } 231 | 232 | if resp.StatusCode != http.StatusNotFound { 233 | t.Errorf("Secret returned %v, want %v", resp.StatusCode, http.StatusOK) 234 | } 235 | } 236 | 237 | func ExampleSecretService_Get() { 238 | // Create a new vela client for interacting with server 239 | c, _ := NewClient("http://localhost:8080", "", nil) 240 | 241 | // Set new token in existing client 242 | c.Authentication.SetPersonalAccessTokenAuth("token") 243 | 244 | // Get the secret from the server 245 | secret, resp, err := c.Secret.Get("native", "repo", "github", "octocat", "foo") 246 | if err != nil { 247 | fmt.Println(err) 248 | } 249 | 250 | fmt.Printf("Received response code %d, for secret %+v", resp.StatusCode, secret) 251 | } 252 | 253 | func ExampleSecretService_GetAll() { 254 | // Create a new vela client for interacting with server 255 | c, _ := NewClient("http://localhost:8080", "", nil) 256 | 257 | // Set new token in existing client 258 | c.Authentication.SetPersonalAccessTokenAuth("token") 259 | 260 | // Get all the secrets from the server 261 | secrets, resp, err := c.Secret.GetAll("native", "repo", "github", "octocat", nil) 262 | if err != nil { 263 | fmt.Println(err) 264 | } 265 | 266 | fmt.Printf("Received response code %d, for secrets %+v", resp.StatusCode, secrets) 267 | } 268 | 269 | func ExampleSecretService_Add() { 270 | // Create a new vela client for interacting with server 271 | c, _ := NewClient("http://localhost:8080", "", nil) 272 | 273 | // Set new token in existing client 274 | c.Authentication.SetPersonalAccessTokenAuth("token") 275 | 276 | req := api.Secret{ 277 | Name: String("foo"), 278 | Value: String("bar"), 279 | Images: &[]string{"foo", "bar"}, 280 | AllowEvents: testEvents(), 281 | } 282 | 283 | // Create the secret in the server 284 | secret, resp, err := c.Secret.Add("native", "repo", "github", "octocat", &req) 285 | if err != nil { 286 | fmt.Println(err) 287 | } 288 | 289 | fmt.Printf("Received response code %d, for secret %+v", resp.StatusCode, secret) 290 | } 291 | 292 | func ExampleSecretService_Update() { 293 | // Create a new vela client for interacting with server 294 | c, _ := NewClient("http://localhost:8080", "", nil) 295 | 296 | // Set new token in existing client 297 | c.Authentication.SetPersonalAccessTokenAuth("token") 298 | 299 | req := api.Secret{ 300 | Name: String("foo"), 301 | Value: String("bar"), 302 | AllowEvents: testEvents(), 303 | } 304 | 305 | // Update the secret in the server 306 | secret, resp, err := c.Secret.Update("native", "repo", "github", "octocat", &req) 307 | if err != nil { 308 | fmt.Println(err) 309 | } 310 | 311 | fmt.Printf("Received response code %d, for secret %+v", resp.StatusCode, secret) 312 | } 313 | 314 | func ExampleSecretService_Remove() { 315 | // Create a new vela client for interacting with server 316 | c, _ := NewClient("http://localhost:8080", "", nil) 317 | 318 | // Set new token in existing client 319 | c.Authentication.SetPersonalAccessTokenAuth("token") 320 | 321 | // Remove the secret in the server 322 | secret, resp, err := c.Secret.Remove("native", "repo", "github", "octocat", "foo") 323 | if err != nil { 324 | fmt.Println(err) 325 | } 326 | 327 | fmt.Printf("Received response code %d, for secret %+v", resp.StatusCode, secret) 328 | } 329 | -------------------------------------------------------------------------------- /vela/service.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | //nolint:dupl // ignore dupl linter false positive 4 | package vela 5 | 6 | import ( 7 | "fmt" 8 | 9 | api "github.com/go-vela/server/api/types" 10 | ) 11 | 12 | // SvcService handles retrieving services for builds 13 | // from the server methods of the Vela API. 14 | type SvcService service 15 | 16 | // Get returns the provided service. 17 | func (svc *SvcService) Get(org, repo string, build int64, service int32) (*api.Service, *Response, error) { 18 | // set the API endpoint path we send the request to 19 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d", org, repo, build, service) 20 | 21 | // API Service type we want to return 22 | v := new(api.Service) 23 | 24 | // send request using client 25 | resp, err := svc.client.Call("GET", u, nil, v) 26 | 27 | return v, resp, err 28 | } 29 | 30 | // GetAll returns a list of all services. 31 | func (svc *SvcService) GetAll(org, repo string, build int64, opt *ListOptions) (*[]api.Service, *Response, error) { 32 | // set the API endpoint path we send the request to 33 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services", org, repo, build) 34 | 35 | // add optional arguments if supplied 36 | u, err := addOptions(u, opt) 37 | if err != nil { 38 | return nil, nil, err 39 | } 40 | 41 | // slice API Service type we want to return 42 | v := new([]api.Service) 43 | 44 | // send request using client 45 | resp, err := svc.client.Call("GET", u, nil, v) 46 | 47 | return v, resp, err 48 | } 49 | 50 | // Add constructs a service with the provided details. 51 | func (svc *SvcService) Add(org, repo string, build int, s *api.Service) (*api.Service, *Response, error) { 52 | // set the API endpoint path we send the request to 53 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services", org, repo, build) 54 | 55 | // API Service type we want to return 56 | v := new(api.Service) 57 | 58 | // send request using client 59 | resp, err := svc.client.Call("POST", u, s, v) 60 | 61 | return v, resp, err 62 | } 63 | 64 | // Update modifies a service with the provided details. 65 | func (svc *SvcService) Update(org, repo string, build int64, s *api.Service) (*api.Service, *Response, error) { 66 | // set the API endpoint path we send the request to 67 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d", org, repo, build, s.GetNumber()) 68 | 69 | // API Service type we want to return 70 | v := new(api.Service) 71 | 72 | // send request using client 73 | resp, err := svc.client.Call("PUT", u, s, v) 74 | 75 | return v, resp, err 76 | } 77 | 78 | // Remove deletes the provided service. 79 | func (svc *SvcService) Remove(org, repo string, build, service int) (*string, *Response, error) { 80 | // set the API endpoint path we send the request to 81 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/services/%d", org, repo, build, service) 82 | 83 | // string type we want to return 84 | v := new(string) 85 | 86 | // send request using client 87 | resp, err := svc.client.Call("DELETE", u, nil, v) 88 | 89 | return v, resp, err 90 | } 91 | -------------------------------------------------------------------------------- /vela/service_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | "time" 13 | 14 | "github.com/gin-gonic/gin" 15 | 16 | api "github.com/go-vela/server/api/types" 17 | "github.com/go-vela/server/mock/server" 18 | ) 19 | 20 | func TestService_Get_200(t *testing.T) { 21 | // setup context 22 | gin.SetMode(gin.TestMode) 23 | 24 | s := httptest.NewServer(server.FakeHandler()) 25 | c, _ := NewClient(s.URL, "", nil) 26 | 27 | data := []byte(server.ServiceResp) 28 | 29 | var want api.Service 30 | 31 | _ = json.Unmarshal(data, &want) 32 | 33 | // run test 34 | got, resp, err := c.Svc.Get("github", "octocat", 1, 1) 35 | if err != nil { 36 | t.Errorf("New returned err: %v", err) 37 | } 38 | 39 | if resp.StatusCode != http.StatusOK { 40 | t.Errorf("Service returned %v, want %v", resp.StatusCode, http.StatusOK) 41 | } 42 | 43 | if !reflect.DeepEqual(got, &want) { 44 | t.Errorf("Service get is %v, want %v", got, want) 45 | } 46 | } 47 | 48 | func TestService_Get_404(t *testing.T) { 49 | // setup context 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | want := api.Service{} 56 | 57 | // run test 58 | got, resp, err := c.Svc.Get("github", "octocat", 1, 0) 59 | if err == nil { 60 | t.Errorf("New returned err: %v", err) 61 | } 62 | 63 | if resp.StatusCode != http.StatusNotFound { 64 | t.Errorf("Service returned %v, want %v", resp.StatusCode, http.StatusOK) 65 | } 66 | 67 | if !reflect.DeepEqual(got, &want) { 68 | t.Errorf("Service get is %v, want %v", got, want) 69 | } 70 | } 71 | 72 | func TestService_GetAll_200(t *testing.T) { 73 | // setup context 74 | gin.SetMode(gin.TestMode) 75 | 76 | s := httptest.NewServer(server.FakeHandler()) 77 | c, _ := NewClient(s.URL, "", nil) 78 | 79 | data := []byte(server.ServicesResp) 80 | 81 | var want []api.Service 82 | 83 | _ = json.Unmarshal(data, &want) 84 | 85 | // run test 86 | got, resp, err := c.Svc.GetAll("github", "octocat", 1, nil) 87 | if err != nil { 88 | t.Errorf("New returned err: %v", err) 89 | } 90 | 91 | if resp.StatusCode != http.StatusOK { 92 | t.Errorf("Service returned %v, want %v", resp.StatusCode, http.StatusOK) 93 | } 94 | 95 | if !reflect.DeepEqual(got, &want) { 96 | t.Errorf("Service getall is %v, want %v", got, want) 97 | } 98 | } 99 | 100 | func TestService_Add_201(t *testing.T) { 101 | // setup context 102 | gin.SetMode(gin.TestMode) 103 | 104 | s := httptest.NewServer(server.FakeHandler()) 105 | c, _ := NewClient(s.URL, "", nil) 106 | 107 | data := []byte(server.ServiceResp) 108 | 109 | var want api.Service 110 | 111 | _ = json.Unmarshal(data, &want) 112 | 113 | req := api.Service{ 114 | Number: Int32(1), 115 | Name: String("clone"), 116 | Status: String("created"), 117 | Error: String(""), 118 | ExitCode: Int32(0), 119 | Created: Int64(1563475419), 120 | Started: Int64(0), 121 | Finished: Int64(0), 122 | } 123 | 124 | // run test 125 | got, resp, err := c.Svc.Add("github", "octocat", 1, &req) 126 | if err != nil { 127 | t.Errorf("New returned err: %v", err) 128 | } 129 | 130 | if resp.StatusCode != http.StatusCreated { 131 | t.Errorf("Service returned %v, want %v", resp.StatusCode, http.StatusOK) 132 | } 133 | 134 | if !reflect.DeepEqual(got, &want) { 135 | t.Errorf("Service create is %v, want %v", got, want) 136 | } 137 | } 138 | 139 | func TestService_Update_201(t *testing.T) { 140 | // setup context 141 | gin.SetMode(gin.TestMode) 142 | 143 | s := httptest.NewServer(server.FakeHandler()) 144 | c, _ := NewClient(s.URL, "", nil) 145 | 146 | data := []byte(server.ServiceResp) 147 | 148 | var want api.Service 149 | 150 | _ = json.Unmarshal(data, &want) 151 | 152 | req := api.Service{ 153 | Number: Int32(1), 154 | Status: String("finished"), 155 | Started: Int64(1563475419), 156 | Finished: Int64(1563475419), 157 | } 158 | 159 | // run test 160 | got, resp, err := c.Svc.Update("github", "octocat", 1, &req) 161 | if err != nil { 162 | t.Errorf("New returned err: %v", err) 163 | } 164 | 165 | if resp.StatusCode != http.StatusOK { 166 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 167 | } 168 | 169 | if !reflect.DeepEqual(got, &want) { 170 | t.Errorf("Repo create is %v, want %v", got, want) 171 | } 172 | } 173 | 174 | func TestService_Update_404(t *testing.T) { 175 | // setup context 176 | gin.SetMode(gin.TestMode) 177 | 178 | s := httptest.NewServer(server.FakeHandler()) 179 | c, _ := NewClient(s.URL, "", nil) 180 | 181 | want := api.Service{} 182 | 183 | req := api.Service{ 184 | Number: Int32(0), 185 | Status: String("finished"), 186 | Started: Int64(1563475419), 187 | Finished: Int64(1563475419), 188 | } 189 | 190 | // run test 191 | got, resp, err := c.Svc.Update("github", "not-found", 0, &req) 192 | if err == nil { 193 | t.Errorf("New returned err: %v", err) 194 | } 195 | 196 | if resp.StatusCode != http.StatusNotFound { 197 | t.Errorf("Build returned %v, want %v", resp.StatusCode, http.StatusOK) 198 | } 199 | 200 | if !reflect.DeepEqual(got, &want) { 201 | t.Errorf("Service get is %v, want %v", got, want) 202 | } 203 | } 204 | 205 | func TestService_Remove_200(t *testing.T) { 206 | // setup context 207 | gin.SetMode(gin.TestMode) 208 | 209 | s := httptest.NewServer(server.FakeHandler()) 210 | c, _ := NewClient(s.URL, "", nil) 211 | 212 | // run test 213 | _, resp, err := c.Svc.Remove("github", "octocat", 1, 1) 214 | if err != nil { 215 | t.Errorf("New returned err: %v", err) 216 | } 217 | 218 | if resp.StatusCode != http.StatusOK { 219 | t.Errorf("Service returned %v, want %v", resp.StatusCode, http.StatusOK) 220 | } 221 | } 222 | 223 | func TestService_Remove_404(t *testing.T) { 224 | // setup context 225 | gin.SetMode(gin.TestMode) 226 | 227 | s := httptest.NewServer(server.FakeHandler()) 228 | c, _ := NewClient(s.URL, "", nil) 229 | 230 | // run test 231 | _, resp, err := c.Svc.Remove("github", "octocat", 1, 0) 232 | if err == nil { 233 | t.Errorf("New returned err: %v", err) 234 | } 235 | 236 | if resp.StatusCode != http.StatusNotFound { 237 | t.Errorf("Build returned %v, want %v", resp.StatusCode, http.StatusOK) 238 | } 239 | } 240 | 241 | func ExampleSvcService_Get() { 242 | // Create a new vela client for interacting with server 243 | c, _ := NewClient("http://localhost:8080", "", nil) 244 | 245 | // Set new token in existing client 246 | c.Authentication.SetPersonalAccessTokenAuth("token") 247 | 248 | // Get a service from the server 249 | service, resp, err := c.Svc.Get("github", "octocat", 1, 1) 250 | if err != nil { 251 | fmt.Println(err) 252 | } 253 | 254 | fmt.Printf("Received response code %d, for service %+v", resp.StatusCode, service) 255 | } 256 | 257 | func ExampleSvcService_GetAll() { 258 | // Create a new vela client for interacting with server 259 | c, _ := NewClient("http://localhost:8080", "", nil) 260 | 261 | // Set new token in existing client 262 | c.Authentication.SetPersonalAccessTokenAuth("token") 263 | 264 | // Get all the services from the server 265 | services, resp, err := c.Svc.GetAll("github", "octocat", 1, nil) 266 | if err != nil { 267 | fmt.Println(err) 268 | } 269 | 270 | fmt.Printf("Received response code %d, for services %+v", resp.StatusCode, services) 271 | } 272 | 273 | func ExampleSvcService_Add() { 274 | // Create a new vela client for interacting with server 275 | c, _ := NewClient("http://localhost:8080", "", nil) 276 | 277 | // Set new token in existing client 278 | c.Authentication.SetPersonalAccessTokenAuth("token") 279 | 280 | req := api.Service{ 281 | Number: Int32(1), 282 | Name: String("clone"), 283 | Status: String("pending"), 284 | Error: String(""), 285 | ExitCode: Int32(0), 286 | Created: Int64(time.Now().UTC().Unix()), 287 | Started: Int64(0), 288 | Finished: Int64(0), 289 | } 290 | 291 | // Create the service in the server 292 | service, resp, err := c.Svc.Add("github", "octocat", 1, &req) 293 | if err != nil { 294 | fmt.Println(err) 295 | } 296 | 297 | fmt.Printf("Received response code %d, for service %+v", resp.StatusCode, service) 298 | } 299 | 300 | func ExampleSvcService_Update() { 301 | // Create a new vela client for interacting with server 302 | c, _ := NewClient("http://localhost:8080", "", nil) 303 | 304 | // Set new token in existing client 305 | c.Authentication.SetPersonalAccessTokenAuth("token") 306 | 307 | req := api.Service{ 308 | Status: String("error"), 309 | Error: String("Something in the runtime broke"), 310 | } 311 | 312 | // Update the service in the server 313 | service, resp, err := c.Svc.Update("github", "octocat", 1, &req) 314 | if err != nil { 315 | fmt.Println(err) 316 | } 317 | 318 | fmt.Printf("Received response code %d, for service %+v", resp.StatusCode, service) 319 | } 320 | 321 | func ExampleSvcService_Remove() { 322 | // Create a new vela client for interacting with server 323 | c, _ := NewClient("http://localhost:8080", "", nil) 324 | 325 | // Set new token in existing client 326 | c.Authentication.SetPersonalAccessTokenAuth("token") 327 | 328 | // Remove the service in the server 329 | service, resp, err := c.Svc.Remove("github", "octocat", 1, 1) 330 | if err != nil { 331 | fmt.Println(err) 332 | } 333 | 334 | fmt.Printf("Received response code %d, for service %+v", resp.StatusCode, service) 335 | } 336 | -------------------------------------------------------------------------------- /vela/step.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | //nolint:dupl // ignore dupl linter false positive 4 | package vela 5 | 6 | import ( 7 | "fmt" 8 | 9 | api "github.com/go-vela/server/api/types" 10 | ) 11 | 12 | // StepService handles retrieving steps for builds 13 | // from the server methods of the Vela API. 14 | type StepService service 15 | 16 | // Get returns the provided step. 17 | func (svc *StepService) Get(org, repo string, build int64, step int32) (*api.Step, *Response, error) { 18 | // set the API endpoint path we send the request to 19 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d", org, repo, build, step) 20 | 21 | // API Step type we want to return 22 | v := new(api.Step) 23 | 24 | // send request using client 25 | resp, err := svc.client.Call("GET", u, nil, v) 26 | 27 | return v, resp, err 28 | } 29 | 30 | // GetAll returns a list of all steps. 31 | func (svc *StepService) GetAll(org, repo string, build int64, opt *ListOptions) (*[]api.Step, *Response, error) { 32 | // set the API endpoint path we send the request to 33 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps", org, repo, build) 34 | 35 | // add optional arguments if supplied 36 | u, err := addOptions(u, opt) 37 | if err != nil { 38 | return nil, nil, err 39 | } 40 | 41 | // slice API Step type we want to return 42 | v := new([]api.Step) 43 | 44 | // send request using client 45 | resp, err := svc.client.Call("GET", u, nil, v) 46 | 47 | return v, resp, err 48 | } 49 | 50 | // Add constructs a step with the provided details. 51 | func (svc *StepService) Add(org, repo string, build int, s *api.Step) (*api.Step, *Response, error) { 52 | // set the API endpoint path we send the request to 53 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps", org, repo, build) 54 | 55 | // API Step type we want to return 56 | v := new(api.Step) 57 | 58 | // send request using client 59 | resp, err := svc.client.Call("POST", u, s, v) 60 | 61 | return v, resp, err 62 | } 63 | 64 | // Update modifies a step with the provided details. 65 | func (svc *StepService) Update(org, repo string, build int64, s *api.Step) (*api.Step, *Response, error) { 66 | // set the API endpoint path we send the request to 67 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d", org, repo, build, s.GetNumber()) 68 | 69 | // API Step type we want to return 70 | v := new(api.Step) 71 | 72 | // send request using client 73 | resp, err := svc.client.Call("PUT", u, s, v) 74 | 75 | return v, resp, err 76 | } 77 | 78 | // Remove deletes the provided step. 79 | func (svc *StepService) Remove(org, repo string, build, step int) (*string, *Response, error) { 80 | // set the API endpoint path we send the request to 81 | u := fmt.Sprintf("/api/v1/repos/%s/%s/builds/%d/steps/%d", org, repo, build, step) 82 | 83 | // string type we want to return 84 | v := new(string) 85 | 86 | // send request using client 87 | resp, err := svc.client.Call("DELETE", u, nil, v) 88 | 89 | return v, resp, err 90 | } 91 | -------------------------------------------------------------------------------- /vela/step_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | "time" 13 | 14 | "github.com/gin-gonic/gin" 15 | 16 | api "github.com/go-vela/server/api/types" 17 | "github.com/go-vela/server/mock/server" 18 | ) 19 | 20 | func TestStep_Get_200(t *testing.T) { 21 | // setup context 22 | gin.SetMode(gin.TestMode) 23 | 24 | s := httptest.NewServer(server.FakeHandler()) 25 | c, _ := NewClient(s.URL, "", nil) 26 | 27 | data := []byte(server.StepResp) 28 | 29 | var want api.Step 30 | 31 | _ = json.Unmarshal(data, &want) 32 | 33 | // run test 34 | got, resp, err := c.Step.Get("github", "octocat", 1, 1) 35 | if err != nil { 36 | t.Errorf("New returned err: %v", err) 37 | } 38 | 39 | if resp.StatusCode != http.StatusOK { 40 | t.Errorf("Step returned %v, want %v", resp.StatusCode, http.StatusOK) 41 | } 42 | 43 | if !reflect.DeepEqual(got, &want) { 44 | t.Errorf("Step get is %v, want %v", got, want) 45 | } 46 | } 47 | 48 | func TestStep_Get_404(t *testing.T) { 49 | // setup context 50 | gin.SetMode(gin.TestMode) 51 | 52 | s := httptest.NewServer(server.FakeHandler()) 53 | c, _ := NewClient(s.URL, "", nil) 54 | 55 | want := api.Step{} 56 | 57 | // run test 58 | got, resp, err := c.Step.Get("github", "octocat", 1, 0) 59 | if err == nil { 60 | t.Errorf("New returned err: %v", err) 61 | } 62 | 63 | if resp.StatusCode != http.StatusNotFound { 64 | t.Errorf("Step returned %v, want %v", resp.StatusCode, http.StatusOK) 65 | } 66 | 67 | if !reflect.DeepEqual(got, &want) { 68 | t.Errorf("Step get is %v, want %v", got, want) 69 | } 70 | } 71 | 72 | func TestStep_GetAll_200(t *testing.T) { 73 | // setup context 74 | gin.SetMode(gin.TestMode) 75 | 76 | s := httptest.NewServer(server.FakeHandler()) 77 | c, _ := NewClient(s.URL, "", nil) 78 | 79 | data := []byte(server.StepsResp) 80 | 81 | var want []api.Step 82 | 83 | _ = json.Unmarshal(data, &want) 84 | 85 | // run test 86 | got, resp, err := c.Step.GetAll("github", "octocat", 1, nil) 87 | if err != nil { 88 | t.Errorf("New returned err: %v", err) 89 | } 90 | 91 | if resp.StatusCode != http.StatusOK { 92 | t.Errorf("Step returned %v, want %v", resp.StatusCode, http.StatusOK) 93 | } 94 | 95 | if !reflect.DeepEqual(got, &want) { 96 | t.Errorf("Step getall is %v, want %v", got, want) 97 | } 98 | } 99 | 100 | func TestStep_Add_201(t *testing.T) { 101 | // setup context 102 | gin.SetMode(gin.TestMode) 103 | 104 | s := httptest.NewServer(server.FakeHandler()) 105 | c, _ := NewClient(s.URL, "", nil) 106 | 107 | data := []byte(server.StepResp) 108 | 109 | var want api.Step 110 | 111 | _ = json.Unmarshal(data, &want) 112 | 113 | req := api.Step{ 114 | Number: Int32(1), 115 | Name: String("clone"), 116 | Status: String("created"), 117 | Error: String(""), 118 | ExitCode: Int32(0), 119 | Created: Int64(1563475419), 120 | Started: Int64(0), 121 | Finished: Int64(0), 122 | Host: String("example.company.com"), 123 | Runtime: String("docker"), 124 | Distribution: String("linux"), 125 | } 126 | 127 | // run test 128 | got, resp, err := c.Step.Add("github", "octocat", 1, &req) 129 | if err != nil { 130 | t.Errorf("New returned err: %v", err) 131 | } 132 | 133 | if resp.StatusCode != http.StatusCreated { 134 | t.Errorf("Step returned %v, want %v", resp.StatusCode, http.StatusOK) 135 | } 136 | 137 | if !reflect.DeepEqual(got, &want) { 138 | t.Errorf("Step create is %v, want %v", got, want) 139 | } 140 | } 141 | 142 | func TestStep_Update_201(t *testing.T) { 143 | // setup context 144 | gin.SetMode(gin.TestMode) 145 | 146 | s := httptest.NewServer(server.FakeHandler()) 147 | c, _ := NewClient(s.URL, "", nil) 148 | 149 | data := []byte(server.StepResp) 150 | 151 | var want api.Step 152 | 153 | _ = json.Unmarshal(data, &want) 154 | 155 | req := api.Step{ 156 | Number: Int32(1), 157 | Status: String("finished"), 158 | Started: Int64(1563475419), 159 | Finished: Int64(1563475419), 160 | } 161 | 162 | // run test 163 | got, resp, err := c.Step.Update("github", "octocat", 1, &req) 164 | if err != nil { 165 | t.Errorf("New returned err: %v", err) 166 | } 167 | 168 | if resp.StatusCode != http.StatusOK { 169 | t.Errorf("Repo returned %v, want %v", resp.StatusCode, http.StatusOK) 170 | } 171 | 172 | if !reflect.DeepEqual(got, &want) { 173 | t.Errorf("Repo create is %v, want %v", got, want) 174 | } 175 | } 176 | 177 | func TestStep_Update_404(t *testing.T) { 178 | // setup context 179 | gin.SetMode(gin.TestMode) 180 | 181 | s := httptest.NewServer(server.FakeHandler()) 182 | c, _ := NewClient(s.URL, "", nil) 183 | 184 | want := api.Step{} 185 | 186 | req := api.Step{ 187 | Number: Int32(0), 188 | Status: String("finished"), 189 | Started: Int64(1563475419), 190 | Finished: Int64(1563475419), 191 | } 192 | 193 | // run test 194 | got, resp, err := c.Step.Update("github", "not-found", 0, &req) 195 | if err == nil { 196 | t.Errorf("New returned err: %v", err) 197 | } 198 | 199 | if resp.StatusCode != http.StatusNotFound { 200 | t.Errorf("Build returned %v, want %v", resp.StatusCode, http.StatusOK) 201 | } 202 | 203 | if !reflect.DeepEqual(got, &want) { 204 | t.Errorf("Step get is %v, want %v", got, want) 205 | } 206 | } 207 | 208 | func TestStep_Remove_200(t *testing.T) { 209 | // setup context 210 | gin.SetMode(gin.TestMode) 211 | 212 | s := httptest.NewServer(server.FakeHandler()) 213 | c, _ := NewClient(s.URL, "", nil) 214 | 215 | // run test 216 | _, resp, err := c.Step.Remove("github", "octocat", 1, 1) 217 | if err != nil { 218 | t.Errorf("New returned err: %v", err) 219 | } 220 | 221 | if resp.StatusCode != http.StatusOK { 222 | t.Errorf("Step returned %v, want %v", resp.StatusCode, http.StatusOK) 223 | } 224 | } 225 | 226 | func TestStep_Remove_404(t *testing.T) { 227 | // setup context 228 | gin.SetMode(gin.TestMode) 229 | 230 | s := httptest.NewServer(server.FakeHandler()) 231 | c, _ := NewClient(s.URL, "", nil) 232 | 233 | // run test 234 | _, resp, err := c.Step.Remove("github", "octocat", 1, 0) 235 | if err == nil { 236 | t.Errorf("New returned err: %v", err) 237 | } 238 | 239 | if resp.StatusCode != http.StatusNotFound { 240 | t.Errorf("Build returned %v, want %v", resp.StatusCode, http.StatusOK) 241 | } 242 | } 243 | 244 | func ExampleStepService_Get() { 245 | // Create a new vela client for interacting with server 246 | c, _ := NewClient("http://localhost:8080", "", nil) 247 | 248 | // Set new token in existing client 249 | c.Authentication.SetPersonalAccessTokenAuth("token") 250 | 251 | // Get a step from the server 252 | step, resp, err := c.Step.Get("github", "octocat", 1, 1) 253 | if err != nil { 254 | fmt.Println(err) 255 | } 256 | 257 | fmt.Printf("Received response code %d, for step %+v", resp.StatusCode, step) 258 | } 259 | 260 | func ExampleStepService_GetAll() { 261 | // Create a new vela client for interacting with server 262 | c, _ := NewClient("http://localhost:8080", "", nil) 263 | 264 | // Set new token in existing client 265 | c.Authentication.SetPersonalAccessTokenAuth("token") 266 | 267 | // Get all the steps from the server 268 | steps, resp, err := c.Step.GetAll("github", "octocat", 1, nil) 269 | if err != nil { 270 | fmt.Println(err) 271 | } 272 | 273 | fmt.Printf("Received response code %d, for steps %+v", resp.StatusCode, steps) 274 | } 275 | 276 | func ExampleStepService_Add() { 277 | // Create a new vela client for interacting with server 278 | c, _ := NewClient("http://localhost:8080", "", nil) 279 | 280 | // Set new token in existing client 281 | c.Authentication.SetPersonalAccessTokenAuth("token") 282 | 283 | req := api.Step{ 284 | Number: Int32(1), 285 | Name: String("clone"), 286 | Status: String("pending"), 287 | Error: String(""), 288 | ExitCode: Int32(0), 289 | Created: Int64(time.Now().UTC().Unix()), 290 | Started: Int64(0), 291 | Finished: Int64(0), 292 | Host: String("example.company.com"), 293 | Runtime: String("docker"), 294 | Distribution: String("linux"), 295 | } 296 | 297 | // Create the step in the server 298 | step, resp, err := c.Step.Add("github", "octocat", 1, &req) 299 | if err != nil { 300 | fmt.Println(err) 301 | } 302 | 303 | fmt.Printf("Received response code %d, for step %+v", resp.StatusCode, step) 304 | } 305 | 306 | func ExampleStepService_Update() { 307 | // Create a new vela client for interacting with server 308 | c, _ := NewClient("http://localhost:8080", "", nil) 309 | 310 | // Set new token in existing client 311 | c.Authentication.SetPersonalAccessTokenAuth("token") 312 | 313 | req := api.Step{ 314 | Status: String("error"), 315 | Error: String("Something in the runtime broke"), 316 | } 317 | 318 | // Update the step in the server 319 | step, resp, err := c.Step.Update("github", "octocat", 1, &req) 320 | if err != nil { 321 | fmt.Println(err) 322 | } 323 | 324 | fmt.Printf("Received response code %d, for step %+v", resp.StatusCode, step) 325 | } 326 | 327 | func ExampleStepService_Remove() { 328 | // Create a new vela client for interacting with server 329 | c, _ := NewClient("http://localhost:8080", "", nil) 330 | 331 | // Set new token in existing client 332 | c.Authentication.SetPersonalAccessTokenAuth("token") 333 | 334 | // Remove the step in the server 335 | step, resp, err := c.Step.Remove("github", "octocat", 1, 1) 336 | if err != nil { 337 | fmt.Println(err) 338 | } 339 | 340 | fmt.Printf("Received response code %d, for step %+v", resp.StatusCode, step) 341 | } 342 | -------------------------------------------------------------------------------- /vela/user.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // UserService handles retrieving users from 12 | // the server methods of the Vela API. 13 | type UserService service 14 | 15 | // Get returns the provided user by name. 16 | func (svc *UserService) Get(name string) (*api.User, *Response, error) { 17 | // set the API endpoint path we send the request to 18 | u := fmt.Sprintf("/api/v1/users/%s", name) 19 | 20 | // api user type we want to return 21 | v := new(api.User) 22 | 23 | // send request using client 24 | resp, err := svc.client.Call("GET", u, nil, v) 25 | 26 | return v, resp, err 27 | } 28 | 29 | // GetCurrent returns the current user. 30 | func (svc *UserService) GetCurrent() (*api.User, *Response, error) { 31 | // set the API endpoint path we send the request to 32 | u := "/api/v1/user" 33 | 34 | // api user type we want to return 35 | v := new(api.User) 36 | 37 | // send request using client 38 | resp, err := svc.client.Call("GET", u, nil, v) 39 | 40 | return v, resp, err 41 | } 42 | 43 | // Update modifies a user with the provided details. 44 | func (svc *UserService) Update(name string, user *api.User) (*api.User, *Response, error) { 45 | // set the API endpoint path we send the request to 46 | u := fmt.Sprintf("/api/v1/users/%s", name) 47 | 48 | // api User type we want to return 49 | v := new(api.User) 50 | 51 | // send request using client 52 | resp, err := svc.client.Call("PUT", u, user, v) 53 | 54 | return v, resp, err 55 | } 56 | 57 | // Update modifies the current user with the provided details. 58 | func (svc *UserService) UpdateCurrent(user *api.User) (*api.User, *Response, error) { 59 | // set the API endpoint path we send the request to 60 | u := "/api/v1/user" 61 | 62 | // api User type we want to return 63 | v := new(api.User) 64 | 65 | // send request using client 66 | resp, err := svc.client.Call("PUT", u, user, v) 67 | 68 | return v, resp, err 69 | } 70 | -------------------------------------------------------------------------------- /vela/user_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "net/http" 8 | "net/http/httptest" 9 | "reflect" 10 | "testing" 11 | 12 | "github.com/gin-gonic/gin" 13 | 14 | api "github.com/go-vela/server/api/types" 15 | "github.com/go-vela/server/mock/server" 16 | ) 17 | 18 | func TestUser_Get_200(t *testing.T) { 19 | // setup context 20 | gin.SetMode(gin.TestMode) 21 | 22 | s := httptest.NewServer(server.FakeHandler()) 23 | c, _ := NewClient(s.URL, "", nil) 24 | 25 | data := []byte(server.UserResp) 26 | 27 | var want api.User 28 | 29 | _ = json.Unmarshal(data, &want) 30 | 31 | // run test 32 | got, resp, err := c.User.Get("octocat") 33 | if err != nil { 34 | t.Errorf("User Get returned err: %v", err) 35 | } 36 | 37 | if resp.StatusCode != http.StatusOK { 38 | t.Errorf("User Get returned %v, want %v", resp.StatusCode, http.StatusOK) 39 | } 40 | 41 | if !reflect.DeepEqual(got, &want) { 42 | t.Errorf("User Get is %v, want %v", got, want) 43 | } 44 | } 45 | 46 | func TestUser_Get_404(t *testing.T) { 47 | // setup context 48 | gin.SetMode(gin.TestMode) 49 | 50 | s := httptest.NewServer(server.FakeHandler()) 51 | c, _ := NewClient(s.URL, "", nil) 52 | 53 | want := api.User{} 54 | 55 | // run test 56 | got, resp, err := c.User.Get("not-found") 57 | if err == nil { 58 | t.Errorf("User Get should have returned err") 59 | } 60 | 61 | if resp.StatusCode != http.StatusNotFound { 62 | t.Errorf("User Get returned %v, want %v", resp.StatusCode, http.StatusNotFound) 63 | } 64 | 65 | if !reflect.DeepEqual(got, &want) { 66 | t.Errorf("User Get is %v, want %v", got, want) 67 | } 68 | } 69 | 70 | func TestUser_Update_200(t *testing.T) { 71 | // setup context 72 | gin.SetMode(gin.TestMode) 73 | 74 | s := httptest.NewServer(server.FakeHandler()) 75 | c, _ := NewClient(s.URL, "", nil) 76 | 77 | data := []byte(server.UserResp) 78 | 79 | var want api.User 80 | 81 | _ = json.Unmarshal(data, &want) 82 | 83 | req := api.User{ 84 | Admin: Bool(true), 85 | } 86 | 87 | // run test 88 | got, resp, err := c.User.Update("octocat", &req) 89 | if err != nil { 90 | t.Errorf("User Update returned err: %v", err) 91 | } 92 | 93 | if resp.StatusCode != http.StatusOK { 94 | t.Errorf("User Update returned %v, want %v", resp.StatusCode, http.StatusOK) 95 | } 96 | 97 | if !reflect.DeepEqual(got, &want) { 98 | t.Errorf("User Update is %v, want %v", got, want) 99 | } 100 | } 101 | 102 | func TestUser_Update_404(t *testing.T) { 103 | // setup context 104 | gin.SetMode(gin.TestMode) 105 | 106 | s := httptest.NewServer(server.FakeHandler()) 107 | c, _ := NewClient(s.URL, "", nil) 108 | 109 | want := api.User{} 110 | 111 | req := api.User{ 112 | Admin: Bool(true), 113 | } 114 | 115 | // run test 116 | got, resp, err := c.User.Update("not-found", &req) 117 | if err == nil { 118 | t.Errorf("User Update should have returned err") 119 | } 120 | 121 | if resp.StatusCode != http.StatusNotFound { 122 | t.Errorf("User Update returned %v, want %v", resp.StatusCode, http.StatusNotFound) 123 | } 124 | 125 | if !reflect.DeepEqual(got, &want) { 126 | t.Errorf("User Update is %v, want %v", got, want) 127 | } 128 | } 129 | 130 | func TestCurrentUser_Get_200(t *testing.T) { 131 | // setup context 132 | gin.SetMode(gin.TestMode) 133 | 134 | s := httptest.NewServer(server.FakeHandler()) 135 | c, _ := NewClient(s.URL, "", nil) 136 | 137 | data := []byte(server.UserResp) 138 | 139 | var want api.User 140 | 141 | _ = json.Unmarshal(data, &want) 142 | 143 | // run test 144 | got, resp, err := c.User.GetCurrent() 145 | if err != nil { 146 | t.Errorf("User GetCurrent returned err: %v", err) 147 | } 148 | 149 | if resp.StatusCode != http.StatusOK { 150 | t.Errorf("User GetCurrent returned %v, want %v", resp.StatusCode, http.StatusOK) 151 | } 152 | 153 | if !reflect.DeepEqual(got, &want) { 154 | t.Errorf("User GetCurrent is %v, want %v", got, want) 155 | } 156 | } 157 | 158 | func TestUser_GetCurrent_401(t *testing.T) { 159 | // setup context 160 | gin.SetMode(gin.TestMode) 161 | 162 | s := httptest.NewServer(server.FakeHandler()) 163 | c, _ := NewClient(s.URL, "", nil) 164 | 165 | c.Authentication.SetTokenAuth("invalid") 166 | 167 | want := api.User{} 168 | 169 | // run test 170 | got, resp, err := c.User.GetCurrent() 171 | if err == nil { 172 | t.Errorf("User GetCurrent should have returned err") 173 | } 174 | 175 | if resp.StatusCode != http.StatusUnauthorized { 176 | t.Errorf("User GetCurrent returned %v, want %v", resp.StatusCode, http.StatusUnauthorized) 177 | } 178 | 179 | if !reflect.DeepEqual(got, &want) { 180 | t.Errorf("User GetCurrent is %v, want %v", got, want) 181 | } 182 | } 183 | 184 | func TestUser_UpdateCurrent_200(t *testing.T) { 185 | // setup context 186 | gin.SetMode(gin.TestMode) 187 | 188 | s := httptest.NewServer(server.FakeHandler()) 189 | c, _ := NewClient(s.URL, "", nil) 190 | 191 | data := []byte(server.UserResp) 192 | 193 | var want api.User 194 | 195 | _ = json.Unmarshal(data, &want) 196 | 197 | favorites := []string{"github/octocat"} 198 | 199 | req := api.User{ 200 | Favorites: &favorites, 201 | } 202 | 203 | // run test 204 | got, resp, err := c.User.UpdateCurrent(&req) 205 | if err != nil { 206 | t.Errorf("User UpdateCurrent returned err: %v", err) 207 | } 208 | 209 | if resp.StatusCode != http.StatusOK { 210 | t.Errorf("User UpdateCurrent returned %v, want %v", resp.StatusCode, http.StatusOK) 211 | } 212 | 213 | if !reflect.DeepEqual(got, &want) { 214 | t.Errorf("User UpdateCurrent is %v, want %v", got, want) 215 | } 216 | } 217 | 218 | func TestUser_UpdateCurrent_401(t *testing.T) { 219 | // setup context 220 | gin.SetMode(gin.TestMode) 221 | 222 | s := httptest.NewServer(server.FakeHandler()) 223 | c, _ := NewClient(s.URL, "", nil) 224 | 225 | c.Authentication.SetTokenAuth("invalid") 226 | 227 | want := api.User{} 228 | 229 | favorites := []string{"github/octocat"} 230 | 231 | req := api.User{ 232 | Favorites: &favorites, 233 | } 234 | 235 | // run test 236 | got, resp, err := c.User.UpdateCurrent(&req) 237 | if err == nil { 238 | t.Errorf("User UpdateCurrent should have returned err") 239 | } 240 | 241 | if resp.StatusCode != http.StatusUnauthorized { 242 | t.Errorf("User UpdateCurrent returned %v, want %v", resp.StatusCode, http.StatusUnauthorized) 243 | } 244 | 245 | if !reflect.DeepEqual(got, &want) { 246 | t.Errorf("User UpdateCurrent is %v, want %v", got, want) 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /vela/vela.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | // Bool is a helper routine that allocates a new boolean 6 | // value to store v and returns a pointer to it. 7 | func Bool(v bool) *bool { return &v } 8 | 9 | // Bytes is a helper routine that allocates a new byte 10 | // array value to store v and returns a pointer to it. 11 | func Bytes(v []byte) *[]byte { return &v } 12 | 13 | // Int is a helper routine that allocates a new integer 14 | // value to store v and returns a pointer to it. 15 | func Int(v int) *int { return &v } 16 | 17 | // Int32 is a helper routine that allocates a new 32 bit 18 | // integer value to store v and returns a pointer to it. 19 | func Int32(v int32) *int32 { return &v } 20 | 21 | // Int64 is a helper routine that allocates a new 64 bit 22 | // integer value to store v and returns a pointer to it. 23 | func Int64(v int64) *int64 { return &v } 24 | 25 | // UInt64 is a helper routine that allocates a new unsigned 64 bit 26 | // integer value to store v and returns a pointer to it. 27 | func UInt64(v uint64) *uint64 { return &v } 28 | 29 | // String is a helper routine that allocates a new string 30 | // value to store v and returns a pointer to it. 31 | func String(v string) *string { return &v } 32 | 33 | // Strings is a helper routine that allocates a new string 34 | // array value to store v and returns a pointer to it. 35 | func Strings(v []string) *[]string { return &v } 36 | -------------------------------------------------------------------------------- /vela/vela_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "reflect" 7 | "testing" 8 | ) 9 | 10 | func TestVela_Bool(t *testing.T) { 11 | // setup types 12 | _bool := false 13 | 14 | want := &_bool 15 | 16 | // run test 17 | got := Bool(_bool) 18 | 19 | if !reflect.DeepEqual(got, want) { 20 | t.Errorf("Bool is %v, want %v", got, want) 21 | } 22 | } 23 | 24 | func TestVela_Bytes(t *testing.T) { 25 | // setup types 26 | _bytes := []byte("foo") 27 | 28 | want := &_bytes 29 | 30 | // run test 31 | got := Bytes(_bytes) 32 | 33 | if !reflect.DeepEqual(got, want) { 34 | t.Errorf("Bytes is %v, want %v", got, want) 35 | } 36 | } 37 | 38 | func TestVela_Int(t *testing.T) { 39 | // setup types 40 | _int := 1 41 | 42 | want := &_int 43 | 44 | // run test 45 | got := Int(_int) 46 | 47 | if !reflect.DeepEqual(got, want) { 48 | t.Errorf("Int is %v, want %v", got, want) 49 | } 50 | } 51 | 52 | func TestVela_Int64(t *testing.T) { 53 | // setup types 54 | _int64 := int64(1) 55 | 56 | want := &_int64 57 | 58 | // run test 59 | got := Int64(_int64) 60 | 61 | if !reflect.DeepEqual(got, want) { 62 | t.Errorf("Int64 is %v, want %v", got, want) 63 | } 64 | } 65 | 66 | func TestVela_String(t *testing.T) { 67 | // setup types 68 | _string := "foo" 69 | 70 | want := &_string 71 | 72 | // run test 73 | got := String(_string) 74 | 75 | if !reflect.DeepEqual(got, want) { 76 | t.Errorf("String is %v, want %v", got, want) 77 | } 78 | } 79 | 80 | func TestVela_Strings(t *testing.T) { 81 | // setup types 82 | _strings := []string{"foo"} 83 | 84 | want := &_strings 85 | 86 | // run test 87 | got := Strings(_strings) 88 | 89 | if !reflect.DeepEqual(got, want) { 90 | t.Errorf("Strings is %v, want %v", got, want) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /vela/worker.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "fmt" 7 | 8 | api "github.com/go-vela/server/api/types" 9 | ) 10 | 11 | // WorkerService handles retrieving workers from 12 | // the server methods of the Vela API. 13 | type WorkerService service 14 | 15 | // WorkerListOptions specifies the optional parameters to the 16 | // Worker.GetAll method. 17 | type WorkerListOptions struct { 18 | Active string `url:"active,omitempty"` 19 | CheckedInBefore int64 `url:"checked_in_before,omitempty"` 20 | CheckedInAfter int64 `url:"checked_in_after,omitempty"` 21 | } 22 | 23 | // Get returns the provided worker. 24 | func (svc *WorkerService) Get(hostname string) (*api.Worker, *Response, error) { 25 | // set the API endpoint path we send the request to 26 | u := fmt.Sprintf("/api/v1/workers/%s", hostname) 27 | 28 | // api Worker type we want to return 29 | v := new(api.Worker) 30 | 31 | // send request using client 32 | resp, err := svc.client.Call("GET", u, nil, v) 33 | 34 | return v, resp, err 35 | } 36 | 37 | // GetAll returns a list of all workers. 38 | func (svc *WorkerService) GetAll(opt *WorkerListOptions) (*[]api.Worker, *Response, error) { 39 | // set the API endpoint path we send the request to 40 | u := "/api/v1/workers" 41 | 42 | // add optional arguments if supplied 43 | u, err := addOptions(u, opt) 44 | if err != nil { 45 | return nil, nil, err 46 | } 47 | 48 | // slice API Worker type we want to return 49 | v := new([]api.Worker) 50 | 51 | // send request using client 52 | resp, err := svc.client.Call("GET", u, nil, v) 53 | 54 | return v, resp, err 55 | } 56 | 57 | // Add constructs a worker with the provided details. 58 | func (svc *WorkerService) Add(w *api.Worker) (*api.Token, *Response, error) { 59 | // set the API endpoint path we send the request to 60 | u := "/api/v1/workers" 61 | 62 | // API Token type we want to return 63 | v := new(api.Token) 64 | 65 | // send request using client 66 | resp, err := svc.client.Call("POST", u, w, v) 67 | 68 | return v, resp, err 69 | } 70 | 71 | // RefreshAuth exchanges a worker token for a new one. 72 | func (svc *WorkerService) RefreshAuth(worker string) (*api.Token, *Response, error) { 73 | // set the API endpoint path we send the request to 74 | u := fmt.Sprintf("/api/v1/workers/%s/refresh", worker) 75 | 76 | // API Token type we want to return 77 | v := new(api.Token) 78 | 79 | // send request using client 80 | resp, err := svc.client.Call("POST", u, nil, v) 81 | 82 | return v, resp, err 83 | } 84 | 85 | // Update modifies a worker with the provided details. 86 | func (svc *WorkerService) Update(worker string, w *api.Worker) (*api.Worker, *Response, error) { 87 | // set the API endpoint path we send the request to 88 | u := fmt.Sprintf("/api/v1/workers/%s", worker) 89 | 90 | // API Worker type we want to return 91 | v := new(api.Worker) 92 | 93 | // send request using client 94 | resp, err := svc.client.Call("PUT", u, w, v) 95 | 96 | return v, resp, err 97 | } 98 | 99 | // Remove deletes the provided worker. 100 | func (svc *WorkerService) Remove(worker string) (*string, *Response, error) { 101 | // set the API endpoint path we send the request to 102 | u := fmt.Sprintf("/api/v1/workers/%s", worker) 103 | 104 | // string type we want to return 105 | v := new(string) 106 | 107 | // send request using client 108 | resp, err := svc.client.Call("DELETE", u, nil, v) 109 | 110 | return v, resp, err 111 | } 112 | -------------------------------------------------------------------------------- /vela/worker_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package vela 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "net/http" 9 | "net/http/httptest" 10 | "reflect" 11 | "testing" 12 | 13 | "github.com/gin-gonic/gin" 14 | 15 | api "github.com/go-vela/server/api/types" 16 | "github.com/go-vela/server/mock/server" 17 | ) 18 | 19 | func TestWorker_Get_200(t *testing.T) { 20 | // setup context 21 | gin.SetMode(gin.TestMode) 22 | 23 | s := httptest.NewServer(server.FakeHandler()) 24 | c, _ := NewClient(s.URL, "", nil) 25 | 26 | data := []byte(server.WorkerResp) 27 | 28 | var want api.Worker 29 | 30 | _ = json.Unmarshal(data, &want) 31 | 32 | // run test 33 | got, resp, err := c.Worker.Get("worker_1") 34 | if err != nil { 35 | t.Errorf("Worker get returned err: %v", err) 36 | } 37 | 38 | if resp.StatusCode != http.StatusOK { 39 | t.Errorf("Worker get returned %v, want %v", resp.StatusCode, http.StatusOK) 40 | } 41 | 42 | if !reflect.DeepEqual(got, &want) { 43 | t.Errorf("Worker get is %v, want %v", got, want) 44 | } 45 | } 46 | 47 | func TestWorker_Get_404(t *testing.T) { 48 | // setup context 49 | gin.SetMode(gin.TestMode) 50 | 51 | s := httptest.NewServer(server.FakeHandler()) 52 | c, _ := NewClient(s.URL, "", nil) 53 | 54 | want := api.Worker{} 55 | 56 | // run test 57 | got, resp, err := c.Worker.Get("0") 58 | if err == nil { 59 | t.Errorf("Worker get returned err: %v", err) 60 | } 61 | 62 | if resp.StatusCode != http.StatusNotFound { 63 | t.Errorf("Worker get returned %v, want %v", resp.StatusCode, http.StatusNotFound) 64 | } 65 | 66 | if !reflect.DeepEqual(got, &want) { 67 | t.Errorf("Worker get is %v, want %v", got, want) 68 | } 69 | } 70 | 71 | func TestWorker_GetAll_200(t *testing.T) { 72 | // setup context 73 | gin.SetMode(gin.TestMode) 74 | 75 | s := httptest.NewServer(server.FakeHandler()) 76 | c, _ := NewClient(s.URL, "", nil) 77 | 78 | data := []byte(server.WorkersResp) 79 | 80 | var want []api.Worker 81 | 82 | _ = json.Unmarshal(data, &want) 83 | 84 | // run test 85 | got, resp, err := c.Worker.GetAll(nil) 86 | if err != nil { 87 | t.Errorf("Worker get all returned err: %v", err) 88 | } 89 | 90 | if resp.StatusCode != http.StatusOK { 91 | t.Errorf("Worker returned %v, want %v", resp.StatusCode, http.StatusOK) 92 | } 93 | 94 | if !reflect.DeepEqual(got, &want) { 95 | t.Errorf("Worker getall is %v, want %v", got, want) 96 | } 97 | } 98 | 99 | func TestWorker_Add_201(t *testing.T) { 100 | // setup context 101 | gin.SetMode(gin.TestMode) 102 | 103 | s := httptest.NewServer(server.FakeHandler()) 104 | c, _ := NewClient(s.URL, "", nil) 105 | 106 | data := []byte(server.AddWorkerResp) 107 | 108 | var want api.Token 109 | 110 | _ = json.Unmarshal(data, &want) 111 | 112 | req := api.Worker{ 113 | ID: Int64(1), 114 | Hostname: String("worker_1"), 115 | Address: String("http://vela:8080"), 116 | Routes: Strings([]string{ 117 | "large", 118 | "docker", 119 | "large:docker", 120 | }), 121 | Active: Bool(true), 122 | LastCheckedIn: Int64(1602612590), 123 | } 124 | 125 | // run test 126 | got, resp, err := c.Worker.Add(&req) 127 | if err != nil { 128 | t.Errorf("Worker add returned err: %v", err) 129 | } 130 | 131 | if resp.StatusCode != http.StatusCreated { 132 | t.Errorf("Worker add returned %v, want %v", resp.StatusCode, http.StatusCreated) 133 | } 134 | 135 | if !reflect.DeepEqual(got, &want) { 136 | t.Errorf("Worker add is %v, want %v", got, want) 137 | } 138 | } 139 | 140 | func TestWorker_RefreshAuth_200(t *testing.T) { 141 | // setup context 142 | gin.SetMode(gin.TestMode) 143 | 144 | s := httptest.NewServer(server.FakeHandler()) 145 | c, _ := NewClient(s.URL, "", nil) 146 | 147 | data := []byte(server.AddWorkerResp) 148 | 149 | var want api.Token 150 | 151 | _ = json.Unmarshal(data, &want) 152 | 153 | worker := "worker_1" 154 | 155 | // run test 156 | got, resp, err := c.Worker.RefreshAuth(worker) 157 | if err != nil { 158 | t.Errorf("Worker RefreshAuth returned err: %v", err) 159 | } 160 | 161 | if resp.StatusCode != http.StatusOK { 162 | t.Errorf("Worker RefreshAuth returned %v, want %v", resp.StatusCode, http.StatusOK) 163 | } 164 | 165 | if !reflect.DeepEqual(got, &want) { 166 | t.Errorf("Worker RefreshAuth is %v, want %v", got, want) 167 | } 168 | } 169 | 170 | func TestWorker_RefreshAuth_404(t *testing.T) { 171 | // setup context 172 | gin.SetMode(gin.TestMode) 173 | 174 | s := httptest.NewServer(server.FakeHandler()) 175 | c, _ := NewClient(s.URL, "", nil) 176 | 177 | worker := "0" 178 | 179 | // run test 180 | _, resp, err := c.Worker.RefreshAuth(worker) 181 | if err == nil { 182 | t.Error("Worker RefreshAuth should have returned err") 183 | } 184 | 185 | if resp.StatusCode != http.StatusNotFound { 186 | t.Errorf("Worker RefreshAuth returned %v, want %v", resp.StatusCode, http.StatusNotFound) 187 | } 188 | } 189 | 190 | func TestWorker_Update_200(t *testing.T) { 191 | // setup context 192 | gin.SetMode(gin.TestMode) 193 | 194 | s := httptest.NewServer(server.FakeHandler()) 195 | c, _ := NewClient(s.URL, "", nil) 196 | 197 | data := []byte(server.WorkerResp) 198 | 199 | var want api.Worker 200 | 201 | _ = json.Unmarshal(data, &want) 202 | 203 | req := api.Worker{ 204 | Active: Bool(true), 205 | } 206 | 207 | // run test 208 | got, resp, err := c.Worker.Update("worker_1", &req) 209 | if err != nil { 210 | t.Errorf("Worker update returned err: %v", err) 211 | } 212 | 213 | if resp.StatusCode != http.StatusOK { 214 | t.Errorf("Worker returned %v, want %v", resp.StatusCode, http.StatusOK) 215 | } 216 | 217 | if !reflect.DeepEqual(got, &want) { 218 | t.Errorf("Worker create is %v, want %v", got, want) 219 | } 220 | } 221 | 222 | func TestWorker_Update_404(t *testing.T) { 223 | // setup context 224 | gin.SetMode(gin.TestMode) 225 | 226 | s := httptest.NewServer(server.FakeHandler()) 227 | c, _ := NewClient(s.URL, "", nil) 228 | 229 | want := api.Worker{} 230 | 231 | req := api.Worker{ 232 | Active: Bool(true), 233 | } 234 | 235 | // run test 236 | got, resp, err := c.Worker.Update("0", &req) 237 | if err == nil { 238 | t.Errorf("Worker update returned err: %v", err) 239 | } 240 | 241 | if resp.StatusCode != http.StatusNotFound { 242 | t.Errorf("Worker returned %v, want %v", resp.StatusCode, http.StatusNotFound) 243 | } 244 | 245 | if !reflect.DeepEqual(got, &want) { 246 | t.Errorf("Worker update is %v, want %v", got, want) 247 | } 248 | } 249 | 250 | func TestWorker_Remove_200(t *testing.T) { 251 | // setup context 252 | gin.SetMode(gin.TestMode) 253 | 254 | s := httptest.NewServer(server.FakeHandler()) 255 | c, _ := NewClient(s.URL, "", nil) 256 | 257 | // run test 258 | _, resp, err := c.Worker.Remove("worker_1") 259 | if err != nil { 260 | t.Errorf("Worker remove returned err: %v", err) 261 | } 262 | 263 | if resp.StatusCode != http.StatusOK { 264 | t.Errorf("Worker remove returned %v, want %v", resp.StatusCode, http.StatusOK) 265 | } 266 | } 267 | 268 | func TestWorker_Remove_404(t *testing.T) { 269 | // setup context 270 | gin.SetMode(gin.TestMode) 271 | 272 | s := httptest.NewServer(server.FakeHandler()) 273 | c, _ := NewClient(s.URL, "", nil) 274 | 275 | // run test 276 | _, resp, err := c.Worker.Remove("0") 277 | if err == nil { 278 | t.Errorf("Worker remove returned err: %v", err) 279 | } 280 | 281 | if resp.StatusCode != http.StatusNotFound { 282 | t.Errorf("Worker remove returned %v, want %v", resp.StatusCode, http.StatusNotFound) 283 | } 284 | } 285 | 286 | func ExampleWorkerService_Get() { 287 | // Create a new vela client for interacting with server 288 | c, _ := NewClient("http://localhost:8080", "", nil) 289 | 290 | // Set new token in existing client 291 | c.Authentication.SetPersonalAccessTokenAuth("token") 292 | 293 | // Get a worker from the server 294 | worker, resp, err := c.Worker.Get("worker_1") 295 | if err != nil { 296 | fmt.Println(err) 297 | } 298 | 299 | fmt.Printf("Received response code %d, for worker %+v", resp.StatusCode, worker) 300 | } 301 | 302 | func ExampleWorkerService_GetAll() { 303 | // Create a new vela client for interacting with server 304 | c, _ := NewClient("http://localhost:8080", "", nil) 305 | 306 | // Set new token in existing client 307 | c.Authentication.SetPersonalAccessTokenAuth("token") 308 | 309 | // Get all the workers from the server 310 | workers, resp, err := c.Worker.GetAll(nil) 311 | if err != nil { 312 | fmt.Println(err) 313 | } 314 | 315 | fmt.Printf("Received response code %d, for workers %+v", resp.StatusCode, workers) 316 | } 317 | 318 | func ExampleWorkerService_Add() { 319 | // Create a new vela client for interacting with server 320 | c, _ := NewClient("http://localhost:8080", "", nil) 321 | 322 | // Set new token in existing client 323 | c.Authentication.SetPersonalAccessTokenAuth("token") 324 | 325 | req := api.Worker{ 326 | ID: Int64(1), 327 | Hostname: String("worker_1"), 328 | Address: String("http://vela:8080"), 329 | Routes: Strings([]string{ 330 | "large", 331 | "docker", 332 | "large:docker", 333 | }), 334 | Active: Bool(true), 335 | LastCheckedIn: Int64(1602612590), 336 | } 337 | 338 | // Create the worker in the server 339 | worker, resp, err := c.Worker.Add(&req) 340 | if err != nil { 341 | fmt.Println(err) 342 | } 343 | 344 | fmt.Printf("Received response code %d, for worker %+v", resp.StatusCode, worker) 345 | } 346 | 347 | func ExampleWorkerService_RefreshAuth() { 348 | // Create a new vela client for interacting with server 349 | c, _ := NewClient("http://localhost:8080", "", nil) 350 | 351 | // Set new token in existing client 352 | c.Authentication.SetPersonalAccessTokenAuth("token") 353 | 354 | worker := "worker_1" 355 | 356 | // Refresh a worker token with the server 357 | _, resp, err := c.Worker.RefreshAuth(worker) 358 | if err != nil { 359 | fmt.Println(err) 360 | } 361 | 362 | fmt.Printf("Received response code %d, for worker %+v", resp.StatusCode, worker) 363 | } 364 | 365 | func ExampleWorkerService_Update() { 366 | // Create a new vela client for interacting with server 367 | c, _ := NewClient("http://localhost:8080", "", nil) 368 | 369 | // Set new token in existing client 370 | c.Authentication.SetPersonalAccessTokenAuth("token") 371 | 372 | req := api.Worker{ 373 | Active: Bool(false), 374 | } 375 | 376 | // Update the worker in the server 377 | worker, resp, err := c.Worker.Update("worker_1", &req) 378 | if err != nil { 379 | fmt.Println(err) 380 | } 381 | 382 | fmt.Printf("Received response code %d, for worker %+v", resp.StatusCode, worker) 383 | } 384 | 385 | func ExampleWorkerService_Remove() { 386 | // Create a new vela client for interacting with server 387 | c, _ := NewClient("http://localhost:8080", "", nil) 388 | 389 | // Set new token in existing client 390 | c.Authentication.SetPersonalAccessTokenAuth("token") 391 | 392 | // Remove the worker in the server 393 | worker, resp, err := c.Worker.Remove("worker_1") 394 | if err != nil { 395 | fmt.Println(err) 396 | } 397 | 398 | fmt.Printf("Received response code %d, for worker %+v", resp.StatusCode, worker) 399 | } 400 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | 3 | package version 4 | 5 | import "github.com/coreos/go-semver/semver" 6 | 7 | var ( 8 | // VersionMajor is for an API incompatible changes. 9 | VersionMajor int64 10 | // VersionMinor is for functionality in a backwards-compatible manner. 11 | VersionMinor int64 = 27 12 | // VersionPatch is for backwards-compatible bug fixes. 13 | VersionPatch int64 14 | ) 15 | 16 | // Version is the specification version that the package types support. 17 | var Version = semver.Version{ 18 | Major: VersionMajor, 19 | Minor: VersionMinor, 20 | Patch: VersionPatch, 21 | } 22 | --------------------------------------------------------------------------------