Skip to content
Draft
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
8e9125f
feat: prototype 3.0 model
kzantow Aug 2, 2024
b92b27a
chore: support external references
kzantow Aug 4, 2024
08c976d
chore: bad CPE example
kzantow Aug 6, 2024
49d029d
chore: update to new prototype model
kzantow Jan 28, 2025
23c3aaf
Merge remote-tracking branch 'upstream/main' into feat/spdx-3-prototype
kzantow Jan 28, 2025
a45af1e
chore: update go version to 1.23
kzantow Jan 29, 2025
8533d40
chore: update model and examples
kzantow Feb 4, 2025
53e1f17
feat: mostly functional SPDX 3 model with validation
kzantow Mar 10, 2025
a9d84dc
chore: functional converter with spdx 3
kzantow Mar 12, 2025
56f2c82
chore: add Cast function
kzantow Aug 6, 2025
1dbe8fe
chore: upgrade go-struct-converter
kzantow Aug 6, 2025
e693934
chore: prototype convert function
kzantow Aug 6, 2025
4a052c2
Merge remote-tracking branch 'upstream/main' into feat/spdx-3-prototype
kzantow Aug 6, 2025
af194a5
Merge remote-tracking branch 'upstream/main' into feat/spdx-3-prototype
kzantow Sep 8, 2025
75e046c
feat(wip): struct-based v3 serializations
kzantow Oct 8, 2025
293fbfb
chore: update cpe
kzantow Oct 8, 2025
5a408ad
chore: erroneous commit
kzantow Oct 8, 2025
7df12e9
feat: flat struct generation, update tests
kzantow Oct 8, 2025
20112fc
chore: update tests
kzantow Oct 8, 2025
084656c
chore: adjust coverage filtering
kzantow Oct 8, 2025
162bb87
chore: minor updates
kzantow Oct 8, 2025
4a11143
chore: bump go-ld
kzantow Oct 9, 2025
77304a6
chore: cleanup test logging, misc fixes
kzantow Oct 9, 2025
22d11c1
chore: move json ld library to internal package
kzantow Oct 13, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: '1.18'
go-version: '1.23'
- name: Run tests
run: make test
- name: Send coverage report to coveralls
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ format:

.PHONY: unit
unit:
go test -v -covermode=count -coverprofile=profile.cov ./...
go test -v -covermode=count -coverprofile=profile.cov.tmp ./...
cat profile.cov.tmp | grep -v /internal/ | grep -v /model.go | grep -v /model_validations.go > profile.cov # ignore generated model file

.PHONY: fuzz
fuzz:
go test -v -run=Fuzz -fuzz=FuzzShouldIgnore ./utils -fuzztime=10s
go test -v -run=Fuzz -fuzz=FuzzPackageCanGetVerificationCode ./utils -fuzztime=10s

.PHONY: generate
generate:
go run ./spdx/v3/internal/generate
17 changes: 10 additions & 7 deletions convert/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ import (
converter "github.com/anchore/go-struct-converter"

"github.com/spdx/tools-golang/spdx/common"
"github.com/spdx/tools-golang/spdx/v2/v2_1"
"github.com/spdx/tools-golang/spdx/v2/v2_2"
"github.com/spdx/tools-golang/spdx/v2/v2_3"
"github.com/spdx/tools-golang/spdx/v3/v3_0"
)

var DocumentChain = converter.NewChain(
v2_1.Document{},
v2_2.Document{},
v2_3.Document{},
)
func DocumentChain() converter.FuncChain {
return converter.NewFuncChain(
v2_2.From_v2_1, v2_2.To_v2_1,
v2_3.From_v2_2, v2_3.To_v2_2,
v3_0.From_v2_3,
// for future v3.x to v3.y conversions, see funcChain.AutoPackageConverter()
)
}

// Document converts from one document to another document
// For example, converting a document to the latest version could be done like:
Expand All @@ -35,5 +38,5 @@ func Document(from common.AnyDocument, to common.AnyDocument) error {
reflect.ValueOf(to).Elem().Set(reflect.ValueOf(from))
return nil
}
return DocumentChain.Convert(from, to)
return DocumentChain().Convert(from, to)
}
23 changes: 19 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
module github.com/spdx/tools-golang

