Skip to content

Commit a455308

Browse files
committed
Improve CI workflow and code quality
- Fix broken gosec action by using direct installation from github.com/securego/gosec - Update Go version to 1.23 in security workflow for consistency - Add caching to security workflows for better performance - Add proper error handling to example code demonstrating best practices - Reduce gosec security findings from 41 to 26 by fixing unhandled errors - Add comprehensive badges to README including CI, security, coverage, license, and release status
1 parent c721ca7 commit a455308

5 files changed

Lines changed: 95 additions & 24 deletions

File tree

.github/workflows/security.yml

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ jobs:
2323
- name: Set up Go
2424
uses: actions/setup-go@v6
2525
with:
26-
go-version: '1.21'
26+
go-version: '1.23'
27+
28+
- name: Cache Go modules
29+
uses: actions/cache@v4
30+
with:
31+
path: ~/go/pkg/mod
32+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
33+
restore-keys: |
34+
${{ runner.os }}-go-
2735
2836
- name: Install govulncheck
2937
run: go install golang.org/x/vuln/cmd/govulncheck@latest
@@ -41,14 +49,24 @@ jobs:
4149
- name: Set up Go
4250
uses: actions/setup-go@v6
4351
with:
44-
go-version: '1.21'
52+
go-version: '1.23'
4553

46-
- name: Run Gosec Security Scanner
47-
uses: securecodewarrior/github-action-gosec@master
54+
- name: Cache Go modules
55+
uses: actions/cache@v4
4856
with:
49-
args: '-no-fail -fmt sarif -out results.sarif ./...'
57+
path: ~/go/pkg/mod
58+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
59+
restore-keys: |
60+
${{ runner.os }}-go-
61+
62+
- name: Install Gosec
63+
run: go install github.com/securego/gosec/v2/cmd/gosec@latest
64+
65+
- name: Run Gosec Security Scanner
66+
run: gosec -no-fail -fmt sarif -out results.sarif ./...
5067

5168
- name: Upload SARIF file
5269
uses: github/codeql-action/upload-sarif@v3
5370
with:
54-
sarif_file: results.sarif
71+
sarif_file: results.sarif
72+
if: always()

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ High-performance, thread-safe caching library for Go with automatic function wra
44

