Skip to content

Commit

Permalink
Merge branch 'main' into adamdmharvey/enable-setup-in-examples
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdmharvey authored Mar 10, 2023
2 parents 8d77691 + f59d90e commit 8722150
Show file tree
Hide file tree
Showing 34 changed files with 1,889 additions and 1,198 deletions.
27 changes: 17 additions & 10 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1

orbs:
shellcheck: circleci/[email protected]
windows: circleci/windows@2.2.0
windows: circleci/windows@5.0.0

executors:
go:
Expand Down Expand Up @@ -82,19 +82,22 @@ commands:

jobs:
test_windows:
executor: windows/default
executor:
name: windows/default
shell: bash --login -eo pipefail
steps:
- run: git config --global core.autocrlf false
- checkout
- run: setx GOPATH %USERPROFILE%\go
- run: go get gotest.tools/gotestsum
- run: mkdir test_results
- run: setx TESTING "true"

- run:
name: Run tests
command: |
C:\Users\circleci\go\bin\gotestsum.exe --junitfile test_results/windows.xml
export GOBIN=/c/go/bin
export PATH=$GOBIN:$PATH
export TESTING="true"
go install gotest.tools/gotestsum@latest
gotestsum --junitfile test_results/windows.xml
- store_test_results:
path: test_results
- store_artifacts:
Expand Down Expand Up @@ -267,9 +270,9 @@ jobs:
brew-deploy:
executor: mac
environment:
- USER: circleci
- TRAVIS: circleci
- DESTDIR: /Users/distiller/dest
USER: circleci
TRAVIS: circleci
DESTDIR: /Users/distiller/dest
steps:
- checkout
- force-http-1
Expand Down Expand Up @@ -332,6 +335,8 @@ workflows:
- brew-deploy:
requires:
- run-brew-deploy-gate
context:
- devex-release
- deploy:
requires:
- test
Expand All @@ -342,4 +347,6 @@ workflows:
- shellcheck/check
filters:
branches:
only: master
only: main
context:
- devex-release
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
* @CircleCI-Public/Extensibility
*orb*.go @CircleCI-Public/CPEng @CircleCI-Public/Extensibility
* @CircleCI-Public/developer-experience
*orb*.go @CircleCI-Public/CPEng @CircleCI-Public/developer-experience

