Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 65 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: lint

on:
push:
pull_request:

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

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

- name: Install openapi CLI
run: go install github.com/speakeasy-api/openapi/cmd/openapi@v0.0.0-20260622002648-cfc99c3a8316

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"

- name: Install yamllint
run: pip install yamllint

- name: yamllint YAML specs
shell: bash
run: |
shopt -s globstar nullglob
files=(openapi/**/*.yaml openapi/**/*.yml)
if [ ${#files[@]} -eq 0 ]; then
echo "No YAML spec files found, skipping yamllint."
else
yamllint -c .yamllint.yml "${files[@]}"
fi

- name: Validate JSON spec syntax
shell: bash
run: |
shopt -s globstar nullglob
files=(openapi/**/*.json)
if [ ${#files[@]} -eq 0 ]; then
echo "No JSON spec files found, skipping JSON syntax check."
else
for f in "${files[@]}"; do
jq empty "$f"
done
fi

- name: Validate OpenAPI specs
shell: bash
run: |
shopt -s globstar nullglob
files=(openapi/**/*.yaml openapi/**/*.yml openapi/**/*.json)
if [ ${#files[@]} -eq 0 ]; then
echo "No spec files found, skipping OpenAPI validation."
else
for f in "${files[@]}"; do
echo "Validating $f"
openapi spec validate "$f"
done
fi
27 changes: 27 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: release

on:
push:
branches:
- main

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build asset bundle
env:
SHA: ${{ github.sha }}
run: tar czf "morphic-test-assets-${SHA}.tar.gz" openapi/

- name: Create GitHub release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ github.sha }}
name: ${{ github.sha }}
files: morphic-test-assets-${{ github.sha }}.tar.gz
10 changes: 10 additions & 0 deletions .yamllint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extends: default

rules:
line-length:
max: 120
level: warning
document-start: disable
indentation:
spaces: consistent
indent-sequences: whatever
92 changes: 92 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What this repo is

`morphic-test-assets` is a versioned, external corpus of real-world API specs used to test
[morphic](https://github.com/dexpace/morphic), a spec-to-SDK compiler. Morphic parses specs
(OpenAPI today; Swagger, GraphQL, protobuf, TypeSpec planned) into a spec-agnostic intermediate
representation (IR). This repo holds spec fixtures — and eventually their expected IR output —
independent of morphic's own internal `testdata/` golden fixtures, so morphic's tooling and CI can
pull in a growing corpus without vendoring it into the morphic repo itself.

There is no application code here. This repo is fixtures, directory conventions, and CI.

## Project status

Early scaffold. Only OpenAPI v3.x is in scope for now. One seed fixture exists:
`openapi/v3.1/petstore/spec.yaml`. `openapi/v3.0/` and `openapi/v3.2/` are placeholder directories
(`.gitkeep`) awaiting real examples. `expected_ir_file` goldens are deliberately deferred — morphic's
IR format is still evolving (Milestone 1 in the morphic repo), so hand-written or generated goldens
would go stale almost immediately.

## Directory & naming conventions

- Spec-type directories live at the repo root: `openapi/` (future: `graphql/`, `protobuf/`,
`typespec/`, ...).
- One directory per spec version inside each: `v3.0/`, `v3.1/`, `v3.2/`.
- One directory per API inside that: `<spec-type>/<version>/<api-name>/`.
- Each API directory holds `spec_file` and, once available, `expected_ir_file` (e.g. `spec.yaml` +
`spec-ir.json`).
- APIs split across multiple spec documents use numbered files instead: `spec-1.yml`, `spec-2.yml`,
with matching `spec-1-ir.json`, `spec-2-ir.json` once IR goldens are added.
- Spec files keep their original serialization format (YAML or JSON) when added — don't normalize
or convert format; that's needless transformation and risks drifting from the upstream source.

## Fixture quality bar

- A fixture must be genuinely valid OpenAPI, not merely "looks right." Before adding or changing
any spec file, validate it locally:
```bash
go install github.com/speakeasy-api/openapi/cmd/openapi@v0.0.0-20260622002648-cfc99c3a8316
openapi spec validate path/to/spec.yaml
```
This is the exact same parser library morphic's own compiler depends on
(`github.com/speakeasy-api/openapi`) — if a spec doesn't validate cleanly here, morphic won't
compile it either.
- Don't assume a fixture's origin without checking. A prior fixture
(`openapi/v3.1/petstore/spec.yaml`) was assumed at first to be the official OAI example; tracing
it (diffing against public repos) showed it was actually `speakeasy-api/openapi`'s own test
fixture, and it had one real defect (`$vocabulary` as a bare string instead of the
JSON-Schema-2020-12-required object) that `openapi spec validate` caught and that was fixed in
this repo's copy. Verify provenance and correctness rather than trusting a filename or a
familiar-looking shape.
- Don't gate validity on Spectral or other OpenAPI-3.0-era linters for 3.1 fixtures that use
`$id`-based JSON Schema 2020-12 references — they raise false-positive `invalid-ref` errors
because they don't do full `$id` resolution. `openapi spec validate` is the ground truth here.
- Don't gate on `openapi spec lint` (the same CLI's OWASP/security/style ruleset) either — it's
calibrated for hand-authored new APIs, not a corpus of arbitrary real-world specs, and produces
dozens of stylistic/security-best-practice findings that aren't fixture defects.

## CI

- `.github/workflows/lint.yml` (push, PR): `yamllint` on YAML spec files (config: `.yamllint.yml`),
`jq empty` on JSON spec files, `openapi spec validate` on every spec file.
- `.github/workflows/release.yml` (push to `main` only — this single trigger is meant to cover both
"every commit" and "every PR merge," since a merge is itself a push to `main`): bundles every
spec-type directory into `morphic-test-assets-<full-commit-sha>.tar.gz` and publishes it as a
GitHub Release tagged with that same full 40-character commit SHA.
- No semantic versioning: consumers pin to a specific commit SHA / release, not a version range.

## Repository rules

These mirror the conventions already in force in `dexpace/morphic` and other dexpace repos, kept
consistent so contributors don't have to context-switch between repos.

- Branch from `main`: `type/short-desc` (e.g. `feat/github-api-fixture`,
`fix/petstore-vocabulary`, `ci/pin-openapi-cli-version`).
- No CODEOWNERS, PR/issue templates, or CODE_OF_CONDUCT.md exist in this repo — don't assume them
or invent content for files that aren't there.

## Commits & pull requests

- **Conventional Commits**: `type(scope): subject`, imperative mood, subject line only (no period,
≤72 chars). Common types here: `feat` (new fixture or spec-type support), `fix` (fixture defect),
`ci`, `docs`, `chore`. Scope is the touched spec type/API when it narrows things down
(`openapi/petstore`, `ci`) — omit it when the change is repo-wide.
- PR description: Summary / Test plan. Keep PRs scoped to one logical change (one new fixture, or
one CI change) — split unrelated changes into separate PRs.
- Write self-contained, human-framed titles/descriptions. No LLM/session artifacts, no internal
audit/finding IDs, no "remediation"/"audit sweep" framing. State the problem, the change, and the
rationale on their own terms.
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,65 @@
# morphic-test-assets
A set of assets used to test the morphic framework and CLI
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/dexpace-wordmark-dark.svg">
<img alt="dexpace" src="docs/assets/dexpace-wordmark-light.svg" width="280">
</picture>
</p>

<h1 align="center">morphic-test-assets</h1>

<p align="center">
<a href="https://github.com/dexpace/morphic-test-assets/actions/workflows/lint.yml"><img alt="lint" src="https://github.com/dexpace/morphic-test-assets/actions/workflows/lint.yml/badge.svg"></a>
<a href="https://github.com/dexpace/morphic-test-assets/actions/workflows/release.yml"><img alt="release" src="https://github.com/dexpace/morphic-test-assets/actions/workflows/release.yml/badge.svg"></a>
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
</p>

A versioned corpus of real-world API specs used to test
[morphic](https://github.com/dexpace/morphic), a spec-to-SDK compiler. Morphic
parses specs (OpenAPI today; Swagger, GraphQL, protobuf, and TypeSpec planned)
into a spec-agnostic Intermediate Representation (IR). This repo holds spec
fixtures — and eventually their expected IR output — independent of morphic's
own internal `testdata/` golden fixtures, so morphic's tooling and CI can pull
in a growing, external corpus.

## Structure

One directory per spec format at the repo root, then one per spec version,
then one per API:

```
openapi/
v3.0/
v3.1/
petstore/
spec.yaml
v3.2/
```

Each API directory holds `spec_file` and, once available, `expected_ir_file`
(e.g. `spec.yaml` + `spec-ir.json`). IR golden files are omitted for now —
morphic's IR format is still evolving, so hand-written or generated goldens
would go stale immediately. Spec files keep their original serialization
format (YAML or JSON) rather than being normalized to one.

APIs split across multiple spec documents use numbered files instead:
`spec-1.yml`, `spec-2.yml`, with matching `spec-1-ir.json`, `spec-2-ir.json`
once IR goldens are added.

Only OpenAPI v3.x is in scope for now.

## CI

- **`lint.yml`** (push, PR): validates every file under `openapi/**` —
`yamllint` for YAML syntax, `jq` for JSON syntax, and
[`openapi spec validate`](https://github.com/speakeasy-api/openapi) (the
same OpenAPI parser morphic itself depends on) for structural OpenAPI
validity.
- **`release.yml`** (push to `main`): bundles every spec-type directory into
`morphic-test-assets-<commit-sha>.tar.gz` and publishes it as a GitHub
Release tagged with the full commit SHA. One release per commit on `main`.

## Versioning

There's no semantic version — each release is tagged with the exact commit
SHA it was built from. Consumers pin to a specific SHA/release rather than a
version range.
6 changes: 6 additions & 0 deletions docs/assets/dexpace-wordmark-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading