Compare commits

..

No commits in common. "0ee28fbc1f9b079740ff7c570246f9c56f98d710" and "66789d67ad8eea2ad5905fe971e727b25f005d65" have entirely different histories.

11 changed files with 22 additions and 658 deletions

View File

@ -2,62 +2,11 @@ kind: pipeline
type: docker
name: go-lib/gelf
trigger:
event:
- push
- tag
ref:
include:
- refs/heads/**
- refs/tags/v*
steps:
- name: test
image: golang:1.25.8
image: golang:1.20.1
commands:
- go get ./...
- go vet ./...
- mkdir -p .build
- go test -v -coverprofile .build/coverage.out ./...
- go tool cover -func .build/coverage.out | tee .build/coverage.txt
- bash scripts/check-coverage.sh .build/coverage.out 80
- go test ./...
- go install golang.org/x/vuln/cmd/govulncheck@latest
- govulncheck -json ./... > .build/vulncheck.json
- name: release-notes
image: golang:1.25.8
commands:
- bash scripts/generate-release-notes.sh
when:
event:
- tag
status:
- success
- name: package
image: golang:1.25.8
commands:
- tar czf .build/sources.tar.gz --exclude=.build --exclude=.git --exclude=.drone.yml .
when:
event:
- tag
status:
- success
- name: release
image: plugins/gitea-release
settings:
base_url: https://scm.yoorie.de
api_key:
from_secret: gitea_token
files:
- .build/coverage.txt
- .build/sources.tar.gz
- .build/release-notes.md
title: ${DRONE_TAG}
note_from_file: .build/release-notes.md
when:
event:
- tag
status:
- success
- govulncheck -v ./...

View File

@ -1,85 +1,50 @@
# AGENTS.md
## Purpose
This file defines the default working agreement for AI coding agents
and contributors in this repository.
This file defines the default working agreement for AI coding agents and contributors in this repository.
## Documentation Language
Project language is English. All documentation, issues, pull requests,
commit messages, and code comments should be written in English.
Project language is English. All documentation, issues, pull requests, commit messages, and code comments should be written in English.
All newly created documentation in this project must be written in English.
All project documentation files must be stored under `docs/`, except
`README.md` and `AGENTS.md`.
All project documentation files must be stored under `docs/`, except `README.md` and `AGENTS.md`.
## Working Principles
1. Keep changes minimal and focused on the requested task.
2. Preserve existing public APIs unless a breaking change is explicitly
requested.
2. Preserve existing public APIs unless a breaking change is explicitly requested.
3. Prefer clear, maintainable code over clever shortcuts.
4. Do not modify unrelated files.
5. Never add secrets, credentials, or tokens to the repository.
## Testing Expectations
1. Add or update tests for behavior changes.
2. Keep tests deterministic and fast.
3. Prefer table-driven tests where they improve readability.
4. Run relevant tests locally before finishing changes.
5. For Go projects, use `github.com/smartystreets/goconvey` as the
standard test library.
5. For Go projects, use `github.com/smartystreets/goconvey` as the standard test library.
## Build Artifacts and Reports
1. Builder logs and generated reports must be created under `.build/`.
2. The `.build/` directory must be excluded from version control via `.gitignore`.
## Git and Script Standards
1. Shell scripts (`*.sh`) must use LF line endings.
2. Shell scripts committed to the repository must be executable in Git
index (mode `100755`).
3. When adding a new shell script, set execute permissions before
commit: `git add --chmod=+x path/to/script.sh`.
2. Shell scripts committed to the repository must be executable in Git index (mode `100755`).
3. When adding a new shell script, set execute permissions before commit: `git add --chmod=+x path/to/script.sh`.
## Git Bash Execution Defaults
1. Repository maintenance scripts are executed with Git Bash shell on Windows.
2. Default repository root is `~/git`.
3. The repository root can be overridden via `GO_GIT_ROOT`.
4. The standards repository defaults to `$ROOT_PATH/project-standards`.
5. The standards repository path can be overridden via `GO_PROJECT_STANDARDS`.
## Definition of Done (DoD)
### DoD Purpose
The Definition of Done defines the minimum quality bar for every
completed change in this repository.
### Purpose
The Definition of Done defines the minimum quality bar for every completed change in this repository.
### Mandatory Criteria
1. Tests
- Every code change is covered by tests where applicable.
- New functionality includes new tests.
- Bug fixes include at least one regression test.
@ -87,47 +52,37 @@ completed change in this repository.
- Automated test coverage is at least 80%.
1. Functional documentation
- Implemented functionality is documented.
- Public API-relevant changes are reflected in README and/or docs.
1. Documentation standards
- Documentation is written in English.
- Documentation files are placed under `docs/`.
- Exceptions: `README.md` and `AGENTS.md` remain at repository root.
### Technical Completion Criteria
1. Build and test status
- The project builds successfully.
- Relevant test commands run successfully.
1. No unresolved critical issues
- No new blocking errors are introduced.
- Known non-blocking warnings are acceptable only if unrelated to the
change or documented.
- Known non-blocking warnings are acceptable only if unrelated to the change or documented.
1. SonarQube status
- No SonarQube errors are present.
1. Documentation structure
- Links to moved or newly added docs are valid.
- Documentation structure remains consistent with project rules.
### Review Checklist (Quick)
- [ ] Change is implemented and meets acceptance criteria.
- [ ] Tests were added/updated and pass.
- [ ] Go tests use `github.com/smartystreets/goconvey`.
- [ ] Automated test coverage is at least 80%.
- [ ] Functionality is documented.
- [ ] Documentation is in English.
- [ ] Documentation is located under `docs/` (except `README.md` and
`AGENTS.md`).
- [ ] Documentation is located under `docs/` (except `README.md` and `AGENTS.md`).
- [ ] No SonarQube errors are present.
- [ ] No critical regressions found.

View File

@ -1,52 +0,0 @@
# Changelog
<!-- markdownlint-disable MD024 -->
All notable changes to this project will be documented in this file.
The format follows conventional changelog categories.
## [Unreleased]
## [v0.0.3] - 2026-03-29
### Added
- Added comprehensive project documentation in README.
- Added release process documentation in docs/RELEASING.md.
- Added repository changelog file.
- Added test suite based on GoConvey.
- Added coverage gate script: scripts/check-coverage.sh.
- Added release notes generator script: scripts/generate-release-notes.sh.
- Added tag-based Drone release flow with artifact publishing.
### Changed
- Updated Drone pipeline to run on push and tag events.
- Extended CI quality gates with go vet, coverage reporting, and govulncheck.
- Improved markdown quality across project documentation.
- Improved Definition of Done formatting and lint compliance.
### Fixed
- Fixed shell script index modes to be executable (100755).
- Fixed markdownlint violations in README and documentation files.
## [v0.0.2] - 2021-03-03
### Changed
- Updated libraries.
- Added build configuration.
- Updated README.
## [v0.0.1] - 2021-03-03
### Added
- Initial project setup.
[Unreleased]: https://scm.yoorie.de/git/go-lib/gelf/compare/v0.0.3...master
[v0.0.3]: https://scm.yoorie.de/git/go-lib/gelf/compare/v0.0.2...v0.0.3
[v0.0.2]: https://scm.yoorie.de/git/go-lib/gelf/compare/v0.0.1...v0.0.2
[v0.0.1]: https://scm.yoorie.de/git/go-lib/gelf/releases/tag/v0.0.1

100
README.md
View File

@ -1,102 +1,12 @@
# Go GELF Logging Library
<div style="text-align:left"><img src="https://www.yoorie.de/img/favicon_32.png"/></div>
![yoorie favicon](https://www.yoorie.de/img/favicon_32.png)
# Go graylog logging library
[![Build Status][build-badge]][build-link]
[![Build Status](https://drone.yoorie.de/api/badges/go-lib/gelf/status.svg)](https://drone.yoorie.de/go-lib/gelf)
Minimal helper package to send application logs to Graylog via GELF
while still writing to the standard Go logger.
## Documentation
## Overview
This module wraps [gopkg.in/aphistic/golf.v0][golf] and exposes a
small API for common log levels.
Behavior summary:
- If GELF is configured with `SetDefaultConfig`, messages are sent to
Graylog over UDP.
- Messages are also written to the standard Go logger (`log` package).
- If GELF is not configured, logging still works locally via the
standard logger.
## Installation
```bash
go get scm.yoorie.de/go-lib/gelf
```
## Quick Start
```go
package main
import (
"scm.yoorie.de/go-lib/gelf"
)
func main() {
gelf.SetDefaultConfig("graylog.example.local", 12201,
map[string]interface{}{
"service": "billing-api",
"env": "prod",
},
)
gelf.Info("service started")
gelf.Infof("listening on %s", ":8080")
gelf.Alert("database latency is high")
}
```
## API
### Configuration
- `SetDefaultConfig(host string, port int, attrs map[string]interface{})`
Creates and configures the default GELF logger. Attributes in
`attrs` are attached as default fields to all GELF messages.
### Logging Functions
- `Debug(msg string)`
- `Debugf(format string, va ...interface{})`
- `Info(msg string)`
- `Infof(format string, va ...interface{})`
- `Alert(msg string)`
- `Alertf(format string, va ...interface{})`
- `Fatal(msg string)`
- `Fatalf(format string, va ...interface{})`
## Notes
- `Fatal` and `Fatalf` terminate the program by calling `log.Fatalf`.
- Graylog delivery uses UDP (`udp://host:port`).
- Calling `SetDefaultConfig` again replaces the previous client.
## Development
Run tests:
```bash
go test ./...
```
Module information is defined in [go.mod](go.mod).
## Additional Documentation
- [Definition of Done](docs/DEFINITION_OF_DONE.md)
- [Releasing](docs/RELEASING.md)
## License
See [LICENSE](LICENSE).
Is missed so far and will be created soon.
---
Copyright &copy; 2023 yoorie.de
[build-badge]: https://drone.yoorie.de/api/badges/go-lib/gelf/status.svg
[build-link]: https://drone.yoorie.de/go-lib/gelf
[golf]: https://gopkg.in/aphistic/golf.v0

View File

@ -2,13 +2,11 @@
## Purpose
This Definition of Done defines the minimum quality bar for every
completed change in this repository.
This Definition of Done defines the minimum quality bar for every completed change in this repository.
## Mandatory Criteria
1. Tests
- Every code change is covered by tests where applicable.
- New functionality includes new tests.
- Bug fixes include at least one regression test.
@ -16,12 +14,10 @@ completed change in this repository.
- Automated test coverage is at least 80%.
1. Functional documentation
- Implemented functionality is documented.
- Public API-relevant changes are reflected in README and/or docs.
1. Documentation standards
- Documentation is written in English.
- Documentation files are placed under `docs/`.
- Exceptions: `README.md` and `AGENTS.md` remain at repository root.
@ -29,22 +25,17 @@ completed change in this repository.
## Technical Completion Criteria
1. Build and test status
- The project builds successfully.
- Relevant test commands run successfully.
1. No unresolved critical issues
- No new blocking errors are introduced.
- Known non-blocking warnings are acceptable only if unrelated to the
change or documented.
- Known non-blocking warnings are acceptable only if unrelated to the change or documented.
1. SonarQube status
- No SonarQube errors are present.
1. Documentation links and structure
- Links to moved or newly added docs are valid.
- Documentation structure remains consistent with project rules.
@ -56,7 +47,6 @@ completed change in this repository.
- [ ] Automated test coverage is at least 80%.
- [ ] Functionality is documented.
- [ ] Documentation is in English.
- [ ] Documentation is located under `docs/` (except `README.md` and
`AGENTS.md`).
- [ ] Documentation is located under `docs/` (except `README.md` and `AGENTS.md`).
- [ ] No SonarQube errors are present.
- [ ] No critical regressions found.

View File

@ -1,115 +0,0 @@
# Releasing go-lib/gelf
This document describes the process for creating a release of the
`go-lib/gelf` library.
## Overview
Releases in this project are managed via Git tags. When you push a
tag matching the pattern `v*` (for example, `v0.2.0`), the Drone
pipeline automatically:
1. Runs quality checks (tests, coverage gate, vet, vulnerability scan)
2. Generates release notes from commits
3. Creates a source archive (`sources.tar.gz`)
4. Publishes a release to Gitea with attached artifacts
## Versioning
This library follows semantic versioning: `MAJOR.MINOR.PATCH`
(for example, `v1.2.3`).
- `v1.0.0`: breaking API changes
- `v1.1.0`: backward-compatible features
- `v1.0.1`: backward-compatible fixes
## Prerequisites
Before creating a release, ensure:
1. Working tree is clean (`git status`)
2. Tests pass locally (`go test ./...`)
3. Coverage is at least 80%
4. Dependencies are tidy (`go mod tidy`)
5. Documentation is up to date (README/docs)
## Create a Release
### 1. Prepare (optional)
Update docs, examples, or changelog if needed:
```bash
git add README.md docs/
git commit -m "docs: prepare release"
```
### 2. Create tag
```bash
git tag -a v0.2.0 -m "Release v0.2.0"
```
### 3. Push tag
```bash
git push origin v0.2.0
```
### 4. Verify pipeline and release
After pushing the tag, verify in Drone and Gitea:
- Pipeline succeeded for tag build
- Gitea release exists with artifacts:
- `.build/coverage.txt`
- `.build/sources.tar.gz`
- `.build/release-notes.md`
## Install Released Version
```bash
# latest
go get scm.yoorie.de/go-lib/gelf
# specific
go get scm.yoorie.de/go-lib/gelf@v0.2.0
```
## Troubleshooting
### Coverage below threshold
Run locally and inspect uncovered code:
```bash
go test -v -coverprofile .build/coverage.out ./...
go tool cover -func .build/coverage.out
```
### Release step fails
Common causes:
- Missing Drone secret `gitea_token`
- Tag does not match `v*`
- Earlier pipeline step failed
### Wrong tag pushed
```bash
git tag -d v0.2.0
git push origin :refs/tags/v0.2.0
```
Then create and push the corrected tag.
## Release Checklist
- [ ] Tests pass locally
- [ ] Coverage is at least 80%
- [ ] `go vet ./...` passes
- [ ] `govulncheck ./...` is clean or reviewed
- [ ] Tag `vX.Y.Z` created and pushed
- [ ] Drone pipeline succeeded
- [ ] Gitea release contains expected artifacts

View File

@ -1,158 +0,0 @@
package gelf
import (
"bytes"
"log"
"os"
"os/exec"
"testing"
. "github.com/smartystreets/goconvey/convey"
golf "gopkg.in/aphistic/golf.v0"
)
func TestSetDefaultConfig(t *testing.T) {
Convey("SetDefaultConfig with empty host keeps GELF client disabled", t, func() {
originalClient := c
defer func() { c = originalClient }()
c = nil
SetDefaultConfig("", 12201, map[string]interface{}{"service": "test"})
So(c, ShouldBeNil)
})
Convey("SetDefaultConfig with host initializes GELF client", t, func() {
originalClient := c
defer func() {
if c != nil {
c.Close()
}
c = originalClient
}()
c = nil
SetDefaultConfig("127.0.0.1", 12201, map[string]interface{}{"service": "test"})
So(c, ShouldNotBeNil)
})
}
func TestLoggingWithoutGelfClient(t *testing.T) {
Convey("Logging functions write to standard logger when GELF client is nil", t, func() {
originalClient := c
defer func() { c = originalClient }()
c = nil
buffer, restore := captureStandardLogger()
defer restore()
Debug("debug message")
Debugf("debugf %d", 42)
Info("info message")
Infof("infof %s", "ok")
Alert("alert message")
Alertf("alertf %d", 7)
output := buffer.String()
So(output, ShouldContainSubstring, "debug message")
So(output, ShouldContainSubstring, "debugf 42")
So(output, ShouldContainSubstring, "info message")
So(output, ShouldContainSubstring, "infof ok")
So(output, ShouldContainSubstring, "Alert: alert message")
So(output, ShouldContainSubstring, "Alert: alertf 7")
})
}
func TestLoggingWithGelfClient(t *testing.T) {
Convey("Logging functions execute without panic when GELF client is configured", t, func() {
originalClient := c
defer func() {
if c != nil {
c.Close()
}
c = originalClient
}()
client, err := golf.NewClient()
So(err, ShouldBeNil)
c = client
So(c.Dial("udp://127.0.0.1:12201"), ShouldBeNil)
logger, err := c.NewLogger()
So(err, ShouldBeNil)
golf.DefaultLogger(logger)
buffer, restore := captureStandardLogger()
defer restore()
So(func() { Debug("debug with gelf") }, ShouldNotPanic)
So(func() { Debugf("debugf %d", 1) }, ShouldNotPanic)
So(func() { Info("info with gelf") }, ShouldNotPanic)
So(func() { Infof("infof %d", 2) }, ShouldNotPanic)
So(func() { Alert("alert with gelf") }, ShouldNotPanic)
So(func() { Alertf("alertf %d", 3) }, ShouldNotPanic)
output := buffer.String()
So(output, ShouldContainSubstring, "debug with gelf")
So(output, ShouldContainSubstring, "Alert: alert with gelf")
})
}
func TestFatalExits(t *testing.T) {
Convey("Fatal exits with non-zero status and logs message", t, func() {
cmd := exec.Command(os.Args[0], "-test.run=TestFatalHelperProcess")
cmd.Env = append(os.Environ(), "GO_WANT_FATAL_HELPER=1", "FATAL_MODE=plain", "FATAL_WITH_GELF=1")
output, err := cmd.CombinedOutput()
So(err, ShouldNotBeNil)
So(string(output), ShouldContainSubstring, "Fatal: fatal message")
})
}
func TestFatalfExits(t *testing.T) {
Convey("Fatalf exits with non-zero status and logs formatted message", t, func() {
cmd := exec.Command(os.Args[0], "-test.run=TestFatalHelperProcess")
cmd.Env = append(os.Environ(), "GO_WANT_FATAL_HELPER=1", "FATAL_MODE=format", "FATAL_WITH_GELF=1")
output, err := cmd.CombinedOutput()
So(err, ShouldNotBeNil)
So(string(output), ShouldContainSubstring, "Fatal: formatted 9")
})
}
func TestFatalHelperProcess(t *testing.T) {
if os.Getenv("GO_WANT_FATAL_HELPER") != "1" {
return
}
log.SetFlags(0)
mode := os.Getenv("FATAL_MODE")
if os.Getenv("FATAL_WITH_GELF") == "1" {
SetDefaultConfig("127.0.0.1", 12201, map[string]interface{}{"service": "test"})
}
if mode == "format" {
Fatalf("formatted %d", 9)
}
Fatal("fatal message")
}
func captureStandardLogger() (*bytes.Buffer, func()) {
var buffer bytes.Buffer
originalWriter := log.Writer()
originalFlags := log.Flags()
originalPrefix := log.Prefix()
log.SetOutput(&buffer)
log.SetFlags(0)
log.SetPrefix("")
return &buffer, func() {
log.SetOutput(originalWriter)
log.SetFlags(originalFlags)
log.SetPrefix(originalPrefix)
}
}

4
go.mod
View File

@ -7,9 +7,5 @@ require gopkg.in/aphistic/golf.v0 v0.0.0-20180712155816-02c07f170c5a
require (
github.com/aphistic/sweet v0.3.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/onsi/gomega v1.27.2 // indirect
github.com/smarty/assertions v1.15.0 // indirect
github.com/smartystreets/goconvey v1.8.1 // indirect
)

9
go.sum
View File

@ -5,11 +5,7 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
@ -22,10 +18,6 @@ github.com/onsi/gomega v1.27.2 h1:SKU0CXeKE/WVgIV1T61kSa3+IRE8Ekrv9rdXDwwTqnY=
github.com/onsi/gomega v1.27.2/go.mod h1:5mR3phAHpkAVIDkHEUBY6HGVsU+cpcEscrGPB4oPlZI=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -38,7 +30,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
gopkg.in/aphistic/golf.v0 v0.0.0-20180712155816-02c07f170c5a h1:34vqlRjuZiE9c8eHsuZ9nn+GbcimFpvGUEmW+vyfhG8=

View File

@ -1,32 +0,0 @@
#!/bin/bash
# Check test coverage against minimum threshold.
set -euo pipefail
COVERAGE_FILE="${1:-.build/coverage.out}"
MIN_COVERAGE="${2:-80}"
if [ ! -f "$COVERAGE_FILE" ]; then
echo "Error: coverage file not found: $COVERAGE_FILE"
exit 1
fi
# Extract total coverage percentage from go tool cover output.
COVERAGE=$(go tool cover -func "$COVERAGE_FILE" | awk '/^total:/ { match($0, /[0-9.]+%/); print substr($0, RSTART, RLENGTH-1) }')
if [ -z "$COVERAGE" ]; then
echo "Error: failed to parse coverage from $COVERAGE_FILE"
exit 1
fi
echo "Total coverage: ${COVERAGE}%"
# Compare as integer part to keep shell arithmetic simple and portable.
COVERAGE_INT=${COVERAGE%.*}
if [ "$COVERAGE_INT" -lt "$MIN_COVERAGE" ]; then
echo "Coverage ${COVERAGE}% is below minimum ${MIN_COVERAGE}%"
exit 1
fi
echo "Coverage check passed"

View File

@ -1,70 +0,0 @@
#!/bin/bash
# Generate release notes from commits since the previous tag.
set -euo pipefail
CURRENT_TAG="${1:-${DRONE_TAG:-}}"
OUTPUT_FILE="${2:-.build/release-notes.md}"
if [ -z "$CURRENT_TAG" ]; then
echo "Error: current tag not provided"
exit 1
fi
PREVIOUS_TAG=$(git describe --tags --abbrev=0 "$CURRENT_TAG"^ 2>/dev/null || echo "")
mkdir -p "$(dirname "$OUTPUT_FILE")"
{
echo "# Release $CURRENT_TAG"
echo
if [ -n "$PREVIOUS_TAG" ]; then
echo "Changes since $PREVIOUS_TAG:"
echo
git log "$PREVIOUS_TAG..$CURRENT_TAG" --pretty=format:"%s" | while read -r commit; do
if [[ $commit =~ ^([a-z]+)(\(.+\))?:\ (.+)$ ]]; then
TYPE="${BASH_REMATCH[1]}"
SCOPE="${BASH_REMATCH[2]}"
MESSAGE="${BASH_REMATCH[3]}"
case "$TYPE" in
feat)
echo "- Feature${SCOPE}: $MESSAGE" ;;
fix)
echo "- Fix${SCOPE}: $MESSAGE" ;;
docs)
echo "- Docs${SCOPE}: $MESSAGE" ;;
ci)
echo "- CI${SCOPE}: $MESSAGE" ;;
test)
echo "- Test${SCOPE}: $MESSAGE" ;;
refactor)
echo "- Refactor${SCOPE}: $MESSAGE" ;;
perf)
echo "- Performance${SCOPE}: $MESSAGE" ;;
*)
echo "- $commit" ;;
esac
else
echo "- $commit"
fi
done
else
echo "Initial release"
echo
git log "$CURRENT_TAG" --pretty=format:"- %s" | head -20
fi
echo
echo "---"
if [ -n "$PREVIOUS_TAG" ]; then
echo "See all changes: https://scm.yoorie.de/git/go-lib/gelf/compare/$PREVIOUS_TAG...$CURRENT_TAG"
else
echo "See all changes: https://scm.yoorie.de/git/go-lib/gelf/releases/tag/$CURRENT_TAG"
fi
} > "$OUTPUT_FILE"
echo "Release notes generated: $OUTPUT_FILE"
cat "$OUTPUT_FILE"