diff --git a/.github/workflows/bookstore-api-optic.yml b/.github/workflows/bookstore-api-optic.yml index ed48bbb..9ddbcc7 100644 --- a/.github/workflows/bookstore-api-optic.yml +++ b/.github/workflows/bookstore-api-optic.yml @@ -1,65 +1,26 @@ -name: bookstore-api-optic +name: optic on: + pull_request: push: branches: - main - paths: - - apps/bookstore-api/** - pull_request: - paths: - - apps/bookstore-api/** - workflow_call: defaults: - run: - working-directory: apps/bookstore-api + run: + working-directory: apps/bookstore-api jobs: - diff-all: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Install dependencies - run: yarn install - - - name: Generate Spec - run: yarn generate-spec - - - uses: opticdev/action@v1 - with: - # Your Optic Cloud Token - optic_token: ${{ secrets.OPTIC_TOKEN }} - - # A GitHub token with access to create comments on pull requests - github_token: ${{ secrets.GITHUB_TOKEN }} - - # If true, standard check failures will cause this action to fail. - # If false, standard check failures will show in PR comments and - # in Optic Cloud but will not cause the action to fail - standards_fail: true - - # If you have more than one spec, separate matches with commas - # (openapi.yml,other.yml) - additional_args: --match apps/bookstore-api/openapi.yml - - compare_from_pr: cloud:default - compare_from_push: cloud:default - verify: + run: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - - name: Install dependencies - run: yarn install - - name: Install Optic - run: sh -c "$(curl -Ls https://install.useoptic.com/install.sh)" -- latest /usr/local/bin/ - - - name: Generate Spec - run: yarn generate-spec + run: npm install --location global @useoptic/optic - - name: Verify spec against integration tests - run: yarn verify + - name: Run Optic + env: + OPTIC_TOKEN: ${{ secrets.OPTIC_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: optic run diff --git a/.github/workflows/bookstore-optic.yml b/.github/workflows/bookstore-optic.yml deleted file mode 100644 index 35ff75c..0000000 --- a/.github/workflows/bookstore-optic.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: bookstore-optic -on: - push: - branches: - - main - paths: - - ci/github-actions-bookstore/** - pull_request: - paths: - - ci/github-actions-bookstore/** - workflow_call: - -jobs: - diff-all: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - uses: opticdev/action@v1 - with: - # Your Optic Cloud Token - optic_token: ${{ secrets.OPTIC_TOKEN }} - - # A GitHub token with the `pull-requests: write` permissions scope - github_token: ${{ secrets.GITHUB_TOKEN }} - - # true: standard check failures will cause this action to fail - # false: standard check failures will show in PR comments and in Optic Cloud but will not cause the action to fail - standards_fail: true diff --git a/apps/bookstore-api/README.md b/apps/bookstore-api/README.md index 49d2606..444da6a 100644 --- a/apps/bookstore-api/README.md +++ b/apps/bookstore-api/README.md @@ -1,50 +1,16 @@ -# Bookstore API - -Bookstore API built using Fastify and Typescript with Optic. Generates an OpenAPI spec using `@fastify/swagger` and tracks changes using Optic. We have set up Optic to: -- [preview API changes in PRs](#preview-api-changes-in-prs) -- [test for breaking changes](https://github.com/opticdev/bookstore-api/pull/1) -- [enforce the API style guide](https://github.com/opticdev/bookstore-api/pull/3) -- [share our API changelog and documentation with consumers](#accurate-documentation-and-changelogs) - -Take a look at the guides or just dig around the repo. You can start a server or generate an OpenAPI spec from the code. - -## Running this repo locally - -To run this locally, you will need [node >= 16](https://nodejs.org/en) and [yarn](https://yarnpkg.com/getting-started/install). - -Get started by installing dependencies: - -`yarn install` - -And then run one of the following commands: -- `yarn start:local` - starts the server -- `yarn verify` - verifies the spec using integration tests -- `yarn generate-spec` - generates an OpenAPI spec from code definitions - -## Preview API changes in PRs - -Take a look at the [open pull requests of the repo](https://github.com/opticdev/bookstore-api/pulls). It's difficult to know how the code changes will impact your API. Optic adds preview documentation and an API changelog to each PR so every developer on your team knows exactly what changes to the API have been proposed. - -Here are a couple of examples of what Optic can do: -- [Optic caught a breaking change](https://github.com/opticdev/bookstore-api/pull/1) -- A small line of code can change multiple endpoints. [Optic makes it easy to see the effective API changes being proposed](https://github.com/opticdev/bookstore-api/pull/2) -- [Adding 2 new query parameters that do not follow our team's naming conventions](https://github.com/opticdev/bookstore-api/pull/3) - -## Accurate documentation and changelogs - -Every time this repositories main branch is updated, a new version of your API is pushed to Optic. Developers on your team, or your consumers (if public), can see a complete API changelog, and accurate documentation for the API. - -- [View the Optic Changelog](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/apis/Ru2Me4G-2nIro-cj4Bbib) -![optic changelog](/images/changelog.png) -- [View diffs between different API versions](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/apis/Ru2Me4G-2nIro-cj4Bbib/operations/get.%2Fauthors%2F%7BauthorId%7D?diffTag=fyXT_OAvfLfjlipBFl2Xw) -![diff two versions](/images/diff-versions.png) -- [Preview documentation and changes in pull requests](https://github.com/opticdev/bookstore-api/pull/2#issuecomment-1613615164) -![preview changes](/images/preview-changes.png) - -You can also add badges to your repository that show you how often your API is changing and the number of endpoints you have. - -[![Optic badge of documentation](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/public/apis/Ru2Me4G-2nIro-cj4Bbib/badge.svg?type=documentation&code=O3UVmk3goSaVOxxbSTHxu.hiMaTkrqNRj8dEb41awZRxdn0iUZ9UhT)](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/apis/Ru2Me4G-2nIro-cj4Bbib?ref=badge) [![Optic badge of changes](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/public/apis/Ru2Me4G-2nIro-cj4Bbib/badge.svg?type=changes&code=a5dN_bRR7n6-MEutVOj8f.jdaniuNKGOz-CgAf_R5YfQIR3UvNYcWK)](https://app.useoptic.com/organizations/32613bcd-704e-4661-85f0-7b3d75613fb0/apis/Ru2Me4G-2nIro-cj4Bbib?ref=badge) - -## Set up Optic Cloud - -You can follow instructions on how to set up Optic Cloud on [our website](https://www.useoptic.com/docs/cloud-get-started). If you generate an OpenAPI spec from your code (just like this repo), you should follow our [generated spec set up guide](https://www.useoptic.com/docs/setup-ci-generated). +A demo repository with a book store API example. + +## Local usage +- Run `optic run` on the main branch +- make some changes to `openapi.yml` +- run `optic run` again. + +## CI setup +The repo is setup with Gitlab CI and Github Action configuration files: +- fork the repository +- grab an Optic organization token from https://app.useoptic.com `tokens` tab, and set it as `OPTIC_TOKEN` in your CI env +- add a `GITHUB_TOKEN` or `OPTIC_GITLAB_TOKEN` with comment permission to your CI env (more about this [in the docs](http://localhost:3000/docs/setup-ci#configure-commenting-on-pull-requests-optional)) +- create a pull request containing breaking changes in `openapi.yml` to see Optic in action. + +## Advanced +- Configure custom governance rules in `optic.yml`: read [the docs](http://localhost:3000/docs/lint-openapi) diff --git a/ci/github-actions-bookstore/.github/workflows/README.md b/ci/github-actions-bookstore/.github/workflows/README.md deleted file mode 100644 index 9895073..0000000 --- a/ci/github-actions-bookstore/.github/workflows/README.md +++ /dev/null @@ -1 +0,0 @@ -⚠️ Note: If this were a standalone project, the GitHub Actions workflow file would live here. Because workflow files must exist in the root `.github/workflows` directory, we symlink the relevant workflows here for reference purposes. \ No newline at end of file diff --git a/ci/github-actions-bookstore/.github/workflows/optic.yml b/ci/github-actions-bookstore/.github/workflows/optic.yml deleted file mode 120000 index 5349ca9..0000000 --- a/ci/github-actions-bookstore/.github/workflows/optic.yml +++ /dev/null @@ -1 +0,0 @@ -.github/workflows/bookstore-optic.yml \ No newline at end of file diff --git a/ci/github-actions-bookstore/.gitignore b/ci/github-actions-bookstore/.gitignore deleted file mode 100644 index e43b0f9..0000000 --- a/ci/github-actions-bookstore/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.DS_Store diff --git a/ci/github-actions-bookstore/README.md b/ci/github-actions-bookstore/README.md deleted file mode 100644 index 4edeaf5..0000000 --- a/ci/github-actions-bookstore/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GitHub Actions Bookstore example - -This directory contains a reference example for implementing Optic in a GitHub Actions workflow. \ No newline at end of file diff --git a/ci/github-actions-bookstore/openapi.yml b/ci/github-actions-bookstore/openapi.yml deleted file mode 100644 index dc4a50d..0000000 --- a/ci/github-actions-bookstore/openapi.yml +++ /dev/null @@ -1,236 +0,0 @@ -openapi: 3.1.3 -info: - title: Optic Bookstore Demo Spec - description: A demo specification for Optic - contact: - email: support@useoptic.com - version: 1.0.0 -servers: - - url: https://bookstore.optic.dev -paths: - /books: - get: - summary: Get a list of books - parameters: - - schema: - type: string - in: query - description: ID of book to fetch after - name: after_id - required: false - - schema: - type: string - enum: - - asc - - desc - in: query - description: Order to sort books by, defaults to asc - name: sort_order - required: false - - schema: - type: string - enum: - - created_at - - name - in: query - description: Book key to sort by, defaults to name - name: sort_key - required: false - responses: - "200": - description: Book success response - content: - application/json: - schema: - type: object - properties: - data: - type: array - items: - $ref: "#/components/schemas/BookResponse" - next: - type: - - string - - "null" - description: after_id for next page - has_more_data: - type: boolean - required: - - data - - next - - has_more_data - post: - summary: Create a book - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/BookRequest" - responses: - "201": - description: Successfully created book - content: - application/json: - schema: - type: object - properties: - id: - type: string - required: - - id - /books/{book_id}: - get: - summary: Get a book - parameters: - - $ref: "#/components/parameters/BookId" - responses: - "200": - description: Book success response - content: - application/json: - schema: - $ref: "#/components/schemas/BookResponse" - patch: - summary: Update a book - parameters: - - $ref: "#/components/parameters/BookId" - requestBody: - content: - application/json: - schema: - type: object - properties: - name: - type: string - author_id: - type: string - responses: - "204": - description: Successfully updated book - /author: - post: - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/AuthorRequest" - responses: - "201": - description: Successfully created author - content: - application/json: - schema: - type: object - properties: - id: - type: string - required: - - id - /author/{author_id}: - get: - parameters: - - $ref: "#/components/parameters/AuthorId" - responses: - "200": - description: Successful response - content: - application/json: - schema: - $ref: "#/components/schemas/AuthorResponse" - patch: - parameters: - - $ref: "#/components/parameters/AuthorId" - requestBody: - content: - application/json: - schema: - type: object - properties: - name: - type: string - responses: - "204": - description: Successfully updated author - -components: - parameters: - BookId: - schema: - type: string - in: path - description: ID of book - name: book_id - required: true - AuthorId: - schema: - type: string - in: path - description: ID of author - name: author_id - required: true - schemas: - AuthorRequest: - type: object - properties: - name: - type: string - required: - - name - AuthorResponse: - type: object - properties: - id: - type: string - example: FrCmluBlTSwwxLLEbEDCP - name: - type: string - example: Jane Austen - created_at: - type: string - format: timestamp - example: 2023-02-18T14:29:26.384Z - updated_at: - type: string - format: timestamp - example: 2023-03-18T14:29:26.384Z - required: - - id - - name - - created_at - - updated_at - BookRequest: - type: object - properties: - name: - type: string - author_id: - type: string - required: - - name - - author_id - BookResponse: - type: object - properties: - id: - type: string - example: BEfCDC5FHWelCADHR9Rcm - name: - type: string - example: Pride and Prejudice - author_id: - type: string - example: FrCmluBlTSwwxLLEbEDCP - created_at: - type: string - format: timestamp - example: 2023-05-18T14:29:26.384Z - updated_at: - type: string - format: timestamp - example: 2023-05-18T14:29:26.384Z - required: - - id - - name - - author_id - - created_at - - updated_at diff --git a/ci/github-actions-bookstore/optic.yml b/ci/github-actions-bookstore/optic.yml deleted file mode 100644 index 514a663..0000000 --- a/ci/github-actions-bookstore/optic.yml +++ /dev/null @@ -1,9 +0,0 @@ -ruleset: - - breaking-changes - - naming: - required_on: added - # Different names for different parts of the spec - # options = "snake_case" "camelCase" "Capital-Param-Case" "param-case" "PascalCase" - properties: snake_case - pathComponents: snake_case - queryParameters: snake_case