diff --git a/.changelog/128.txt b/.changelog/128.txt new file mode 100644 index 00000000..9d2dd625 --- /dev/null +++ b/.changelog/128.txt @@ -0,0 +1,11 @@ +```release-note:improvement +Run tests in GitHub Actions instead of Circle CI. +``` + +```release-note:improvement +Upload test coverage artifacts to GitHub Actions job run. +``` + +```release-note:improvement +Set up up auto releaser with test gating. +``` diff --git a/.changelog/changelog.tmpl b/.changelog/changelog.tmpl new file mode 100644 index 00000000..dfef4401 --- /dev/null +++ b/.changelog/changelog.tmpl @@ -0,0 +1,47 @@ +{{- if index .NotesByType "breaking-change" -}} +BREAKING CHANGES: + +{{range index .NotesByType "breaking-change" -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.security }} +SECURITY: + +{{range .NotesByType.security -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.feature }} +FEATURES: + +{{range .NotesByType.feature -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.improvement }} +IMPROVEMENTS: + +{{range .NotesByType.improvement -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.deprecation }} +DEPRECATIONS: + +{{range .NotesByType.deprecation -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.bug }} +BUG FIXES: + +{{range .NotesByType.bug -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} diff --git a/.changelog/note.tmpl b/.changelog/note.tmpl new file mode 100644 index 00000000..0f9cd413 --- /dev/null +++ b/.changelog/note.tmpl @@ -0,0 +1,3 @@ +{{- define "note" -}} +{{.Body}}{{if not (stringHasPrefix .Issue "_")}} [[GH-{{- .Issue -}}](https://github.com/hashicorp/hcp-sdk-go/pull/{{- .Issue -}})]{{end}} +{{- end -}} diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 13011a8e..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,44 +0,0 @@ -version: 2 -jobs: - go/test: - docker: - - image: cimg/go:1.18 - environment: - - GO111MODULE: 'on' - - TEST_RESULTS: /tmp/test-results - - GOMAXPROCS: 8 - resource_class: xlarge - steps: - - checkout - - run: - command: | - go mod download - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0 - go install gotest.tools/gotestsum@v1.8.2 - go mod tidy - name: Get CI dependencies - - run: - command: | - make test-ci - go tool cover -html=cover.out -o=coverage.html - environment: - GO_TEST_ARGS: -coverprofile=cover.out - name: test - - store_artifacts: - destination: coverage.html - path: coverage.html - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results -workflows: - main: - jobs: - - go/test - version: 2 -experimental: - notify: - branches: - only: - - master - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a3b932fc..e61c9ecc 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,16 +7,6 @@ version of a service SDK was added, what are the key new features or breaking ch -### :ship: Release Note -Release note for [CHANGELOG](https://github.com/hashicorp/hcp-sdk-go/blob/main/CHANGELOG.md): - - -```release-note -... -``` - ### :+1: Definition of Done diff --git a/.github/workflows/changelog-check.yml b/.github/workflows/changelog-check.yml new file mode 100644 index 00000000..edc28e19 --- /dev/null +++ b/.github/workflows/changelog-check.yml @@ -0,0 +1,50 @@ +# This workflow checks that there is either a 'pr/no-changelog' label +# applied to a PR or there is a .changelog/.txt file associated +# with a PR for a changelog entry. +--- +name: Changelog Check + +on: + pull_request: + types: + - opened + - synchronize + - labeled + branches: + - main + +jobs: + changelog-check: + name: Changelog Check + # Ignore this check if there is a `pr/no-changelog` label + if: | + !contains(github.event.pull_request.labels.*.name, 'pr/no-changelog') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # by default the checkout action doesn't checkout all branches + + - name: Check for changelog entry in diff + run: | + # check if there is a diff in the changelog directory + changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" -- .changelog/${{ github.event.pull_request.number }}.txt) + # If we do not find a file matching the PR # in .changelog/, we fail the check + if [ -z "$changelog_files" ]; then + echo "::error::Did not find a changelog entry named ${{ github.event.pull_request.number }}.txt in .changelog/" + echo "::debug::For reference, refer to the README." + exit 1 + elif grep -q ':enhancement$' $changelog_files; then + # "Enhancement is not a valid type of changelog entry, but it's a common mistake. + echo "::error::Found invalid type (enhancement) in changelog - did you mean improvement?" + exit 1 + elif grep -q ':bugs$' $changelog_files; then + echo "::error::Found invalid type (bugs) in changelog - did you mean bug?" + exit 1 + elif ! grep -q '```release-note:' $changelog_files; then + # People often make changelog files like ```changelog:, which is incorrect. + echo "::error::Changelog file did not contain 'release-note' heading - check formatting." + exit 1 + else + echo "::debug::Found changelog entry in PR!" + fi diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 00000000..5a424a2a --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,105 @@ +name: Create Release + +on: + # Run Every Wednesday at 12:00 AM UTC + schedule: + - cron: '0 0 * * 3' + workflow_dispatch: + +permissions: write-all + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + token: ${{ secrets.HCP_SDK_PIPELINE_TOKEN }} + + - name: Setup Go + uses: actions/setup-go@v3 + with: + cache: true + go-version-file: 'go.mod' + + - name: Configure Git + env: + TOKEN: ${{ secrets.HCP_SDK_PIPELINE_TOKEN }} + run: | + git config --global advice.detachedHead false + git config --global url."https://${TOKEN}:x-oauth-basic@github.com/".insteadOf "https://github.com/" + git config user.name "hashicorp-cloud" + git config user.email "hashicorp-cloud@hashicorp.com" + + - name: Cache Go Dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install Go Binaries + env: + GOPRIVATE: 'github.com/hashicorp/*' + run: | + go install github.com/hashicorp/go-changelog/cmd/changelog-build@6ec9be372335f39c5df27e232c3669db7f5183a5 + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0 + + - name: Run Unit Tests and Linter + run: make test-ci + + - name: Upload Coverage Artifact + uses: actions/upload-artifact@v3 + with: + name: Test Coverage + path: coverage.html + + - name: Release New Version + env: + GOPRIVATE: 'github.com/hashicorp/*' + GITHUB_TOKEN: ${{ secrets.HCP_SDK_PIPELINE_TOKEN }} + run: | + CURRENT_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`) + SHOULD_RELEASE=$(git diff $CURRENT_VERSION main) + if [[ $SHOULD_RELEASE == "" ]]; then + echo "There were no changes since the last release. Skipping auto release."; + else + echo "There were changes since the last release." + echo "Current Version: $CURRENT_VERSION" + CURRENT_VERSION_PARTS=(${CURRENT_VERSION//./ }) + MAJOR=${CURRENT_VERSION_PARTS[0]} + MINOR=${CURRENT_VERSION_PARTS[1]} + PATCH=${CURRENT_VERSION_PARTS[2]} + HEAD_BRANCH="main" + MINOR=$((MINOR+1)) + NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}" + echo "updating ${CURRENT_VERSION} to ${NEW_VERSION}" + echo "generating changelog" + GIT_COMMIT_SHA=$(git rev-parse HEAD) + CHANGELOG=$(changelog-build -changelog-template .changelog/changelog.tmpl -note-template .changelog/note.tmpl -entries-dir .changelog/ -last-release ${CURRENT_VERSION} -this-release ${GIT_COMMIT_SHA}) + DATE=$(date '+%B %d, %Y') + mv CHANGELOG.md OLD-CHANGELOG.md + echo -e "## ${NEW_VERSION} (${DATE})\n${CHANGELOG}" > CHANGELOG.md + cat OLD-CHANGELOG.md >> CHANGELOG.md + rm -f OLD-CHANGELOG.md + git add CHANGELOG.md + git commit -m 'updated CHANGELOG.md' + echo "creating a new git tag" + CHANGELOG_URL="https://github.com/hashicorp/hcp-sdk-go/blob/${NEW_VERSION}/CHANGELOG.md" + git tag -a -m "${NEW_VERSION}" -m "See changelog: ${CHANGELOG_URL}" "${NEW_VERSION}" + echo "New Version: ${NEW_VERSION}" + echo "Pushing new tag to remote" + git config -l + git push --tags + git push + echo "Generating Release Notes" + sed -n -e "1{/# v /d;}" -e "2{/^$/d;}" -e "/# v$(git describe --abbrev=0 --exclude="$(git describe --abbrev=0 --match='v*.*.*' --tags)" --match='v*.*.*' --tags | tr -d v)/q;p" CHANGELOG.md > release-notes.txt + echo "Creating New Release: ${NEW_VERSION}" + gh release create $NEW_VERSION -F release-notes.txt + fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..4e66e023 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,44 @@ +name: Test + +permissions: + contents: write + +on: [pull_request] + +jobs: + test: + name: Run Unit Tests and Linter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup Go + uses: actions/setup-go@v3 + with: + cache: true + go-version-file: 'go.mod' + + - name: Cache Go Dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Install Dependencies + run: | + go mod download + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.49.0 + go mod tidy + + - name: Run Tests + run: make test-ci + + - name: Upload Coverage Artifact + uses: actions/upload-artifact@v3 + with: + name: Test Coverage + path: coverage.html diff --git a/Makefile b/Makefile index d788afb1..bc694e9b 100644 --- a/Makefile +++ b/Makefile @@ -26,18 +26,11 @@ go/tidy: go/lint: $(GO_LINT) run --config $(GO_LINT_CONFIG_PATH) $(GO_LINT_ARGS) +# Run the test and generate an html coverage file. .PHONY: test-ci test-ci: go/lint - @# TEST_RESULTS is assumed to be set by CircleCI - @mkdir -p $(TEST_RESULTS) - $(eval packages = $(shell go list ./... | circleci tests split --split-by=timings --timings-type=classname)) \ - $(GOTESTSUM) \ - --format short-verbose \ - --junitfile $(TEST_RESULTS)/gotestsum-report.xml \ - $(GOTESTSUM_ARGS) \ - -- \ - $(GO_TEST_ARGS) \ - $(packages) + go test -coverprofile=coverage.out ./... + go tool cover -html=coverage.out -o coverage.html # args passed to sdk/update commit=false diff --git a/README.md b/README.md index 56d65d85..c7d9f8a3 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,32 @@ import ( ``` See `cmd/hcp-sdk-go-client` for a complete example. + +## Contributing + +### Changelogs + +This repo requires that a chagnelog file be added in all pull requests. The name of the file must follow `[PR #].txt` and must reside in the `.changelog` directory. The contents must have the following formatting: + +~~~ +```release-note:TYPE +ENTRY +``` +~~~ + +Where `TYPE` is the type of release note entry this is. This is one of either: `breaking-change`, `security`, `feature`, `improvement`, `deprecation`, `bug`. + +`ENTRY` is the body of the changelog entry, and should describe the changes that were made. This is used as free-text input and will be returned to you as it is entered when generating the changelog. + +Sometimes PRs have multiple changelog entries associated with them. In this case, use multiple blocks. + +~~~ +```release-note:deprecation +Deprecated the `foo` interface, please use the `bar` interface instead. +``` + +```release-note:improvement +Added the `bar` interface. +``` +~~~ +