55
[![Go Reference](https://pkg.go.dev/badge/github.com/vnykmshr/obcache-go.svg)](https://pkg.go.dev/github.com/vnykmshr/obcache-go)
66
[![Go Report Card](https://goreportcard.com/badge/github.com/vnykmshr/obcache-go)](https://goreportcard.com/report/github.com/vnykmshr/obcache-go)
7+
[![CI](https://github.com/vnykmshr/obcache-go/workflows/CI/badge.svg)](https://github.com/vnykmshr/obcache-go/actions/workflows/ci.yml)
8+
[![Security](https://github.com/vnykmshr/obcache-go/workflows/Security/badge.svg)](https://github.com/vnykmshr/obcache-go/actions/workflows/security.yml)
9+
[![codecov](https://codecov.io/gh/vnykmshr/obcache-go/branch/main/graph/badge.svg)](https://codecov.io/gh/vnykmshr/obcache-go)
10+
[![License](https://img.shields.io/github/license/vnykmshr/obcache-go.svg)](https://github.com/vnykmshr/obcache-go/blob/main/LICENSE)
11+
[![Release](https://img.shields.io/github/release/vnykmshr/obcache-go.svg)](https://github.com/vnykmshr/obcache-go/releases)
12+
[![Go Version](https://img.shields.io/github/go-mod/go-version/vnykmshr/obcache-go)](https://github.com/vnykmshr/obcache-go/blob/main/go.mod)
713

814
## Installation
915

examples/basic/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ func main() {
1616

1717
// Example 1: Basic cache usage
1818
fmt.Println("=== Basic Cache Usage ===")
19-
cache.Set("key1", "value1", 5*time.Minute)
19+
if err := cache.Set("key1", "value1", 5*time.Minute); err != nil {
20+
fmt.Printf("Error setting cache: %v\n", err)
21+
return
22+
}
2023

2124
if value, found := cache.Get("key1"); found {
2225
fmt.Printf("Found: %v\n", value)

examples/compression/main.go

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ func noCompressionExample() {
107107
fmt.Printf("📊 Original data size: %d bytes\n", len(largeData))
108108

109109
// Store and retrieve
110-
cache.Set("large_data", largeData, 5*time.Minute)
110+
if err := cache.Set("large_data", largeData, 5*time.Minute); err != nil {
111+
log.Printf("Error setting cache: %v", err)
112+
return
113+
}
111114

112115
retrieved, found := cache.Get("large_data")
113116
if !found {
@@ -141,8 +144,14 @@ func gzipCompressionExample() {
141144
fmt.Printf("📊 JSON data size: %d bytes\n", len(largeData))
142145

143146
// Store and retrieve large JSON
144-
cache.Set("large_json", largeData, 5*time.Minute)
145-
cache.Set("large_user", user, 5*time.Minute)
147+
if err := cache.Set("large_json", largeData, 5*time.Minute); err != nil {
148+
log.Printf("Error setting JSON cache: %v", err)
149+
return
150+
}
151+
if err := cache.Set("large_user", user, 5*time.Minute); err != nil {
152+
log.Printf("Error setting user cache: %v", err)
153+
return
154+
}
146155

147156
// Retrieve and verify
148157
retrievedJSON, found := cache.Get("large_json")
@@ -192,7 +201,10 @@ func deflateCompressionExample() {
192201
repeatedText := strings.Repeat("This is a test string that repeats many times to demonstrate compression efficiency. ", 1000)
193202
fmt.Printf("📊 Repetitive text size: %d bytes\n", len(repeatedText))
194203

195-
cache.Set("repetitive_text", repeatedText, 5*time.Minute)
204+
if err := cache.Set("repetitive_text", repeatedText, 5*time.Minute); err != nil {
205+
log.Printf("Error setting repetitive text cache: %v", err)
206+
return
207+
}
196208

197209
retrieved, found := cache.Get("repetitive_text")
198210
if !found {
@@ -233,11 +245,17 @@ func compressionThresholdExample() {
233245

234246
// Test with small data (should not be compressed)
235247
smallData := strings.Repeat("small", 50) // ~250 bytes
236-
cache.Set("small_data", smallData, time.Minute)
248+
if err := cache.Set("small_data", smallData, time.Minute); err != nil {
249+
log.Printf("Error setting small data cache: %v", err)
250+
continue
251+
}
237252

238253
// Test with large data (should be compressed if above threshold)
239254
largeData := strings.Repeat("large data for compression testing ", 100) // ~3400 bytes
240-
cache.Set("large_data", largeData, time.Minute)
255+
if err := cache.Set("large_data", largeData, time.Minute); err != nil {
256+
log.Printf("Error setting large data cache: %v", err)
257+
continue
258+
}
241259

242260
// Retrieve both
243261
smallRetrieved, _ := cache.Get("small_data")
@@ -255,7 +273,9 @@ func compressionThresholdExample() {
255273
fmt.Printf(" ❌ Data integrity failed\n")
256274
}
257275

258-
cache.Close()
276+
if err := cache.Close(); err != nil {
277+
log.Printf("Error closing cache: %v", err)
278+
}
259279
}
260280
}
261281

@@ -270,14 +290,23 @@ func performanceComparisonExample() {
270290
fmt.Printf(" Testing %d operations without compression...\n", iterations)
271291
start := time.Now()
272292

273-
uncompressedCache, _ := obcache.New(obcache.NewDefaultConfig().WithMaxEntries(200))
293+
uncompressedCache, err := obcache.New(obcache.NewDefaultConfig().WithMaxEntries(200))
294+
if err != nil {
295+
log.Printf("Error creating uncompressed cache: %v", err)
296+
return
297+
}
274298
for i := 0; i < iterations; i++ {
275299
key := fmt.Sprintf("test_%d", i)
276-
uncompressedCache.Set(key, testData, time.Hour)
300+
if err := uncompressedCache.Set(key, testData, time.Hour); err != nil {
301+
log.Printf("Error setting uncompressed cache key %s: %v", key, err)
302+
continue
303+
}
277304
_, _ = uncompressedCache.Get(key)
278305
}
279306
uncompressedTime := time.Since(start)
280-
uncompressedCache.Close()
307+
if err := uncompressedCache.Close(); err != nil {
308+
log.Printf("Error closing uncompressed cache: %v", err)
309+
}
281310

282311
// Test with compression
283312
fmt.Printf(" Testing %d operations with gzip compression...\n", iterations)
@@ -290,15 +319,24 @@ func performanceComparisonExample() {
290319
Algorithm: compression.CompressorGzip,
291320
MinSize: 1000,
292321
})
293-
compressedCache, _ := obcache.New(config)
322+
compressedCache, err := obcache.New(config)
323+
if err != nil {
324+
log.Printf("Error creating compressed cache: %v", err)
325+
return
326+
}
294327

295328
for i := 0; i < iterations; i++ {
296329
key := fmt.Sprintf("test_%d", i)
297-
compressedCache.Set(key, testData, time.Hour)
330+
if err := compressedCache.Set(key, testData, time.Hour); err != nil {
331+
log.Printf("Error setting compressed cache key %s: %v", key, err)
332+
continue
333+
}
298334
_, _ = compressedCache.Get(key)
299335
}
300336
compressedTime := time.Since(start)
301-
compressedCache.Close()
337+
if err := compressedCache.Close(); err != nil {
338+
log.Printf("Error closing compressed cache: %v", err)
339+
}
302340

303341
// Results
304342
fmt.Printf("\n📊 Performance Results:\n")

examples/echo-web-server/main.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,16 @@ func (s *APIServer) invalidateProductCache(c echo.Context) error {
430430
// Invalidate from all relevant caches
431431
productKey := fmt.Sprintf("product:%d", id)
432432
analyticsKey := fmt.Sprintf("analytics:%d", id)
433-
434-
s.cacheManager.l1Cache.Delete(productKey)
435-
s.cacheManager.l2Cache.Delete(productKey)
436-
s.cacheManager.analyticsCache.Delete(analyticsKey)
433+
434+
if err := s.cacheManager.l1Cache.Delete(productKey); err != nil {
435+
log.Printf("Error deleting from L1 cache: %v", err)
436+
}
437+
if err := s.cacheManager.l2Cache.Delete(productKey); err != nil {
438+
log.Printf("Error deleting from L2 cache: %v", err)
439+
}
440+
if err := s.cacheManager.analyticsCache.Delete(analyticsKey); err != nil {
441+
log.Printf("Error deleting from analytics cache: %v", err)
442+
}
437443

438444
return c.JSON(http.StatusOK, map[string]string{
439445
"message": fmt.Sprintf("Cache invalidated for product %d", id),

0 commit comments

Comments
 (0)