Skip to content

Commit

Permalink
changes per code review (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
dumpsterfireproject committed Jul 21, 2022
1 parent d2d184b commit 08f6186
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 52 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/release-go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Release Go

on:
push:
branches: [release/*]

jobs:
read-version:
name: Read version to release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.versions.outputs.changelog-latest-version }}
steps:
- uses: actions/checkout@v3
- uses: cucumber/[email protected]
id: versions

publish-go:
name: Create go/v* tag
runs-on: ubuntu-latest
needs: read-version
steps:
- uses: actions/checkout@v3
- name: Create git tag
run: |
git tag "go/v${{ needs.read-version.outputs.version }}"
git push --tags
25 changes: 3 additions & 22 deletions .github/workflows/test-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,12 @@ jobs:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Go cache
uses: actions/cache@v2
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-cache-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-cache
- name: Run gofmt
- name: lint
working-directory: go
run: gofmt -d -e . 2>&1 | tee outfile && test -z "$(cat outfile)" && rm outfile
# - name: Run staticcheck
# if: matrix.go-version == '1.17.x'
# run: |
# bin/staticcheck_linux_amd64_2021.1.2 github.com/cucumber/ci-environment/go
run: gofmt -w .
- name: Run go vet
working-directory: go
run: go vet ./...
- name: Run go test
working-directory: go
run: go test ./...
# run: go test -coverprofile=coverage.txt -covermode=atomic ./...
# - name: Report on code coverage
# if: matrix.go-version == '1.17.x'
# uses: codecov/codecov-action@v1
# with:
# file: ./go/coverage.txt
run: make test
2 changes: 1 addition & 1 deletion go/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ test: copy-template check-go-version
@go fmt ./...
@go run honnef.co/go/tools/cmd/[email protected] github.com/cucumber/ci-environment/go
go vet ./...
go test -race ./...
go test ./...
54 changes: 27 additions & 27 deletions go/README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
# CI-Environment: Go

This directory contains the Go implementation of te ci-environment implementation.
To embed the templates for the ci-environment go module, we'll use go:embed to include CIEnvironments.json.
Since go:embed does not support paths which include `..`, we can't just use a path the the CIEnvironments.json
file in the root of the git repository. So a Makefile is included in this go module which will handle copying the
most recent template from the root of the git repository to the go directory.

The CIEnvironments.json file contains the templates to map available environment variables to values in templates
for the variety of supported CI enviroments. Many are simple replacements of environment variables. E.g, for
Azure DevOps, the URI is simply the value of the `${BUILD_BUILDURI}` environment variable. For others, it is a
combination of multiple enviroment variables and constants. E.g., for Github Actions, the URI is the combination
of `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`. Still for others, there is some
additional processing of values that can be found in environment variables. In these cases, the value in the
template consists of three parts: the environment variable to be used, the regex expression (including capture
groups) to to used to derive the final value, and the template to be applied using the value(s) from those
capture groups. E.g., the Git remote template for CodeShip has a value of `${CI_PULL_REQUEST/(.*)\\/pull\\/\\d+/\\1.git}`.
The sections of this expression are delineated by unescaped slashes. So the three parts are the `CI_PULL_REQUEST`
environment variable, the regex of `(.*)\\/pull\\/\\d+`, and the template of `\\1.git`. So in this example, the URL
in the CI_PULL_REQUEST environment variable will have everything prior to `pull/\d+` in a capture group, then the first
(and only in this example) capture group is prepended to the literal `.git`. So if the CI_PULL_REQUEST envrionment variable
were `https://github.com/owner/repo/pull/42`, then the value of `https://github.com/owner/repo` would be part of that
first capture group, and then the resulting value will be `https://github.com/owner/repo.git`. Or as explained in
ARCHITECTURE.md,
This directory contains the Go implementation of the ci-environment implementation.

## Template Locations
To embed the templates for the ci-environment go module, we'll use go:embed to include CIEnvironments.json. Since go:embed does not support paths which include `..`, we can't just use a path the the CIEnvironments.json file in the root of the git repository. So a Makefile is included in this go module which will handle copying the most recent template from the root of the git repository to the go directory. The CiEnvironments.json file contains the templates to map available environment variables to values in templates for the variety of supported CI enviroments.

## Template Expressions

### Simple Environment Variables
Many are simple replacements of environment variables. E.g, for Azure DevOps, the URI is simply the value of the `${BUILD_BUILDURI}` environment variable.

### Multiple Environment Variables and/or Constants
For others, it is a combination of multiple enviroment variables and constants. E.g., for Github Actions, the URI is the combination of `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`.

### Expression Syntax
Still for others, there is some additional processing of values that can be found in environment variables. In these cases, the value in the template consists of three parts: the environment variable to be used, the regex expression (including capture groups) to to used to derive the final value, and the template to be applied using the value(s) from those
capture groups.

E.g., the Git remote template for CodeShip has a value of `${CI_PULL_REQUEST/(.*)\\/pull\\/\\d+/\\1.git}`. The sections of this expression are delineated by unescaped slashes. So the three parts are the `CI_PULL_REQUEST` environment variable, the regex of `(.*)\\/pull\\/\\d+`, and the template of `\\1.git`.

So in this example, the URL in the CI_PULL_REQUEST environment variable will have everything prior to `pull/\d+` in a capture group, then the first (and only in this example) capture group is prepended to the literal `.git`. So if the CI_PULL_REQUEST envrionment variable were `https://github.com/owner/repo/pull/42`, then the value of `https://github.com/owner/repo` would be part of that first capture group, and then the resulting value will be `https://github.com/owner/repo.git`.

Or as explained in ARCHITECTURE.md:
>The expression syntax for environment variables can use the form `${variable/pattern/replacement}`, similar to [bash parameter substitution](https://tldp.org/LDP/abs/html/parameter-substitution.html), but inspired from [sed's s command](https://www.gnu.org/software/sed/manual/html_node/The-_0022s_0022-Command.html) which provides support for capture group back-references in the replacement.
Note that in other implementations, such as the javascript implementation, for ci-environments, a regex can be
used when evaluating the variable/pattern/replacement expressions. An example regex is `'\\${(.*?)(?:(?<!\\\\)/(.*)/(.*))?}'`.
However, for Go, the [Google/re2](https://github.com/google/re2/wiki/Syntax) syntax does not support `after text not matching`
expressions in the form of `(?<!re)`. So a quick and simple parser was put together to evaluate these expressions in
lieu of using regex.
### Wildcards in Environment Variable Names
In some expressions, an environment variable name can contain a wildcard, e.g., GoCD. The git branch is derived using `GO_SCM_*_PR_BRANCH`. In this situation, the environment variable name contains the branch name (e.g., GO_SCM_MY_MATERIAL_PR_BRANCH where the branch name is MY_MATERIAL) and is thus not a constant. So the wildcard is used as a placeholder and when evaluating the expression, we must loop through all the environment variables until we find the one that matches the pattern.

## Why Parse the Template Expressions?
In other implementations, such as the javascript implementation for ci-environments, a regex can be used when evaluating the variable/pattern/replacement expressions. An example regex is `'\\${(.*?)(?:(?<!\\\\)/(.*)/(.*))?}'`. However, for Go, the [Google/re2](https://github.com/google/re2/wiki/Syntax) syntax does not support `after text not matching` expressions in the form of `(?<!re)`. So a quick and simple parser was put together to evaluate these expressions in lieu of using regex.
8 changes: 6 additions & 2 deletions go/detect_environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type testCase struct {
want *cienvironment.CiEnvironment
}

func TestDetectCIEnvironment(t *testing.T) {
func TestDetectCIEnvironment_AcceptanceTests(t *testing.T) {
testCases := loadTestData()
for _, tc := range testCases {
t.Run(tc.fileName, testDetectCIEnvironment(tc.envVars, tc.want))
Expand Down Expand Up @@ -51,7 +51,11 @@ func testDetectCIEnvironment(envVars map[string]string, want *cienvironment.CiEn
assert.Equal(t, want.Git.Branch, got.Git.Branch, "Git.Branch for %s", want.Name)
assert.Equal(t, want.Git.Remote, got.Git.Remote, "Git.Remote for %s", want.Name)
assert.Equal(t, want.Git.Tag, got.Git.Tag, "Git.Tag for %s", want.Name)
if want.Name != "GitHub Actions" { // TODO: EXPLAIN!
// In the acceptance test files (../testdata), for GitHubActionsPullRequestOpened and GitHubActionsPullRequestSynchronize,
// the .txt file has a GITHUB_SHA of 99684bcacf01d95875834d87903dcb072306c9ad, but the json files have expected
// git.revision values of d79b417f8e974b9a2d5e6483845a96446695f944 and 3738117e3337e54955580f4e98cf767d96b42135, respectively.
// The template is "revision": "${GITHUB_SHA}",
if want.Name != "GitHub Actions" {
assert.Equal(t, want.Git.Revision, got.Git.Revision, "Git.Revision for %s", want.Name)
}
}
Expand Down

0 comments on commit 08f6186

Please sign in to comment.