Skip to content
Open

test #2354

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cf8a014
Add personal signature to README
Feb 17, 2026
f6f0cec
testing
Feb 17, 2026
179437d
Add CI workflow with forced failure
Feb 17, 2026
b58c104
Fix CI workflow to run go version instead of force failure
Feb 17, 2026
46fe88c
Add unit test for GETAPIKey function
Feb 18, 2026
f28e8f6
Temporarily break test to verify CI catches failures
Feb 18, 2026
ebd750e
Merge pull request #1 from diegocavi84/addtests
diegocavi84 Feb 18, 2026
5c9e29c
Fix test: CI now propeply validates GetAPIKey
Feb 18, 2026
46af95d
Fix typo: go test :/... (three dots, not two)
Feb 18, 2026
e142b9b
Merge pull request #3 from diegocavi84/addtests
diegocavi84 Feb 18, 2026
d6e02f9
Add -cover flag to show test coverage in CI
Feb 18, 2026
da4412c
Add CI status badge to README
Feb 18, 2026
04b0f4d
Merge pull request #4 from diegocavi84/addtests
diegocavi84 Feb 18, 2026
098fa2b
Demostrate test -z with go fmt for CI formatting check
Feb 18, 2026
00ab49b
Add style job to CI workflow for formatting checks
Feb 19, 2026
047b9bd
Ensure code is properly formatted
Feb 19, 2026
a88ff2a
Fix style job: quote the test -z command properly
Feb 19, 2026
9d943be
Add staticcheck to CI and demostrate it catches unused code
Feb 19, 2026
b0b66aa
Remove unused function: staticcheck now passes
Feb 19, 2026
f089cf3
Fix staticcheck step: separate install and run commands
Feb 19, 2026
393966e
Fix remaining gosec warnings with #nosec directives for false positives
Feb 19, 2026
1c3bec3
Fix log.Print typo: use log.Printf for fomatted output
Feb 19, 2026
5ea9db0
Merge pull request #5 from diegocavi84/addtests
diegocavi84 Feb 25, 2026
2385443
Merge pull request #2 from diegocavi84/addtest
diegocavi84 Feb 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: ci

on:
pull_request:
branches: [main]

jobs:
tests:
name: Tests
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.1"

- name: Run unit tests
run: go test -cover ./...

style:
name: Style
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.1"

- name: Check code formatting
run: test -z $(go fmt ./...)

- name: Run static analysis
run: |
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
![CI Status](https://github.com/diegocavi84/learn-cicd-starter/actions/workflows/ci.yml/badge.svg)

# learn-cicd-starter (Notely)

This repo contains the starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev).
Expand All @@ -17,6 +19,10 @@ Run the server:
```bash
go build -o notely && ./notely
```
Diego's version of Boot.dev's Notely app.


Diego's version of Boot.dev's Notely app.

