diff --git a/.gitea/workflows/pr-validation.yml b/.gitea/workflows/pr-validation.yml index ba9ff49..5141ed3 100644 --- a/.gitea/workflows/pr-validation.yml +++ b/.gitea/workflows/pr-validation.yml @@ -34,6 +34,12 @@ jobs: cache: true cache-dependency-path: go.sum + - name: Install security tools + run: | + set -euo pipefail + go install github.com/securego/gosec/v2/cmd/gosec@v2.22.3 + go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 + - name: Install AWS CLI v2 uses: ankurk91/install-aws-cli-action@v1 @@ -60,6 +66,12 @@ jobs: printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT" + - name: Run security analysis + run: | + set -euo pipefail + "$(go env GOPATH)/bin/gosec" ./... + "$(go env GOPATH)/bin/govulncheck" ./... + - name: Generate coverage badge env: COVERAGE_TOTAL: ${{ steps.coverage.outputs.total }} diff --git a/.gitea/workflows/prepare-release.yml b/.gitea/workflows/prepare-release.yml index 9456177..21ff4ac 100644 --- a/.gitea/workflows/prepare-release.yml +++ b/.gitea/workflows/prepare-release.yml @@ -1,83 +1,32 @@ -name: Prepare Release +name: Release on: - workflow_dispatch: - inputs: - version: - description: Semantic version to release, with or without leading v. - required: true + push: + branches: [main] + +permissions: + contents: write jobs: prepare: runs-on: ubuntu-latest - container: docker.io/catthehacker/ubuntu:act-latest - defaults: - run: - shell: bash - env: - RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Setup Go - uses: actions/setup-go@v5 + - name: Vociferate prepare + uses: aether/vociferate/prepare@v1.0.0 + + publish: + needs: prepare + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 with: - go-version: '1.26.1' - check-latest: true - cache: true - cache-dependency-path: go.sum + fetch-depth: 0 - - name: Prepare release files - env: - RELEASE_VERSION: ${{ inputs.version }} - run: | - set -euo pipefail - ./script/prepare-release.sh "$RELEASE_VERSION" - - - name: Run tests - run: | - set -euo pipefail - go test ./... - - - name: Configure git author - run: | - set -euo pipefail - git config user.name "gitea-actions[bot]" - git config user.email "gitea-actions[bot]@users.noreply.local" - - - name: Commit release changes and push tag - env: - RELEASE_VERSION: ${{ inputs.version }} - run: | - set -euo pipefail - - normalized_version="${RELEASE_VERSION#v}" - tag="v${normalized_version}" - - if git rev-parse "$tag" >/dev/null 2>&1; then - echo "Tag ${tag} already exists" >&2 - exit 1 - fi - - case "$GITHUB_SERVER_URL" in - https://*) - authed_remote="https://oauth2:${RELEASE_TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git" - ;; - http://*) - authed_remote="http://oauth2:${RELEASE_TOKEN}@${GITHUB_SERVER_URL#http://}/${GITHUB_REPOSITORY}.git" - ;; - *) - echo "Unsupported GITHUB_SERVER_URL: ${GITHUB_SERVER_URL}" >&2 - exit 1 - ;; - esac - - git remote set-url origin "$authed_remote" - git add changelog.md internal/homesick/version/version.go - git commit -m "release: prepare ${tag}" - git tag "$tag" - git push origin HEAD - git push origin "$tag" \ No newline at end of file + - name: Vociferate publish + uses: aether/vociferate/publish@v1.0.0 \ No newline at end of file diff --git a/.gitea/workflows/push-validation.yml b/.gitea/workflows/push-validation.yml index 42ef38a..4cb5a9c 100644 --- a/.gitea/workflows/push-validation.yml +++ b/.gitea/workflows/push-validation.yml @@ -34,6 +34,12 @@ jobs: cache: true cache-dependency-path: go.sum + - name: Install security tools + run: | + set -euo pipefail + go install github.com/securego/gosec/v2/cmd/gosec@v2.22.3 + go install golang.org/x/vuln/cmd/govulncheck@v1.1.4 + - name: Install AWS CLI v2 uses: ankurk91/install-aws-cli-action@v1 @@ -52,6 +58,12 @@ jobs: printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT" + - name: Run security analysis + run: | + set -euo pipefail + "$(go env GOPATH)/bin/gosec" ./... + "$(go env GOPATH)/bin/govulncheck" ./... + - name: Generate coverage badge env: COVERAGE_TOTAL: ${{ steps.coverage.outputs.total }} @@ -121,26 +133,3 @@ jobs: - name: Run behavior suite on main pushes if: ${{ github.ref == 'refs/heads/main' }} run: ./script/run-behavior-suite-docker.sh - - - name: Recommend next release tag on main pushes - if: ${{ github.ref == 'refs/heads/main' }} - run: | - set -euo pipefail - - if recommended_tag="$(go run git.hrafn.xyz/aether/vociferate/cmd/releaseprep@latest --recommend --root . --version-file internal/homesick/version/version.go --version-pattern 'const String = "([^"]+)"' --changelog changelog.md 2>release-recommendation.err)"; then - { - echo - echo '## Release Recommendation' - echo - echo "- Recommended next tag: \\`${recommended_tag}\\`" - } >> "$GITHUB_STEP_SUMMARY" - else - recommendation_error="$(tr '\n' ' ' < release-recommendation.err | sed 's/[[:space:]]\+/ /g' | sed 's/^ //; s/ $//')" - echo "::warning::${recommendation_error}" - { - echo - echo '## Release Recommendation' - echo - echo "- No recommended tag emitted: ${recommendation_error}" - } >> "$GITHUB_STEP_SUMMARY" - fi diff --git a/justfile b/justfile index 544d7df..e660f37 100644 --- a/justfile +++ b/justfile @@ -14,6 +14,10 @@ go-build-linux: go-test: go test ./... +go-security: + gosec ./... + govulncheck ./... + behavior: ./script/run-behavior-suite-docker.sh @@ -21,4 +25,4 @@ behavior-verbose: ./script/run-behavior-suite-docker.sh --verbose prepare-release version: - ./script/prepare-release.sh "{{version}}" + @echo "Release preparation is handled by vociferate workflows." diff --git a/script/prepare-release.sh b/script/prepare-release.sh deleted file mode 100755 index ea5f04f..0000000 --- a/script/prepare-release.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -if [[ $# -ne 1 ]]; then - echo "usage: $0 " >&2 - exit 2 -fi - -repo_root="$(cd "$(dirname "$0")/.." && pwd)" -release_date="$(date -u +%F)" - -go run git.hrafn.xyz/aether/vociferate/cmd/releaseprep@latest \ - --root "$repo_root" \ - --version "$1" \ - --date "$release_date" \ - --version-file internal/homesick/version/version.go \ - --version-pattern 'const String = "([^"]+)"' \ - --changelog changelog.md \ No newline at end of file diff --git a/script/prepare_release_script_test.go b/script/prepare_release_script_test.go deleted file mode 100644 index 923c4c0..0000000 --- a/script/prepare_release_script_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package script_test - -import ( - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestPrepareReleaseScript_UsesVociferateReleaseprep(t *testing.T) { - wd, err := os.Getwd() - require.NoError(t, err) - - repoRoot := filepath.Dir(wd) - tempBin := t.TempDir() - argsLog := filepath.Join(tempBin, "go-args.log") - fakeGoPath := filepath.Join(tempBin, "go") - - fakeGo := `#!/usr/bin/env bash -set -euo pipefail -printf '%s\n' "$*" > "$GO_ARGS_LOG" -` - require.NoError(t, os.WriteFile(fakeGoPath, []byte(fakeGo), 0o755)) - - cmd := exec.Command("bash", filepath.Join(repoRoot, "script", "prepare-release.sh"), "v1.2.3") - cmd.Dir = repoRoot - cmd.Env = append(os.Environ(), - "PATH="+tempBin+":"+os.Getenv("PATH"), - "GO_ARGS_LOG="+argsLog, - ) - - output, err := cmd.CombinedOutput() - require.NoError(t, err, string(output)) - - invocationBytes, err := os.ReadFile(argsLog) - require.NoError(t, err) - invocation := strings.TrimSpace(string(invocationBytes)) - - require.Contains(t, invocation, "run git.hrafn.xyz/aether/vociferate/cmd/releaseprep@latest") - require.Contains(t, invocation, "--root "+repoRoot) - require.Contains(t, invocation, "--version v1.2.3") - require.Contains(t, invocation, "--version-file internal/homesick/version/version.go") - require.Contains(t, invocation, "--version-pattern const String = \"([^\"]+)\"") - require.Contains(t, invocation, "--changelog changelog.md") - require.Regexp(t, regexp.MustCompile(`--date [0-9]{4}-[0-9]{2}-[0-9]{2}`), invocation) -} \ No newline at end of file