diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index ed26995..819cb4a 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -6,22 +6,55 @@ on: - "master" jobs: + setup: + runs-on: ubuntu-latest + outputs: + releases: ${{ steps.releases.outputs.releases }} + steps: + - id: releases + run: | + echo "releases=$(curl -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -H "X-GitHub-Api-Version: 2022-11-28" "https://api.github.com/repos/${{github.repository}}/releases?per_page=100" | jq -c '[.[].tag_name]')" >> $GITHUB_OUTPUT + releases: + needs: setup + runs-on: ubuntu-latest + strategy: + matrix: + release: ${{fromJson(needs.setup.outputs.releases)}} + steps: + - uses: dsaltares/fetch-gh-release-asset@1.1.2 + with: + version: "tags/${{ matrix.release }}" + file: "keymanager-oapi.json" + target: "deploy/releases/${{ matrix.release }}/keymanager-oapi.json" + - name: Save releases (artifact) + uses: actions/upload-artifact@v3 + with: + name: releases + retention-days: 7 + path: | + deploy/releases deploy: + needs: releases runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm i -g @apidevtools/swagger-cli@4 - name: Prepare deploy directory run: | mkdir ./deploy cp -r dist ./deploy cp -r assets ./deploy - cp -r index.html ./deploy - - name: Bundle spec - uses: mpetrunic/swagger-cli-action@v1.0.0 + cp index.html ./deploy + - name: Restore releases + uses: actions/download-artifact@v3 with: - command: "bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" + name: releases + path: deploy/releases + - name: Bundle spec + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" - name: Publish to Github Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./deploy diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 30ac513..850e6e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,20 +1,23 @@ name: CI -on: [push, pull_request] +on: + push: + branches: + - "master" + pull_request: + workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm i -g @apidevtools/swagger-cli@4 @redocly/cli@1.19.0 - name: Lint spec - uses: vaibhav-jain/spectral-action/@v2.6.1 - with: - file_path: keymanager-oapi.yaml + run: redocly lint ./keymanager-oapi.yaml - name: Bundle spec - uses: mpetrunic/swagger-cli-action@v1.0.0 - with: - command: "bundle ./keymanager-oapi.yaml -r -t yaml -o ./bundle.yaml" + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" diff --git a/.github/workflows/pre-release.yaml b/.github/workflows/pre-release.yaml new file mode 100644 index 0000000..5a88c17 --- /dev/null +++ b/.github/workflows/pre-release.yaml @@ -0,0 +1,45 @@ +name: Pre-release + +on: + push: + tags: + - "v*-alpha.*" + - "v*-beta.*" + - "v*-rc.*" + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm i -g @apidevtools/swagger-cli@4 + - name: Update Spec version + run: "sed -i 's/version: \"Dev/version: \"${{ github.ref_name }}/' ./keymanager-oapi.yaml" + - name: Bundle yaml spec + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" + - name: Bundle json spec + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t json -o ./deploy/keymanager-oapi.json" + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + draft: false + prerelease: true + files: | + ./deploy/keymanager-oapi.yaml + ./deploy/keymanager-oapi.json + fail_on_unmatched_files: true + - name: Rollback Release + if: failure() + uses: author/action-rollback@1.0.4 + with: + release_id: ${{ steps.create_release.outputs.id }} + tag: ${{ github.ref }} + delete_orphan_tag: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 57216f9..460b53f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -4,57 +4,56 @@ on: push: tags: - "v*" + - "!v*-alpha.*" + - "!v*-beta.*" + - "!v*-rc.*" jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + - run: npm i -g @apidevtools/swagger-cli@4 + - name: Update Spec version + run: "sed -i 's/version: \"Dev/version: \"${{ github.ref_name }}/' ./keymanager-oapi.yaml" - name: Bundle yaml spec - uses: mpetrunic/swagger-cli-action@v1.0.0 - with: - command: "bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t yaml -o ./deploy/keymanager-oapi.yaml" - name: Bundle json spec - uses: mpetrunic/swagger-cli-action@v1.0.0 + run: "swagger-cli bundle ./keymanager-oapi.yaml -r -t json -o ./deploy/keymanager-oapi.json" + - name: Update index.html + run: | + sed -i "/urls:/a \ {url: \"./releases/${{ github.ref_name }}/keymanager-oapi.json\", name: \"${{ github.ref_name }}\"}," ./index.html + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 with: - command: "bundle ./keymanager-oapi.yaml -r -t json -o ./deploy/keymanager-oapi.json" + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "Release ${{ github.ref_name }}" + branch: release-${{ github.ref_name }} + title: "Release ${{ github.ref_name }}" + body: "" + base: master + add-paths: index.html - name: Create Release id: create_release - uses: actions/create-release@v1 + uses: softprops/action-gh-release@v2 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} draft: false prerelease: false - - name: Upload Yaml Bundle - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./deploy/keymanager-oapi.yaml - asset_name: keymanager-oapi.yaml - asset_content_type: text/x-yaml - - name: Upload Json Bundle - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./deploy/keymanager-oapi.json - asset_name: keymanager-oapi.json - asset_content_type: application/json + files: | + ./deploy/keymanager-oapi.yaml + ./deploy/keymanager-oapi.json + fail_on_unmatched_files: true - name: Rollback Release if: failure() - uses: author/action-rollback@stable + uses: author/action-rollback@1.0.4 with: - # Using a known release ID - id: ${{ steps.create_release.id }} - # Using a tag name + release_id: ${{ steps.create_release.outputs.id }} tag: ${{ github.ref }} - # Always delete} the tag, even if a release is not associated with it. - always_delete_tag: true + delete_orphan_tag: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml new file mode 100644 index 0000000..52c49fd --- /dev/null +++ b/.github/workflows/spellcheck.yml @@ -0,0 +1,17 @@ +name: Spellcheck + +on: + push: + branches: + - "master" + pull_request: + workflow_dispatch: + +jobs: + build: + name: Spellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: rojopolis/spellcheck-github-actions@0.40.0 + name: Spellcheck diff --git a/.gitignore b/.gitignore index 1f1025f..dfb6730 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea -.DS_Store \ No newline at end of file +.DS_Store +deploy +node_modules diff --git a/.redocly.yml b/.redocly.yml new file mode 100644 index 0000000..c2b5106 --- /dev/null +++ b/.redocly.yml @@ -0,0 +1,7 @@ +extends: + - recommended +rules: + no-unused-components: error + operation-4xx-response: off + operation-tag-defined: error + security-defined: off diff --git a/.spectral.yml b/.spectral.yml deleted file mode 100644 index e60e786..0000000 --- a/.spectral.yml +++ /dev/null @@ -1,41 +0,0 @@ -extends: [["spectral:oas", "all"]] -formats: ["oas3"] -rules: - operation-singular-tag: off - oas3-parameter-description: off - contact-properties: off - operation-tags: error - openapi-tags-alphabetical: error - operation-tag-defined: error - paths-snake-case: - description: All YAML paths MUST follow snake-case - severity: error - recommended: true - message: "path is not snake-case: {{error}}" - given: $.paths[*]~ - then: - function: pattern - functionOptions: - match: "^\/([a-z0-9]+(_[a-z0-9]+)*)?(\/[a-z0-9]+(_[a-z0-9]+)*|\/{.+})*$" - parameters-snake-case-alphanumeric: - description: Path parameters MUST follow snake case - severity: error - recommended: true - message: "{{property}} parameter is not snake case: {{error}}" - given: $..parameters[?(@.in == 'path' || @.in == 'query')].name - then: - function: pattern - functionOptions: - match: "^[a-z][_a-z0-9]+$" - - oas3-request-support-json: - description: Every request MUST support `application/json` media type - formats: - - oas3 - recommended: true - severity: error - message: "{{description}}: {{error}}" - given: $.paths.[*].requestBody.content[?(@property.indexOf('json') === -1)]^ - then: - function: falsy - diff --git a/README.md b/README.md index 0d1d911..530a3b3 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ ![CI](https://github.com/ethereum/keymanager-APIs/workflows/CI/badge.svg) [![GitPOAP Badge](https://public-api.gitpoap.io/v1/repo/ethereum/keymanager-APIs/badge)](https://www.gitpoap.io/gh/ethereum/keymanager-APIs) -**_Warning: Super fresh repo, expect rapid iteration and breaking changes_** - Collection of RESTful APIs provided by Ethereum consensus keymanagers API browser: [https://ethereum.github.io/keymanager-APIs/](https://ethereum.github.io/keymanager-APIs/) @@ -55,15 +53,15 @@ edits. ##### Python -``` -python2 -m SimpleHTTPServer 8080 +```sh +python -m http.server 8080 ``` The API spec will render on [http://localhost:8080](http://localhost:8080). ##### NodeJs -``` +```sh npm install simplehttpserver -g # OR @@ -75,38 +73,51 @@ simplehttpserver The API spec will render on [http://localhost:8000](http://localhost:8000). +### Usage + +Local changes will be observable if "dev" is selected in the "Select a definition" drop-down in the web UI. + +Users may need to tick the "Disable Cache" box in their browser's developer tools to see changes after modifying the source. + ## Contributing -The API spec is linted for issues before PRs are merged. +Api spec is checked for lint errors before merge. -To run the linter locally, install `spectral`: +To run lint locally, install linter with -``` -npm install -g @stoplight/spectral +```sh +npm install -g @redocly/cli # OR -yarn global add @stoplight/spectral +yarn global add @redocly/cli ``` -and run with +and run lint with -``` -spectral lint keymanager-oapi.yaml +```sh +redocly lint keymanager-oapi.yaml ``` ## Releasing -1. Create and push a tag +This repository supports both stable and pre-releases. The version of the next release has to be +determined based on the changes in `master` branch since the last stable release. It is recommended +to create a pre-release before releasing a new stable version. - - Make sure info.version in keymanager-oapi.yaml file is updated before tagging. - - CD will create github release and upload bundled spec file +### Stable releases -2. Add release entrypoint in index.html +Steps to create a new stable release: -In SwaggerUIBundle configuration (inside index.html file), add another entry in "urls" field (SwaggerUI will load first item as default). -Entries should be in the following format (replace `` with the real tag name from step 1): +- Create and push a tag with the version of the release, e.g. `v1.1.0` +- CD will create the github release, upload bundled spec files, and open a release PR +- Review, approve and merge the release PR to `master` branch -```javascript - {url: "https://github.com/ethereum/keymanager-APIs/releases/download//keymanager-oapi.yaml", name: ""}, -``` +### Pre-releases + +Steps to create a new pre-release: + +- Create and push a tag with the version of the release, e.g. `v1.1.0-alpha.0` +- CD will create the github release and upload bundled spec files + +Pre-releases will not be listed in `index.html` and are intended to allow early testing against the spec. diff --git a/index.html b/index.html index 99c5d67..3b1c468 100644 --- a/index.html +++ b/index.html @@ -54,8 +54,8 @@ // Begin Swagger UI call region const ui = SwaggerUIBundle({ urls: [ - { url: "https://github.com/ethereum/keymanager-APIs/releases/download/v1.0.0/keymanager-oapi.yaml", name: "v1.0.0" }, - { url: "./keymanager-oapi.yaml", name: "dev" } + {url: "./releases/v1.0.0/keymanager-oapi.json", name: "v1.0.0"}, + {url: "./keymanager-oapi.yaml", name: "dev"} ], basePath: "/", dom_id: "#swagger-ui", diff --git a/keymanager-oapi.yaml b/keymanager-oapi.yaml index f868e5a..009fe9a 100644 --- a/keymanager-oapi.yaml +++ b/keymanager-oapi.yaml @@ -18,7 +18,7 @@ info: of at least 256 bits. If such a parameter is not given, the client SHOULD generate such a token and write it to a file, to be reused across multiple restarts of the binary. If such a parameter is given, but the file or token cannot be read, the client SHOULD treat this as an error: either abort the startup, or show the error and continue without exposing the key manager routes. - version: "v1.0.0" + version: "Dev" contact: name: Ethereum Github url: https://github.com/ethereum/keymanager-APIs/issues @@ -31,7 +31,7 @@ servers: variables: server_url: description: "key manager API url" - default: "https://public-mainnet-node.ethereum.org" + default: "http://localhost/" tags: - name: Fee Recipient diff --git a/spellcheck.yaml b/spellcheck.yaml new file mode 100644 index 0000000..73440d1 --- /dev/null +++ b/spellcheck.yaml @@ -0,0 +1,66 @@ +matrix: + - name: markdown + sources: + - '**/*.md|!node_modules/**' + aspell: + lang: en + d: en_US + ignore-case: true + run-together: true + run-together-min: 2 + run-together-limit: 256 + dictionary: + wordlists: + - wordlist.txt + encoding: utf-8 + pipeline: + - pyspelling.filters.markdown: + - pyspelling.filters.html: + comments: false + ignores: + - code + - pre + - name: schemas + sources: + - 'keymanager-oapi.yaml' + - 'types/**/*.yaml' + - 'apis/**/*.yaml' + aspell: + lang: en + d: en_US + ignore-case: true + run-together: true + run-together-min: 2 + run-together-limit: 256 + dictionary: + wordlists: + - wordlist.txt + encoding: utf-8 + pipeline: + - pyspelling.filters.url: + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: '' + content: 0x[a-fA-F0-9]+ + close: '' + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: 'operationId:.*' + close: '$' + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: 'example:.*' + close: '$' + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: 'title:.*' + close: '$' + - pyspelling.filters.context: + context_visible_first: true + delimiters: + - open: 'data:.*' + close: '$' diff --git a/wordlist.txt b/wordlist.txt new file mode 100644 index 0000000..a7c870e --- /dev/null +++ b/wordlist.txt @@ -0,0 +1,20 @@ +eth +JSON +EIP +https +prysmaticlabs +UI +RPC +natively +VC +Teku +NodeJs +npm +dev +cli +redocly +pre +uint +VPN +BLS +oapi