*This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`.

Expand Down
62 changes: 62 additions & 0 deletions gosec-errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
Results:


[/Users/diegocastillo/learn-cicd-starter/json.go:33] - G705 (CWE): XSS via taint analysis (Confidence: HIGH, Severity: MEDIUM)
32: w.WriteHeader(code)
> 33: w.Write(dat)
34: }

Autofix:

[/Users/diegocastillo/learn-cicd-starter/main.go:90-93] - G112 (CWE-400): Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server (Confidence: LOW, Severity: MEDIUM)
89: router.Mount("/v1", v1Router)
> 90: srv := &http.Server{
> 91: Addr: ":" + port,
> 92: Handler: router,
> 93: }
94:

Autofix:

[/Users/diegocastillo/learn-cicd-starter/models.go:14] - G117 (CWE-499): Exported struct field "ApiKey" (JSON key "api_key") matches secret pattern (Confidence: MEDIUM, Severity: MEDIUM)
13: Name string `json:"name"`
> 14: ApiKey string `json:"api_key"`
15: }

Autofix:

[/Users/diegocastillo/learn-cicd-starter/internal/database/users.sql.go:28] - G117 (CWE-499): Exported struct field "ApiKey" (JSON key "ApiKey") matches secret pattern (Confidence: MEDIUM, Severity: MEDIUM)
27: Name string
> 28: ApiKey string
29: }

Autofix:

[/Users/diegocastillo/learn-cicd-starter/internal/database/models.go:22] - G117 (CWE-499): Exported struct field "ApiKey" (JSON key "ApiKey") matches secret pattern (Confidence: MEDIUM, Severity: MEDIUM)
21: Name string
> 22: ApiKey string
23: }

Autofix:

[/Users/diegocastillo/learn-cicd-starter/main.go:95] - G706 (CWE): Log injection via taint analysis (Confidence: HIGH, Severity: LOW)
94:
> 95: log.Printf("Serving on port: %s\n", port)
96: log.Fatal(srv.ListenAndServe())

Autofix:

[/Users/diegocastillo/learn-cicd-starter/json.go:33] - G104 (CWE-703): Errors unhandled (Confidence: HIGH, Severity: LOW)
32: w.WriteHeader(code)
> 33: w.Write(dat)
34: }

Autofix:

Summary:
Gosec : dev
Files : 12
Lines : 607
Nosec : 0
Issues : 7

50 changes: 50 additions & 0 deletions internal/auth/auth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package auth

import (
"net/http"
"testing"
)

// Test 1: Cuando el header Authorization está vacío
func TestGetAPIKey_NoHeader(t *testing.T) {
headers := http.Header{} // Header vacío

key, err := GetAPIKey(headers)

if err != ErrNoAuthHeaderIncluded {
t.Errorf("Expected ErrNoAuthHeaderIncluded, got: %v", err)
}
if key != "" {
t.Errorf("Expected empty key, got: %s", key)
}
}

// Test 2: Cuando el header está malformado
func TestGetAPIKey_MalformedHeader(t *testing.T) {
headers := http.Header{}
headers.Add("Authorization", "Bearer token123") // Prefijo incorrecto

key, err := GetAPIKey(headers)

if err == nil {
t.Error("Expected error for malformed header, got nil")
}
if key != "" {
t.Errorf("Expected empty key, got: %s", key)
}
}

// Test 3: Cuando el header es correcto
func TestGetAPIKey_ValidHeader(t *testing.T) {
headers := http.Header{}
headers.Add("Authorization", "ApiKey mi-clave-secreta-123")

key, err := GetAPIKey(headers)

if err != nil {
t.Errorf("Expected no error, got: %v", err)
}
if key != "mi-clave-secreta-123" {
t.Errorf("Expected 'mi-clave-secreta-123', got: %s", key)
}
}
4 changes: 1 addition & 3 deletions internal/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/database/users.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion json.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,8 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
return
}
w.WriteHeader(code)
w.Write(dat)
// #nosec G705 - Content-Type is set to application/json, preventing XSS
if _, err := w.Write(dat); err != nil {
log.Printf("Error writing response: %v", err)
}
}
12 changes: 7 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"net/http"
"os"
"time"

"github.com/go-chi/chi"
"github.com/go-chi/cors"
Expand Down Expand Up @@ -36,7 +37,6 @@ func main() {
}

apiCfg := apiConfig{}

// https://github.com/libsql/libsql-client-go/#open-a-connection-to-sqld
// libsql://[your-database].turso.io?authToken=[your-auth-token]
dbURL := os.Getenv("DATABASE_URL")
Expand Down Expand Up @@ -89,10 +89,12 @@ func main() {

router.Mount("/v1", v1Router)
srv := &http.Server{
Addr: ":" + port,
Handler: router,
Addr: ":" + port,
Handler: router,
ReadHeaderTimeout: 10 * time.Second,
}

log.Printf("Serving on port: %s\n", port)
// #nosec G706 - PORT is a controlled config value, not user input
log.Printf("Serving on port: %q\n", port)
log.Fatal(srv.ListenAndServe())

}
2 changes: 1 addition & 1 deletion models.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type User struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name"`
ApiKey string `json:"api_key"`
ApiKey string `json:"api_key"` // #nosec G117
}

func databaseUserToUser(user database.User) (User, error) {
Expand Down