diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000000..0b5b2daf48
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,51 @@
+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.22
+
+ - name: Run 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.22
+
+ # ✅ STRICT STYLE CHECK (assignment requires this)
+ - name: Check Go formatting (strict)
+ run: test -z "$(go fmt ./...)"
+
+ # 🟡 OPTIONAL: SOFT CHECK (uncomment if you don't want to fail CI)
+ # - name: Check Go formatting (soft, always passes)
+ # run: |
+ # files=$(go fmt ./...)
+ # if [ -n "$files" ]; then
+ # echo "These files are not formatted correctly:"
+ # echo "$files"
+ # else
+ # echo "All files are properly formatted."
+ # fi
+
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000000..26d33521af
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000000..105ce2da2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/learn-cicd-starter.iml b/.idea/learn-cicd-starter.iml
new file mode 100644
index 0000000000..d0876a78d0
--- /dev/null
+++ b/.idea/learn-cicd-starter.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000..dfe3a26f93
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000..d0adac68cd
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000..35eb1ddfbb
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index c2bec0368b..d6c0437952 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+
+
# 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).
@@ -21,3 +23,4 @@ go build -o notely && ./notely
*This starts the server in non-database mode.* It will serve a simple webpage at `http://localhost:8080`.
You do *not* need to set up a database or any interactivity on the webpage yet. Instructions for that will come later in the course!
+Niveditha's version of Boot.dev's Notely app.
diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go
new file mode 100644
index 0000000000..e5ae617ff6
--- /dev/null
+++ b/internal/auth/auth_test.go
@@ -0,0 +1,29 @@
+package auth
+
+import (
+ "net/http"
+ "testing"
+)
+
+func TestGetAPIKey_Success(t *testing.T) {
+ headers := http.Header{}
+ headers.Set("Authorization", "ApiKey 12345")
+
+ key, err := GetAPIKey(headers)
+ if err != nil {
+ t.Fatalf("Expected no error, got %v", err)
+ }
+
+ if key != "12345" {
+ t.Errorf("Expected key '12345', got '%s'", key)
+ }
+}
+
+func TestGetAPIKey_MissingHeader(t *testing.T) {
+ headers := http.Header{}
+
+ _, err := GetAPIKey(headers)
+ if err == nil {
+ t.Fatal("Expected an error, got nil")
+ }
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000000..6c19ba9aa3
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6 @@
+{
+ "name": "learn-cicd-starter",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {}
+}
diff --git a/vendor/github.com/go-chi/chi/chi.go b/vendor/github.com/go-chi/chi/chi.go
index b7063dc297..db1780b1c6 100644
--- a/vendor/github.com/go-chi/chi/chi.go
+++ b/vendor/github.com/go-chi/chi/chi.go
@@ -1,29 +1,29 @@
-//
// Package chi is a small, idiomatic and composable router for building HTTP services.
//
// chi requires Go 1.10 or newer.
//
// Example:
-// package main
//
-// import (
-// "net/http"
+// package main
+//
+// import (
+// "net/http"
//
-// "github.com/go-chi/chi"
-// "github.com/go-chi/chi/middleware"
-// )
+// "github.com/go-chi/chi"
+// "github.com/go-chi/chi/middleware"
+// )
//
-// func main() {
-// r := chi.NewRouter()
-// r.Use(middleware.Logger)
-// r.Use(middleware.Recoverer)
+// func main() {
+// r := chi.NewRouter()
+// r.Use(middleware.Logger)
+// r.Use(middleware.Recoverer)
//
-// r.Get("/", func(w http.ResponseWriter, r *http.Request) {
-// w.Write([]byte("root."))
-// })
+// r.Get("/", func(w http.ResponseWriter, r *http.Request) {
+// w.Write([]byte("root."))
+// })
//
-// http.ListenAndServe(":3333", r)
-// }
+// http.ListenAndServe(":3333", r)
+// }
//
// See github.com/go-chi/chi/_examples/ for more in-depth examples.
//
@@ -47,12 +47,12 @@
// placeholder which will match / characters.
//
// Examples:
-// "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/"
-// "/user/{name}/info" matches "/user/jsmith/info"
-// "/page/*" matches "/page/intro/latest"
-// "/page/*/index" also matches "/page/intro/latest"
-// "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01"
//
+// "/user/{name}" matches "/user/jsmith" but not "/user/jsmith/info" or "/user/jsmith/"
+// "/user/{name}/info" matches "/user/jsmith/info"
+// "/page/*" matches "/page/intro/latest"
+// "/page/*/index" also matches "/page/intro/latest"
+// "/date/{yyyy:\\d\\d\\d\\d}/{mm:\\d\\d}/{dd:\\d\\d}" matches "/date/2017/04/01"
package chi
import "net/http"
diff --git a/vendor/github.com/go-chi/chi/context.go b/vendor/github.com/go-chi/chi/context.go
index 8c97f214a9..bd30d52b4f 100644
--- a/vendor/github.com/go-chi/chi/context.go
+++ b/vendor/github.com/go-chi/chi/context.go
@@ -112,13 +112,13 @@ func (x *Context) URLParam(key string) string {
//
// For example,
//
-// func Instrument(next http.Handler) http.Handler {
-// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-// next.ServeHTTP(w, r)
-// routePattern := chi.RouteContext(r.Context()).RoutePattern()
-// measure(w, r, routePattern)
-// })
-// }
+// func Instrument(next http.Handler) http.Handler {
+// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+// next.ServeHTTP(w, r)
+// routePattern := chi.RouteContext(r.Context()).RoutePattern()
+// measure(w, r, routePattern)
+// })
+// }
func (x *Context) RoutePattern() string {
routePattern := strings.Join(x.RoutePatterns, "")
return replaceWildcards(routePattern)
diff --git a/vendor/github.com/go-chi/cors/cors.go b/vendor/github.com/go-chi/cors/cors.go
index 8df81636e3..75196ab91c 100644
--- a/vendor/github.com/go-chi/cors/cors.go
+++ b/vendor/github.com/go-chi/cors/cors.go
@@ -3,15 +3,15 @@
//
// You can configure it by passing an option struct to cors.New:
//
-// c := cors.New(cors.Options{
-// AllowedOrigins: []string{"foo.com"},
-// AllowedMethods: []string{"GET", "POST", "DELETE"},
-// AllowCredentials: true,
-// })
+// c := cors.New(cors.Options{
+// AllowedOrigins: []string{"foo.com"},
+// AllowedMethods: []string{"GET", "POST", "DELETE"},
+// AllowCredentials: true,
+// })
//
// Then insert the handler in the chain:
//
-// handler = c.Handler(handler)
+// handler = c.Handler(handler)
//
// See Options documentation for more options.
//
diff --git a/vendor/github.com/google/uuid/dce.go b/vendor/github.com/google/uuid/dce.go
index fa820b9d30..9302a1c1bb 100644
--- a/vendor/github.com/google/uuid/dce.go
+++ b/vendor/github.com/google/uuid/dce.go
@@ -42,7 +42,7 @@ func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
-// NewDCESecurity(Person, uint32(os.Getuid()))
+// NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
@@ -50,7 +50,7 @@ func NewDCEPerson() (UUID, error) {
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
-// NewDCESecurity(Group, uint32(os.Getgid()))
+// NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go
index b404f4bec2..24ccde6464 100644
--- a/vendor/github.com/google/uuid/hash.go
+++ b/vendor/github.com/google/uuid/hash.go
@@ -39,7 +39,7 @@ func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data. It is the same as calling:
//
-// NewHash(md5.New(), space, data, 3)
+// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
@@ -47,7 +47,7 @@ func NewMD5(space UUID, data []byte) UUID {
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data. It is the same as calling:
//
-// NewHash(sha1.New(), space, data, 5)
+// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}
diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go
index 24b78edc90..96090351a9 100644
--- a/vendor/github.com/google/uuid/node_js.go
+++ b/vendor/github.com/google/uuid/node_js.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build js
// +build js
package uuid
diff --git a/vendor/github.com/google/uuid/node_net.go b/vendor/github.com/google/uuid/node_net.go
index 0cbbcddbd6..e91358f7d9 100644
--- a/vendor/github.com/google/uuid/node_net.go
+++ b/vendor/github.com/google/uuid/node_net.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !js
// +build !js
package uuid
diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go
index d7fcbf2865..06ecf9de2a 100644
--- a/vendor/github.com/google/uuid/null.go
+++ b/vendor/github.com/google/uuid/null.go
@@ -17,15 +17,14 @@ var jsonNull = []byte("null")
// NullUUID implements the SQL driver.Scanner interface so
// it can be used as a scan destination:
//
-// var u uuid.NullUUID
-// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
-// ...
-// if u.Valid {
-// // use u.UUID
-// } else {
-// // NULL value
-// }
-//
+// var u uuid.NullUUID
+// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
+// ...
+// if u.Valid {
+// // use u.UUID
+// } else {
+// // NULL value
+// }
type NullUUID struct {
UUID UUID
Valid bool // Valid is true if UUID is not NULL
diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go
index 7697802e4d..62ac273815 100644
--- a/vendor/github.com/google/uuid/version4.go
+++ b/vendor/github.com/google/uuid/version4.go
@@ -9,7 +9,7 @@ import "io"
// New creates a new random UUID or panics. New is equivalent to
// the expression
//
-// uuid.Must(uuid.NewRandom())
+// uuid.Must(uuid.NewRandom())
func New() UUID {
return Must(NewRandom())
}
@@ -17,7 +17,7 @@ func New() UUID {
// NewString creates a new random UUID and returns it as a string or panics.
// NewString is equivalent to the expression
//
-// uuid.New().String()
+// uuid.New().String()
func NewString() string {
return Must(NewRandom()).String()
}
@@ -31,11 +31,11 @@ func NewString() string {
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
-// Randomly generated UUIDs have 122 random bits. One's annual risk of being
-// hit by a meteorite is estimated to be one chance in 17 billion, that
-// means the probability is about 0.00000000006 (6 × 10−11),
-// equivalent to the odds of creating a few tens of trillions of UUIDs in a
-// year and having one duplicate.
+// Randomly generated UUIDs have 122 random bits. One's annual risk of being
+// hit by a meteorite is estimated to be one chance in 17 billion, that
+// means the probability is about 0.00000000006 (6 × 10−11),
+// equivalent to the odds of creating a few tens of trillions of UUIDs in a
+// year and having one duplicate.
func NewRandom() (UUID, error) {
if !poolEnabled {
return NewRandomFromReader(rander)
diff --git a/vendor/nhooyr.io/websocket/accept.go b/vendor/nhooyr.io/websocket/accept.go
index 18536bdb2c..b54471312e 100644
--- a/vendor/nhooyr.io/websocket/accept.go
+++ b/vendor/nhooyr.io/websocket/accept.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/close_notjs.go b/vendor/nhooyr.io/websocket/close_notjs.go
index 4251311d2e..8cafaa9dcf 100644
--- a/vendor/nhooyr.io/websocket/close_notjs.go
+++ b/vendor/nhooyr.io/websocket/close_notjs.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/compress_notjs.go b/vendor/nhooyr.io/websocket/compress_notjs.go
index 809a272c3d..e094513b35 100644
--- a/vendor/nhooyr.io/websocket/compress_notjs.go
+++ b/vendor/nhooyr.io/websocket/compress_notjs.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/conn_notjs.go b/vendor/nhooyr.io/websocket/conn_notjs.go
index 0c85ab7711..3c1361c5b2 100644
--- a/vendor/nhooyr.io/websocket/conn_notjs.go
+++ b/vendor/nhooyr.io/websocket/conn_notjs.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/dial.go b/vendor/nhooyr.io/websocket/dial.go
index 7a7787ff71..7b91713e9c 100644
--- a/vendor/nhooyr.io/websocket/dial.go
+++ b/vendor/nhooyr.io/websocket/dial.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/doc.go b/vendor/nhooyr.io/websocket/doc.go
index efa920e3b6..a2b873c722 100644
--- a/vendor/nhooyr.io/websocket/doc.go
+++ b/vendor/nhooyr.io/websocket/doc.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
// Package websocket implements the RFC 6455 WebSocket protocol.
@@ -16,7 +17,7 @@
//
// More documentation at https://nhooyr.io/websocket.
//
-// Wasm
+// # Wasm
//
// The client side supports compiling to Wasm.
// It wraps the WebSocket browser API.
@@ -25,8 +26,8 @@
//
// Some important caveats to be aware of:
//
-// - Accept always errors out
-// - Conn.Ping is no-op
-// - HTTPClient, HTTPHeader and CompressionMode in DialOptions are no-op
-// - *http.Response from Dial is &http.Response{} with a 101 status code on success
+// - Accept always errors out
+// - Conn.Ping is no-op
+// - HTTPClient, HTTPHeader and CompressionMode in DialOptions are no-op
+// - *http.Response from Dial is &http.Response{} with a 101 status code on success
package websocket // import "nhooyr.io/websocket"
diff --git a/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go b/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go
index 26ffb45625..88e8f43f69 100644
--- a/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go
+++ b/vendor/nhooyr.io/websocket/internal/wsjs/wsjs_js.go
@@ -1,3 +1,4 @@
+//go:build js
// +build js
// Package wsjs implements typed access to the browser javascript WebSocket API.
diff --git a/vendor/nhooyr.io/websocket/read.go b/vendor/nhooyr.io/websocket/read.go
index ae05cf93ed..0f10afef62 100644
--- a/vendor/nhooyr.io/websocket/read.go
+++ b/vendor/nhooyr.io/websocket/read.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket
diff --git a/vendor/nhooyr.io/websocket/write.go b/vendor/nhooyr.io/websocket/write.go
index 2210cf817a..9528e5acd7 100644
--- a/vendor/nhooyr.io/websocket/write.go
+++ b/vendor/nhooyr.io/websocket/write.go
@@ -1,3 +1,4 @@
+//go:build !js
// +build !js
package websocket