Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: generate types with quicktype #303

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ SRC := $(shell find . -type f -name '*.go' -print) go.mod go.sum
#//////////////////////////////////////////////////////////////////////////////
#
.PHONY: all
all: clean build test generate-compdef-stdout generate-ssp-stdout
all: clean build test generate

.PHONY: help
help: ## Show this help message.
Expand Down Expand Up @@ -77,14 +77,14 @@ install: ## Install binary to $INSTALL_PATH.
.PHONY: upgrade
upgrade: ## Upgrade oscal schema version and generate new types and doctored schema.
make doctor-latest-schema
make generate-latest-schema
make generate
echo -e "---\noscal: v$(subst -,.,$(OSCAL_LATEST))" > update/oscal-version.yaml
rm $(UNDOCTORED_SCHEMA)

.PHONY: doctor-latest
doctor-latest-schema: clean build
$(BINDIR)/$(BINNAME) doctor -f $(UNDOCTORED_SCHEMA) -o $(OSCAL_LATEST_SCHEMA)

.PHONY: generate-latest
generate-latest-schema: clean build
$(BINDIR)/$(BINNAME) generate -f $(OSCAL_LATEST_SCHEMA) --pkg $(OSCAL_LATEST_PACKAGE) --tags json,yaml -o $(OSCAL_LATEST_OUTPUT)/types.go
.PHONY: generate
generate:
go generate
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/defenseunicorns/go-oscal)](https://goreportcard.com/report/github.com/defenseunicorns/go-oscal)
[![License](https://img.shields.io/github/license/defenseunicorns/go-oscal)](https://github.com/defenseunicorns/go-oscal/blob/main/LICENSE)

go-oscal is a comprehensive Go library designed for interacting with the Open Security Controls Assessment Language (OSCAL). It offers robust support for OSCAL releases >=1.0.4, providing Go types that correspond to the latest OSCAL schemas. Notably, go-oscal offers more than just type definitions; it includes tooling for validating OSCAL documents against their respective OSCAL version schemas, facilitating the seamless transition of existing OSCAL documents to newer versions, and generating new OSCAL types as needed. Leveraging the OSCAL Complete Schema definition, go-oscal ensures that developers have access to the most up-to-date and accurate representations of OSCAL releases for their projects.
go-oscal is a comprehensive Go library designed for interacting with the Open Security Controls Assessment Language (OSCAL). It offers robust support for OSCAL releases >=1.0.4, providing Go types (using [quicktype](https://github.com/quicktype/quicktype)) that correspond to the latest OSCAL schemas. Notably, go-oscal offers more than just type definitions; it includes tooling for validating OSCAL documents against their respective OSCAL version schemas, facilitating the seamless transition of existing OSCAL documents to newer versions, and generating new OSCAL types as needed. Leveraging the OSCAL Complete Schema definition, go-oscal ensures that developers have access to the most up-to-date and accurate representations of OSCAL releases for their projects.

## Table Of Contents

Expand All @@ -16,6 +16,8 @@ go-oscal is a comprehensive Go library designed for interacting with the Open Se
- [Import](#import)
- [Using Types](#using-types)
- [Development](#development)
- [Generating Types](#generating-types)
- [Upgrading OSCAL Version](#upgrading-oscal-version)
- [Additional Resources and Projects](#additional-resources-and-projects)

## Usage
Expand All @@ -31,7 +33,6 @@ go build .
- [validate](./docs/commands/validate.md)
- [revise](./docs/commands/revise.md)
- [doctor](./docs/commands/doctor.md)
- [generate](./docs/commands/generate.md)


### Import
Expand Down Expand Up @@ -65,8 +66,24 @@ For development, the `Makefile` can be used to build, test, and generate the Go
make test
```

## Generating Types

To [generate the types](./docs/generating-types.md), run the following command:

```bash
make generate
```

## Upgrading OSCAL Version

To [upgrade the OSCAL version](./docs/upgrading-oscal-version.md), run the following command:

```bash
make upgrade OSCAL_LATEST=X-X-X UNDOCTORED_SCHEMA=path/to/undoctored-schema.json
```

## Additional Resources and Projects
- [lula](https://github.com/defenseunicorns/lula)
- [OSCAL](https://github.com/usnistgov/OSCAL)
- [fedramp automation](https://github.com/GSA/fedramp-automation)
- [Awesome Oscal](https://github.com/oscal-club/awesome-oscal)
- [Awesome Oscal](https://github.com/oscal-club/awesome-oscal)
8 changes: 0 additions & 8 deletions docs/commands/generate.md

This file was deleted.

46 changes: 46 additions & 0 deletions docs/generating-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generating OSCAL Types

This project uses a custom script to generate Go types from OSCAL JSON schemas. The process is automated using the `go generate` command.

## Prerequisites

- Bash shell
- Node.js and npm (for running `npx quicktype`)
- Go installed on your system

## Generation Process

1. The type generation is triggered by running:

```
go generate
```

This command is defined in the `main.go` file:

```go
//go:generate ./hack/gen-types.sh
```

2. The `gen-types.sh` script performs the following actions:
- Iterates through all `oscal_complete_schema-*.json` files in the `src/internal/schemas` directory
- Extracts the version number from each filename
- Creates an output directory for each version
- Uses `quicktype` to generate Go types from the JSON schema
- Adds YAML and XML tags to the generated structs using `sed`

## Output

The generated types are placed in `src/types/oscal-<version>/types.go`, where `<version>` is the OSCAL schema version (e.g., `1-0-0` for version 1.0.0).

Each generated file contains a package named `oscalTypes_<version>` and a top-level struct named `OscalModels`.

## Updating Types

To update the generated types:

1. Ensure you have the latest OSCAL JSON schemas in `src/internal/schemas`
2. Run `go generate` in the project root directory

This will regenerate all type files based on the current schemas.

2 changes: 1 addition & 1 deletion docs/upgrading-oscal-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
## Adding new Oscal version
- download the most recent undoctored `oscal_complete_schema.json` file at https://github.com/usnistgov/OSCAL/releases
- Run `make OSCAL_LATEST=X-X-X UNDOCTORED_SCHEMA=path/to/undoctored-schema.json upgrade`
- This will run build, [doctor](./commands/doctor.md) the schema, placing it in `src/internal/schemas`, and [generate](./commands/generate.md) the new types.
- This will run build, [doctor](./commands/doctor.md) the schema, placing it in `src/internal/schemas`, and [generate](./generating-types.md) the new types.
- This will also ***DELETE*** the undoctored schema.
39 changes: 39 additions & 0 deletions hack/gen-types.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

# Set the source and destination directories
SCHEMA_DIR="src/internal/schemas"
OUTPUT_DIR="src/types"

# Loop through all JSON files in the schema directory
for schema_file in "$SCHEMA_DIR"/oscal_complete_schema-*.json; do
# Extract the version number from the filename
version=$(echo "$schema_file" | sed -n 's/.*oscal_complete_schema-\(.*\)\.json/\1/p' | tr '.' '-')

# Create the output directory if it doesn't exist
mkdir -p "$OUTPUT_DIR/oscal-$version"

# Generate the Go types using quicktype
cat "$schema_file" | npx quicktype -s schema \
-o "$OUTPUT_DIR/oscal-$version/types.go" \
--package "oscalTypes_${version//-/_}" \
--top-level OscalModels

# Add YAML and XML tags
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS version
sed -i '' '
s/`json:"\([^"]*\)"`/`json:"\1" yaml:"\1" xml:"\1"`/g
s/`json:"\([^"]*\)" yaml:"\([^"]*\)"`/`json:"\1" yaml:"\2" xml:"\2"`/g
' "$OUTPUT_DIR/oscal-$version/types.go"
else
# Linux version
sed -i '
s/`json:"\([^"]*\)"`/`json:"\1" yaml:"\1" xml:"\1"`/g
s/`json:"\([^"]*\)" yaml:"\([^"]*\)"`/`json:"\1" yaml:"\2" xml:"\2"`/g
' "$OUTPUT_DIR/oscal-$version/types.go"
fi

echo "Generated types for OSCAL version $version"
done

echo "Type generation complete"
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import "github.com/defenseunicorns/go-oscal/src/cmd"

//go:generate ./hack/gen-types.sh
func main() {
cmd.Execute()
}
67 changes: 0 additions & 67 deletions src/cmd/generate/generate.go

This file was deleted.

Loading