Conversation
- now README.md includes represents the current state of the proejct
- defined Serializable interface with ToData and FromData methods - implemented JSONSerializable struct that uses JSON for serialization - added tests for JSONSerializable to ensure correct serialization and deserialization
There was a problem hiding this comment.
Pull request overview
Introduces a new foundation/serialization capability by defining a Serializable interface and adding a JSON-based implementation, along with basic tests and repo-level developer tooling/docs (Makefile, .gitignore, README updates).
Changes:
- Added
Serializableinterface andJSONSerializableimplementation for JSON marshaling/unmarshaling. - Added a unit test covering JSON round-trip behavior.
- Added README guidance plus Makefile targets for testing/coverage/release and a .gitignore for Go artifacts.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/forging/foundation/serialization/serializable.go | Introduces core Serializable interface. |
| pkg/forging/foundation/serialization/json_serializable.go | Adds JSON-backed implementation of Serializable. |
| pkg/forging/foundation/serialization/json_serializable_test.go | Adds JSON round-trip unit test. |
| README.md | Documents the new serialization package and contributor workflow. |
| Makefile | Adds test/coverage/check-coverage/release targets. |
| .gitignore | Ignores Go build/test artifacts and editor files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @cov=$(shell go tool cover -func=$(COVERAGE_FILE) | awk '/^total:/ {print $$3+0}') ; \ | ||
| if [ $$(echo "$$cov < $(MIN_COVERAGE)" | bc) -eq 1 ]; then \ | ||
| echo "FAIL: coverage below $(MIN_COVERAGE)% ($$cov%)"; exit 1; \ |
There was a problem hiding this comment.
The check-coverage target depends on bc being installed (echo ... | bc). That tool isn’t available by default in some environments/CI images, which can make coverage checks fail unexpectedly. Consider doing the comparison in awk (or Go) to avoid external dependencies, or document bc as a prerequisite.
| ) | ||
|
|
||
| type JSONSerializable struct { | ||
| Value interface{} | ||
| } | ||
|
|
||
| func (j *JSONSerializable) ToData() ([]byte, error) { | ||
| return json.Marshal(j.Value) | ||
| } | ||
|
|
||
| func (j *JSONSerializable) FromData(data []byte) error { | ||
| return json.Unmarshal(data, &j.Value) |
There was a problem hiding this comment.
FromData unmarshals into &j.Value (a *interface{}), which causes encoding/json to replace Value with generic map[string]any/[]any instead of populating the concrete destination. This breaks the intended round-trip and will make the test’s *testStruct type assertion fail. Unmarshal into the concrete destination stored in j.Value (and require it to be a non-nil pointer), or change the type to a generic JSONSerializable[T any] that holds *T so the destination type is explicit.
| ) | |
| type JSONSerializable struct { | |
| Value interface{} | |
| } | |
| func (j *JSONSerializable) ToData() ([]byte, error) { | |
| return json.Marshal(j.Value) | |
| } | |
| func (j *JSONSerializable) FromData(data []byte) error { | |
| return json.Unmarshal(data, &j.Value) | |
| "fmt" | |
| "reflect" | |
| ) | |
| type JSONSerializable struct { | |
| Value interface{} | |
| } | |
| func (j *JSONSerializable) ToData() ([]byte, error) { | |
| return json.Marshal(j.Value) | |
| } | |
| func (j *JSONSerializable) FromData(data []byte) error { | |
| if j == nil { | |
| return fmt.Errorf("JSONSerializable receiver is nil") | |
| } | |
| if j.Value == nil { | |
| return fmt.Errorf("JSONSerializable.Value must be a non-nil pointer; got <nil>") | |
| } | |
| v := reflect.ValueOf(j.Value) | |
| if v.Kind() != reflect.Ptr || v.IsNil() { | |
| return fmt.Errorf("JSONSerializable.Value must be a non-nil pointer; got %T", j.Value) | |
| } | |
| return json.Unmarshal(data, j.Value) |
| @@ -0,0 +1,17 @@ | |||
| package foundation | |||
There was a problem hiding this comment.
Package name is foundation even though the folder path is foundation/serialization. This makes the public API awkward to consume (import path ends in serialization but code is referenced as foundation.JSONSerializable). Align package name with the directory (e.g., package serialization) or move the code under a foundation directory that matches the package name.
| package foundation | |
| package serialization |
| "testing" | ||
| ) | ||
|
|
||
| type testStruct struct { | ||
| Name string | ||
| Age int | ||
| } | ||
|
|
||
| func TestJSONSerializable_ToDataAndFromData(t *testing.T) { | ||
| original := &JSONSerializable{Value: testStruct{Name: "Alice", Age: 30}} | ||
| data, err := original.ToData() | ||
| if err != nil { | ||
| t.Fatalf("ToData failed: %v", err) | ||
| } | ||
|
|
||
| copy := &JSONSerializable{Value: &testStruct{}} | ||
| err = copy.FromData(data) | ||
| if err != nil { | ||
| t.Fatalf("FromData failed: %v", err) | ||
| } | ||
|
|
||
| result, ok := copy.Value.(*testStruct) | ||
| if !ok { | ||
| t.Fatalf("Type assertion failed") | ||
| } | ||
| if result.Name != "Alice" || result.Age != 30 { | ||
| t.Errorf("Expected Alice, 30; got %s, %d", result.Name, result.Age) | ||
| } |
There was a problem hiding this comment.
This file isn’t gofmt-formatted (spaces instead of tabs/standard formatting). Running gofmt (or ensuring the formatter runs in CI) will normalize indentation/import formatting and avoid noisy diffs later.
| "testing" | |
| ) | |
| type testStruct struct { | |
| Name string | |
| Age int | |
| } | |
| func TestJSONSerializable_ToDataAndFromData(t *testing.T) { | |
| original := &JSONSerializable{Value: testStruct{Name: "Alice", Age: 30}} | |
| data, err := original.ToData() | |
| if err != nil { | |
| t.Fatalf("ToData failed: %v", err) | |
| } | |
| copy := &JSONSerializable{Value: &testStruct{}} | |
| err = copy.FromData(data) | |
| if err != nil { | |
| t.Fatalf("FromData failed: %v", err) | |
| } | |
| result, ok := copy.Value.(*testStruct) | |
| if !ok { | |
| t.Fatalf("Type assertion failed") | |
| } | |
| if result.Name != "Alice" || result.Age != 30 { | |
| t.Errorf("Expected Alice, 30; got %s, %d", result.Name, result.Age) | |
| } | |
| "testing" | |
| ) | |
| type testStruct struct { | |
| Name string | |
| Age int | |
| } | |
| func TestJSONSerializable_ToDataAndFromData(t *testing.T) { | |
| original := &JSONSerializable{Value: testStruct{Name: "Alice", Age: 30}} | |
| data, err := original.ToData() | |
| if err != nil { | |
| t.Fatalf("ToData failed: %v", err) | |
| } | |
| copy := &JSONSerializable{Value: &testStruct{}} | |
| err = copy.FromData(data) | |
| if err != nil { | |
| t.Fatalf("FromData failed: %v", err) | |
| } | |
| result, ok := copy.Value.(*testStruct) | |
| if !ok { | |
| t.Fatalf("Type assertion failed") | |
| } | |
| if result.Name != "Alice" || result.Age != 30 { | |
| t.Errorf("Expected Alice, 30; got %s, %d", result.Name, result.Age) | |
| } |
| go test -coverprofile=$(COVERAGE_FILE) ./... | ||
| go tool cover -func=$(COVERAGE_FILE) | ||
| @cov=$(shell go tool cover -func=$(COVERAGE_FILE) | awk '/^total:/ {print $$3+0}') ; \ | ||
| if [ $$(echo "$$cov < $(MIN_COVERAGE)" | bc) -eq 1 ]; then \ | ||
| echo "FAIL: coverage below $(MIN_COVERAGE)% ($$cov%)"; exit 1; \ | ||
| else \ | ||
| echo "PASS: coverage is $$cov%"; \ | ||
| fi |
There was a problem hiding this comment.
In check-coverage, cov=$(shell ...) is evaluated by make during recipe expansion, before the preceding go test -coverprofile=... line generates coverage.out. This can result in go tool cover running against a missing/stale file and makes the target unreliable. Compute cov using shell command substitution ($$(...)) inside the recipe after generating the coverage file.
| release: | ||
| git tag v$(VERSION) | ||
| git push origin v$(VERSION) |
There was a problem hiding this comment.
make release will happily run with an empty VERSION, creating/pushing a v tag, and it always pushes directly to origin. Add guards to require VERSION to be set/valid (and ideally ensure a clean working tree), and consider using an annotated tag (git tag -a) to reduce accidental releases.
- added a new section in the README.md to document the release workflow, including prerequisites, steps for determining the next version, and automating the release process using scripts. This will help maintainers and contributors understand how to manage releases effectively and ensure consistency in versioning and changelog generation.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
foundation/serialization implemented.
in the future maybe it will include impl of default serialization for other presentation layer protocols