/api/runner @CircleCI-Public/runner
/cmd/runner @CircleCI-Public/runner
Expand Down
4 changes: 2 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have checked for similar issues and haven't found anything relevant.
- [ ] This is not a security issue (which should be reported here: https://circleci.com/security/)
- [ ] I have read [Contribution Guidelines](https://github.com/CircleCI-Public/circleci-cli/blob/master/CONTRIBUTING.md).
- [ ] I have read [Contribution Guidelines](https://github.com/CircleCI-Public/circleci-cli/blob/main/CONTRIBUTING.md).

### Internal Checklist
- [ ] I am requesting a review from my own team as well as the owning team
Expand Down Expand Up @@ -45,7 +45,7 @@ Image or gif where change can be clearly seen

## **Here are some helpful tips you can follow when submitting a pull request:**

1. Fork [the repository](https://github.com/CircleCI-Public/circleci-cli) and create your branch from `master`.
1. Fork [the repository](https://github.com/CircleCI-Public/circleci-cli) and create your branch from `main`.
2. Run `make build` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`make test`).
Expand Down
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,43 @@ choco install circleci-cli -y
You can also install the CLI binary by running our install script on most Unix platforms:

```
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | bash
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | bash
```

By default, the `circleci` app will be installed to the ``/usr/local/bin`` directory. If you do not have write permissions to `/usr/local/bin`, you may need to run the above command with `sudo`:

```
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | sudo bash
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | sudo bash
```

Alternatively, you can install to an alternate location by defining the `DESTDIR` environment variable when invoking `bash`:

```
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=/opt/bin bash
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | DESTDIR=/opt/bin bash
```

You can also set a specific version of the CLI to install with the `VERSION` environment variable:

```
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | VERSION=0.1.5222 sudo bash
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | VERSION=0.1.5222 sudo bash
```

#### Checksum verification

If you would like to verify the checksum yourself, you can download the checksum file from the [GitHub releases page](https://github.com/CircleCI-Public/circleci-cli/releases) and verify the checksum of the archive using the `circleci-cli_<version>_checksums.txt` inside the assets of the release you'd like to install:

On macOS and Linux:
```sh
shasum -a 256 circleci-cli_<version>_<os>.tar.gz
```

and on Windows:
```powershell
Get-FileHash .\circleci-cli_<version>_<os>.tar.gz -Algorithm SHA256 | Format-List
```

And compare it to the right checksum depending on the downloaded version in the `circleci-cli_<version>_checksums.txt` file.

### Updating

If you installed the CLI without a package manager, you can use its built-in update command to check for pending updates and download them:
Expand Down Expand Up @@ -135,17 +151,17 @@ The following commands are affected:

## Platforms, Deployment and Package Managers

The tool is deployed through a number of channels. The primary release channel is through [GitHub Releases](https://github.com/CircleCI-Public/circleci-cli/releases). Green builds on the `master` branch will publish a new GitHub release. These releases contain binaries for macOS, Linux and Windows. These releases are published from (CircleCI)[https://app.circleci.com/pipelines/github/CircleCI-Public/circleci-cli] using (GoReleaser)[https://goreleaser.com/].
The tool is deployed through a number of channels. The primary release channel is through [GitHub Releases](https://github.com/CircleCI-Public/circleci-cli/releases). Green builds on the `main` branch will publish a new GitHub release. These releases contain binaries for macOS, Linux and Windows. These releases are published from (CircleCI)[https://app.circleci.com/pipelines/github/CircleCI-Public/circleci-cli] using (GoReleaser)[https://goreleaser.com/].

### Homebrew

We publish the tool to [Homebrew](https://brew.sh/). The tool is [part of `homebrew-core`](https://github.com/Homebrew/homebrew-core/blob/master/Formula/circleci.rb), and therefore the maintainers of the tool are obligated to follow the guidelines for acceptable Homebrew formulae. You should [familairise yourself with the guidelines](https://docs.brew.sh/Acceptable-Formulae#we-dont-like-tools-that-upgrade-themselves) before making changes to the Homebrew deployment system.
We publish the tool to [Homebrew](https://brew.sh/). The tool is [part of `homebrew-core`](https://github.com/Homebrew/homebrew-core/blob/main/Formula/circleci.rb), and therefore the maintainers of the tool are obligated to follow the guidelines for acceptable Homebrew formulae. You should [familairise yourself with the guidelines](https://docs.brew.sh/Acceptable-Formulae#we-dont-like-tools-that-upgrade-themselves) before making changes to the Homebrew deployment system.

The particular considerations that we make are:


1. Since Homebrew [doesn't "like tools that upgrade themselves"](https://docs.brew.sh/Acceptable-Formulae#we-dont-like-tools-that-upgrade-themselves), we disable the `circleci update` command when the tool is released through homebrew. We do this by [defining the PackageManager](https://github.com/Homebrew/homebrew-core/blob/eb1fdb84e2924289bcc8c85ee45081bf83dc024d/Formula/circleci.rb#L28) constant to `homebrew`, which allows us to [disable the `update` command at runtime](https://github.com/CircleCI-Public/circleci-cli/blob/67c7d52bace63846f87a1ed79f67f257c94a55b4/cmd/root.go#L119-L123).
1. We want to avoid every push to `master` from creating a Pull Request to the `circleci` formula on Homebrew. We want to avoid overloading the Homebrew team with pull requests to update our formula for small changes (changes to docs or other files that don't change functionality in the tool).
1. We want to avoid every push to `main` from creating a Pull Request to the `circleci` formula on Homebrew. We want to avoid overloading the Homebrew team with pull requests to update our formula for small changes (changes to docs or other files that don't change functionality in the tool).

### Snap

Expand Down
9 changes: 5 additions & 4 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,7 @@ func ConfigQueryLegacy(cl *graphql.Client, configPath string, orgSlug string, pa
fieldAddendums)

request := graphql.NewRequest(query)
request.SetToken(cl.Token)
request.Var("config", config)

if values != nil {
Expand All @@ -560,8 +561,6 @@ func ConfigQueryLegacy(cl *graphql.Client, configPath string, orgSlug string, pa
request.Var("orgSlug", orgSlug)
}

request.SetToken(cl.Token)

err = cl.Run(request, &response)
if err != nil {
return nil, errors.Wrap(err, "Unable to validate config")
Expand Down Expand Up @@ -603,6 +602,7 @@ func ConfigQuery(cl *graphql.Client, configPath string, orgId string, params pip
fieldAddendums)

request := graphql.NewRequest(query)
request.SetToken(cl.Token)
request.Var("config", config)

if values != nil {
Expand All @@ -619,7 +619,6 @@ func ConfigQuery(cl *graphql.Client, configPath string, orgId string, params pip
if orgId != "" {
request.Var("orgId", orgId)
}
request.SetToken(cl.Token)

err = cl.Run(request, &response)
if err != nil {
Expand Down Expand Up @@ -1634,6 +1633,7 @@ query namespaceOrbs ($namespace: String, $after: String!) {

for {
request := graphql.NewRequest(query)
request.SetToken(cl.Token)
request.Var("after", currentCursor)
request.Var("namespace", namespace)

Expand Down Expand Up @@ -1813,7 +1813,7 @@ func OrbCategoryID(cl *graphql.Client, name string) (*OrbCategoryIDResponse, err
}`

request := graphql.NewRequest(query)

request.SetToken(cl.Token)
request.Var("name", name)

err := cl.Run(request, &response)
Expand Down Expand Up @@ -1917,6 +1917,7 @@ func ListOrbCategories(cl *graphql.Client) (*OrbCategoriesForListing, error) {

for {
request := graphql.NewRequest(query)
request.SetToken(cl.Token)
request.Var("after", currentCursor)

err := cl.Run(request, &result)
Expand Down
15 changes: 15 additions & 0 deletions api/project/project.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package project

// ProjectEnvironmentVariable is a Environment Variable of a Project
type ProjectEnvironmentVariable struct {
Name string
Value string
}

// ProjectClient is the interface to interact with project and it's
// components.
type ProjectClient interface {
ListAllEnvironmentVariables(vcs, org, project string) ([]*ProjectEnvironmentVariable, error)
GetEnvironmentVariable(vcs, org, project, envName string) (*ProjectEnvironmentVariable, error)
CreateEnvironmentVariable(vcs, org, project string, v ProjectEnvironmentVariable) (*ProjectEnvironmentVariable, error)
}
157 changes: 157 additions & 0 deletions api/project/project_rest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package project

import (
"fmt"
"net/url"

"github.com/CircleCI-Public/circleci-cli/api/rest"
"github.com/CircleCI-Public/circleci-cli/settings"
)

type projectRestClient struct {
token string
server string
client *rest.Client
}

var _ ProjectClient = &projectRestClient{}

type listProjectEnvVarsParams struct {
vcs string
org string
project string
pageToken string
}

type projectEnvVarResponse struct {
Name string
Value string
}

type listAllProjectEnvVarsResponse struct {
Items []projectEnvVarResponse
NextPageToken string `json:"next_page_token"`
}

type createProjectEnvVarRequest struct {
Name string `json:"name"`
Value string `json:"value"`
}

// NewProjectRestClient returns a new projectRestClient satisfying the api.ProjectInterface
// interface via the REST API.
func NewProjectRestClient(config settings.Config) (*projectRestClient, error) {
serverURL, err := config.ServerURL()
if err != nil {
return nil, err
}

client := &projectRestClient{
token: config.Token,
server: serverURL.String(),
client: rest.New(config.Host, &config),
}

return client, nil
}

// ListAllEnvironmentVariables returns all of the environment variables owned by the
// given project. Note that pagination is not supported - we get all
// pages of env vars and return them all.
func (p *projectRestClient) ListAllEnvironmentVariables(vcs, org, project string) ([]*ProjectEnvironmentVariable, error) {
res := make([]*ProjectEnvironmentVariable, 0)
var nextPageToken string
for {
resp, err := p.listEnvironmentVariables(&listProjectEnvVarsParams{
vcs: vcs,
org: org,
project: project,
pageToken: nextPageToken,
})
if err != nil {
return nil, err
}

for _, ev := range resp.Items {
res = append(res, &ProjectEnvironmentVariable{
Name: ev.Name,
Value: ev.Value,
})
}

if resp.NextPageToken == "" {
break
}

nextPageToken = resp.NextPageToken
}
return res, nil
}

func (c *projectRestClient) listEnvironmentVariables(params *listProjectEnvVarsParams) (*listAllProjectEnvVarsResponse, error) {
path := fmt.Sprintf("project/%s/%s/%s/envvar", params.vcs, params.org, params.project)
urlParams := url.Values{}
if params.pageToken != "" {
urlParams.Add("page-token", params.pageToken)
}

req, err := c.client.NewRequest("GET", &url.URL{Path: path, RawQuery: urlParams.Encode()}, nil)
if err != nil {
return nil, err
}

var resp listAllProjectEnvVarsResponse
_, err = c.client.DoRequest(req, &resp)
if err != nil {
return nil, err
}
return &resp, nil
}

// GetEnvironmentVariable retrieves and returns a variable with the given name.
// If the response status code is 404, nil is returned.
func (c *projectRestClient) GetEnvironmentVariable(vcs string, org string, project string, envName string) (*ProjectEnvironmentVariable, error) {
path := fmt.Sprintf("project/%s/%s/%s/envvar/%s", vcs, org, project, envName)
req, err := c.client.NewRequest("GET", &url.URL{Path: path}, nil)
if err != nil {
return nil, err
}

var resp projectEnvVarResponse
code, err := c.client.DoRequest(req, &resp)
if err != nil {
if code == 404 {
// Note: 404 may mean that the project isn't found.
// The cause can't be distinguished except by the response text.
return nil, nil
}
return nil, err
}
return &ProjectEnvironmentVariable{
Name: resp.Name,
Value: resp.Value,
}, nil
}

// CreateEnvironmentVariable creates a variable on the given project.
// This returns the variable if successfully created.
func (c *projectRestClient) CreateEnvironmentVariable(vcs string, org string, project string, v ProjectEnvironmentVariable) (*ProjectEnvironmentVariable, error) {
path := fmt.Sprintf("project/%s/%s/%s/envvar", vcs, org, project)
req, err := c.client.NewRequest("POST", &url.URL{Path: path}, &createProjectEnvVarRequest{
Name: v.Name,
Value: v.Value,
})
if err != nil {
return nil, err
}

var resp projectEnvVarResponse
_, err = c.client.DoRequest(req, &resp)
if err != nil {
return nil, err
}
return &ProjectEnvironmentVariable{
Name: resp.Name,
Value: resp.Value,
}, nil
}
Loading

0 comments on commit 8722150

Please sign in to comment.