go 1.22
go 1.23.5

require (
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092
github.com/anchore/go-struct-converter v0.0.0-20251008145103-b79fc8ba4f45
github.com/dave/jennifer v1.7.1
github.com/deiu/rdf2go v0.0.0-20241212211204-b661ba0dfd25
github.com/gertd/go-pluralize v0.2.1
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/piprate/json-gold v0.7.0
github.com/pmezard/go-difflib v1.0.0
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb
github.com/stretchr/testify v1.11.1
mvdan.cc/gofumpt v0.7.0
sigs.k8s.io/yaml v1.6.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deiu/gon3 v0.0.0-20241212124032-93153c038193 // indirect
github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326 // indirect
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/tools v0.17.0 // indirect
)
36 changes: 34 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092 h1:aM1rlcoLz8y5B2r4tTLMiVTrMtpfY0O8EScKJxaSaEc=
github.com/anchore/go-struct-converter v0.0.0-20221118182256-c68fdcfa2092/go.mod h1:rYqSE9HbjzpHTI74vwPvae4ZVYZd1lue2ta6xHPdblA=
github.com/anchore/go-struct-converter v0.0.0-20251008145103-b79fc8ba4f45 h1:sqkP57/1/85SgWDHHJmY4ubBJUIpGlto6JZql6Dpp34=
github.com/anchore/go-struct-converter v0.0.0-20251008145103-b79fc8ba4f45/go.mod h1:SxEY1rkVuDSqQOnD1+G4A45wAKXPMum/a51ywvN/8o4=
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deiu/gon3 v0.0.0-20241212124032-93153c038193 h1:EQBdXSCO7r+0KQE/pN6v+RAH7p6+yz+6pbCfHh+ETME=
github.com/deiu/gon3 v0.0.0-20241212124032-93153c038193/go.mod h1:EdezkFZtCJELxMo+YIX5B5i5ofz9U+n+xSxWku6mOS0=
github.com/deiu/rdf2go v0.0.0-20241212211204-b661ba0dfd25 h1:drltZW/t3SgIHpURgCii68Jq0zvpcGhtkWRf3zmbxpc=
github.com/deiu/rdf2go v0.0.0-20241212211204-b661ba0dfd25/go.mod h1:AAL3UBTBShUaH3y68LyhlSjz6S6DoHoMSpAWvnCiTCs=
github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlLgiA=
github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326 h1:YP3lfXXYiQV5MKeUqVnxRP5uuMQTLPx+PGYm1UBoU98=
github.com/linkeddata/gojsonld v0.0.0-20170418210642-4f5db6791326/go.mod h1:nfqkuSNlsk1bvti/oa7TThx4KmRMBmSxf3okHI9wp3E=
github.com/piprate/json-gold v0.7.0 h1:bEMirgA5y8Z2loTQfxyIFfY+EflxH1CTP6r/KIlcJNw=
github.com/piprate/json-gold v0.7.0/go.mod h1:RVhE35veDX19r5gfUAR+IYHkAUuPwJO8Ie/qVeFaIzw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f h1:L2/fBPABieQnQzfV40k2Zw7IcvZbt0CN5TgwUl8zDCs=
github.com/rychipman/easylex v0.0.0-20160129204217-49ee7767142f/go.mod h1:MZ2GRTcqmve6EoSbErWgCR+Ash4p8Gc5esHe8MDErss=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb h1:bLo8hvc8XFm9J47r690TUKBzcjSWdJDxmjXJZ+/f92U=
github.com/spdx/gordf v0.0.0-20201111095634-7098f93598fb/go.mod h1:uKWaldnbMnjsSAXRurWqqrdyZen1R7kxl8TkmWk2OyM=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
Expand All @@ -14,9 +40,15 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
31 changes: 29 additions & 2 deletions json/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import (
"encoding/json"
"fmt"
"io"
"regexp"

"github.com/spdx/tools-golang/convert"
"github.com/spdx/tools-golang/spdx"
"github.com/spdx/tools-golang/spdx/common"
"github.com/spdx/tools-golang/spdx/v2/v2_1"
"github.com/spdx/tools-golang/spdx/v2/v2_2"
"github.com/spdx/tools-golang/spdx/v2/v2_3"
"github.com/spdx/tools-golang/spdx/v3/v3_0"
)

// Read takes an io.Reader and returns a fully-parsed current model SPDX Document
Expand Down Expand Up @@ -48,8 +50,19 @@ func ReadInto(content io.Reader, doc common.AnyDocument) error {
return fmt.Errorf("not a valid SPDX JSON document")
}

version, ok := val["spdxVersion"]
if !ok {
version, _ := val["spdxVersion"].(string)
if version == "" {
version, _ = val["@context"].(string)
if version != "" {
extract := regexp.MustCompile(`https://spdx.org/rdf/(\d+(?:\.\d+)+)/spdx-context\.jsonld`)
matches := extract.FindStringSubmatch(version)
if len(matches) == 2 {
version = matches[1]
}
}
}

if version == "" {
return fmt.Errorf("JSON document does not contain spdxVersion field")
}

Expand All @@ -75,6 +88,20 @@ func ReadInto(content io.Reader, doc common.AnyDocument) error {
return err
}
data = doc
case "3.0.0":
fallthrough
case v3_0.Version:
// support older 3.0.x versions
contents := buf.Bytes()
if version != v3_0.Version {
contents = bytes.Replace(contents, []byte(version), []byte(fmt.Sprintf("https://spdx.org/rdf/%s/spdx-context.jsonld", v3_0.Version)), 1)
}
var in v3_0.Document
err = json.Unmarshal(contents, &in)
if err != nil {
return err
}
data = in
default:
return fmt.Errorf("unsupported SDPX version: %s", version)
}
Expand Down
28 changes: 28 additions & 0 deletions json/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package json
import (
"os"
"testing"

"github.com/spdx/tools-golang/spdx/v3/v3_0"
)

// TestRead tests that the SPDX Reader can still parse json documents correctly
Expand All @@ -28,3 +30,29 @@ func TestRead(t *testing.T) {
})
}
}

// TestRead tests that the SPDX Reader can still parse json documents correctly
// this protects against any of the custom unmarshalling code breaking given a new change set
func TestReadV3(t *testing.T) {
tt := []struct {
filename string
}{
{"test_fixtures/spdx2_3.json"},
{"../spdx/v3/v3_0/testdata/test.json"},
}

for _, tc := range tt {
t.Run(tc.filename, func(t *testing.T) {
file, err := os.Open(tc.filename)
if err != nil {
t.Errorf("error opening %s: %v", tc.filename, err)
}
defer file.Close()
doc := v3_0.Document{}
err = ReadInto(file, &doc)
if err != nil {
t.Errorf("error reading %s: %v", tc.filename, err)
}
})
}
}
9 changes: 0 additions & 9 deletions spdx/v2/v2_1/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
package v2_1

import (
converter "github.com/anchore/go-struct-converter"

"github.com/spdx/tools-golang/spdx/v2/common"
)

Expand Down Expand Up @@ -70,10 +68,3 @@ type Document struct {
// DEPRECATED in version 2.0 of spec
Reviews []*Review `json:"-"`
}

func (d *Document) ConvertFrom(_ interface{}) error {
d.SPDXVersion = Version
return nil
}

var _ converter.ConvertFrom = (*Document)(nil)
10 changes: 5 additions & 5 deletions spdx/v2/v2_2/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import (
"encoding/json"
"fmt"

converter "github.com/anchore/go-struct-converter"

"github.com/spdx/tools-golang/spdx/v2/common"
"github.com/spdx/tools-golang/spdx/v2/v2_1"
)

const Version = "SPDX-2.2"
Expand Down Expand Up @@ -74,12 +73,13 @@ type Document struct {
Reviews []*Review `json:"-"`
}

func (d *Document) ConvertFrom(_ interface{}) error {
func From_v2_1(_ v2_1.Document, d *Document) {
d.SPDXVersion = Version
return nil
}

var _ converter.ConvertFrom = (*Document)(nil)
func To_v2_1(_ Document, d *v2_1.Document) {
d.SPDXVersion = v2_1.Version
}

func (d *Document) UnmarshalJSON(b []byte) error {
type doc Document
Expand Down
Loading