git.iko.soy/typeable/compaREST
on db716ee help sign in
.github/actions/common_setup/action.yaml+2−2
since splitsnapshots
unifiedsplit
@@ -30,13 +30,13 @@ runs:
30 fi
30 fi
31
31
32 - name: Install Nix
32 - name: Install Nix
33− uses: cachix/install-nix-action@v27
33+ uses: cachix/install-nix-action@v16
34 with:
34 with:
35 extra_nix_config: |
35 extra_nix_config: |
36 system-features = kvm
36 system-features = kvm
37 trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
37 trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
38 substituters = https://hydra.iohk.io https://cache.nixos.org/
38 substituters = https://hydra.iohk.io https://cache.nixos.org/
39− - uses: cachix/cachix-action@v15
39+ - uses: cachix/cachix-action@v10
40 with:
40 with:
41 name: typeable
41 name: typeable
42 authToken: "${{ inputs.authToken }}"
42 authToken: "${{ inputs.authToken }}"
.github/workflows/github-actions-image.yaml+81−60
@@ -9,23 +9,23 @@ on:
9 types: [prereleased]
9 types: [prereleased]
10
10
11jobs:
11jobs:
12−# check-formatting:
12+ check-formatting:
13−# name: Check Haskell formatting
13+ name: Check Haskell formatting
14−# runs-on: ubuntu-latest
14+ runs-on: ubuntu-latest
15−# steps:
15+ steps:
16−# - uses: actions/checkout@v2
16+ - uses: actions/checkout@v2
17−#
18−# - name: Common setup
19−# uses: ./.github/actions/common_setup
20−# with:
21−# authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
22−#
23−# - name: Run fourmolu
24−# run: |
25−# nix-shell nix/ci.nix -j auto --run "git ls-files '*.hs' | xargs fourmolu -m inplace -o -XRecursiveDo -o -XTypeApplications -o -XPatternSynonyms -o -XBangPatterns"
26−# git diff --exit-code
27
17
28− check_versions:
18+ - name: Common setup
19+ uses: ./.github/actions/common_setup
20+ with:
21+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
22+
23+ - name: Run fourmolu
24+ run: |
25+ nix-shell nix/ci.nix -j auto --run "git ls-files '*.hs' | xargs fourmolu -m inplace -o -XRecursiveDo -o -XTypeApplications -o -XPatternSynonyms -o -XBangPatterns"
26+ git diff --exit-code
27+
28+ policeman:
29 runs-on: ubuntu-latest
29 runs-on: ubuntu-latest
30 steps:
30 steps:
31 - uses: actions/checkout@v2
31 - uses: actions/checkout@v2
@@ -37,6 +37,25 @@ jobs:
37 with:
37 with:
38 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
38 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
39
39
40+ - name: Run policeman
41+ run: |
42+ jq --argjson msg "$( $(nix-build ci/policeman.nix)/bin/policeman | grep -v "⚙" | jq -aRs . )" ".[0].message = \$msg" <policeman.json >message.json
43+ cat message.json
44+
45+ - name: Post notice
46+ uses: yuzutech/annotations-action@v0.4.0
47+ with:
48+ title: 👮 Policeman
49+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
50+ input: "./message.json"
51+
52+ check_versions:
53+ runs-on: ubuntu-latest
54+ steps:
55+ - uses: actions/checkout@v2
56+ with:
57+ submodules: recursive
58+
40 - name: Check library version
59 - name: Check library version
41 if: github.event_name == 'release'
60 if: github.event_name == 'release'
42 run: |
61 run: |
@@ -108,6 +127,13 @@ jobs:
108 name: compaREST Docker Image
127 name: compaREST Docker Image
109 path: compaREST-image.tar.gz
128 path: compaREST-image.tar.gz
110
129
130+ - name: Install skopeo
131+ if: github.event_name == 'release'
132+ shell: bash
133+ run: |
134+ sudo apt-get -y update
135+ sudo apt-get -y install skopeo
136+
111 - name: Login to DockerHub
137 - name: Login to DockerHub
112 uses: docker/login-action@v1.10.0
138 uses: docker/login-action@v1.10.0
113 with:
139 with:
@@ -159,18 +185,13 @@ jobs:
159 tag: ${{ github.ref }}
185 tag: ${{ github.ref }}
160
186
161 dist:
187 dist:
162− needs: [check_versions, Linux]
188+ needs: check_versions
163 runs-on: ubuntu-latest
189 runs-on: ubuntu-latest
164 steps:
190 steps:
165 - uses: actions/checkout@v2
191 - uses: actions/checkout@v2
166 with:
192 with:
167 submodules: recursive
193 submodules: recursive
168
194
169− - name: Common setup
170− uses: ./.github/actions/common_setup
171− with:
172− authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
173−
174 - name: Cache
195 - name: Cache
175 uses: actions/cache@v1
196 uses: actions/cache@v1
176 with:
197 with:
@@ -189,7 +210,7 @@ jobs:
189
210
190 - name: Build dist
211 - name: Build dist
191 run: |
212 run: |
192− stack sdist --pvp-bounds both
213+ stack sdist --pvp-bounds both --test-tarball
193 echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
214 echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
194
215
195 - name: Upload compaREST sources artifact
216 - name: Upload compaREST sources artifact
@@ -213,7 +234,7 @@ jobs:
213 env:
234 env:
214 HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
235 HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
215 run: |
236 run: |
216− stack upload --pvp-bounds both --candidate .
237+ stack upload --pvp-bounds both --test-tarball --candidate .
217
238
218 macOS:
239 macOS:
219 needs: check_versions
240 needs: check_versions
@@ -252,39 +273,39 @@ jobs:
252 file: compaREST-macOS-x86.zip
273 file: compaREST-macOS-x86.zip
253 tag: ${{ github.ref }}
274 tag: ${{ github.ref }}
254
275
255−# Linux-Windows:
276+ Linux-Windows:
256−# needs: check_versions
277+ needs: check_versions
257−# runs-on: ubuntu-latest
278+ runs-on: ubuntu-latest
258−# steps:
279+ steps:
259−# - uses: actions/checkout@v2
280+ - uses: actions/checkout@v2
260−# with:
281+ with:
261−# submodules: recursive
282+ submodules: recursive
262−#
283+
263−# - name: Common setup
284+ - name: Common setup
264−# uses: ./.github/actions/common_setup
285+ uses: ./.github/actions/common_setup
265−# with:
286+ with:
266−# authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
287+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
267−#
288+
268−# - name: Build Windows binary
289+ - name: Build Windows binary
269−# run: |
290+ run: |
270−# cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
291+ cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
271−#
292+
272−# - name: Upload Windows compaREST bundle
293+ - name: Upload Windows compaREST bundle
273−# uses: actions/upload-artifact@v2
294+ uses: actions/upload-artifact@v2
274−# with:
295+ with:
275−# name: compaREST binary – Windows
296+ name: compaREST binary – Windows
276−# path: compaREST
297+ path: compaREST
277−#
298+
278−# - name: Zip Release Assets
299+ - name: Zip Release Assets
279−# if: github.event_name == 'release'
300+ if: github.event_name == 'release'
280−# shell: bash
301+ shell: bash
281−# run: |
302+ run: |
282−# zip -r compaREST-Windows.zip compaREST
303+ zip -r compaREST-Windows.zip compaREST
283−#
304+
284−# - name: Upload compaREST binary – Windows to release
305+ - name: Upload compaREST binary – Windows to release
285−# if: github.event_name == 'release'
306+ if: github.event_name == 'release'
286−# uses: svenstaro/upload-release-action@2.2.1
307+ uses: svenstaro/upload-release-action@2.2.1
287−# with:
308+ with:
288−# repo_token: ${{ secrets.GITHUB_TOKEN }}
309+ repo_token: ${{ secrets.GITHUB_TOKEN }}
289−# file: compaREST-Windows.zip
310+ file: compaREST-Windows.zip
290−# tag: ${{ github.ref }}
311+ tag: ${{ github.ref }}
.gitmodulesnew file+3
@@ -0,0 +1,3 @@
1+[submodule "awsm-css"]
2+ path = awsm-css
3+ url = https://github.com/igoradamenko/awsm.css.git
CHANGELOG.md+3−7
@@ -1,13 +1,9 @@
1# Changelog
1# Changelog
2
2
3−`compaREST` uses [PVP Versioning][1].
3+`comparest` uses [PVP Versioning][1].
4
4
5−## 0.1.0.1
5+## 0.0.0.0
6
6
7−* Fixed an issue related to empty commit SHAs in GitHub Actions.
7+* Initially created.
8−
9−## 0.1.0.0
10−
11−* Initial release.
12
8
13[1]: https://pvp.haskell.org
9[1]: https://pvp.haskell.org
LICENSE+1−1
@@ -1,6 +1,6 @@
1MIT License
1MIT License
2
2
3−Copyright (c) 2021 Typeable
3+Copyright (c) 2021 Aleksey Uymanov
4
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
6of this software and associated documentation files (the "Software"), to deal
README.md+19−40
@@ -1,33 +1,14 @@
1−# compaREST
1+# CompaREST
2
2
3−[![Hackage](https://img.shields.io/hackage/v/compaREST.svg?logo=haskell)](https://hackage.haskell.org/package/compaREST)
3+[![Hackage](https://img.shields.io/hackage/v/comparest.svg?logo=haskell)](https://hackage.haskell.org/package/comparest)
4+[![Stackage Lts](http://stackage.org/package/comparest/badge/lts)](http://stackage.org/lts/package/comparest)
5+[![Stackage Nightly](http://stackage.org/package/comparest/badge/nightly)](http://stackage.org/nightly/package/comparest)
4[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
7
6Compatibility checker for OpenAPI
8Compatibility checker for OpenAPI
9+# Quick Start Guide
7
10
8−## Using compaREST in Github Actions
9−
10−Add the following step to your Github Actions workflow:
11−
12−```yaml
13−- uses: typeable/comparest
14− if: ${{ github.event_name == 'pull_request' }}
15− with:
16− old: old-openapi.yaml
17− new: new-openapi.yaml
18−```
19−
20−The `new` and `old` values should be paths to your OpenAPI specifications you want to compare.
21−
22−You will get something like this in your pull requests:
23−
24−![](docs/img/github-action-report.png)
25−
26−For more detail please see our [integration guide](docs/Integration_guide.md).
27−
28−## An example
29−
30−### Your situation
11+## Your situation
31
12
32You are developing a very important server with a REST API. You have clients who use your API that you do not control. Say, you are also developing a mobile app that uses your API and you can't force someone to update to the latest version. (Or you prefer not to for UX reasons.)
13You are developing a very important server with a REST API. You have clients who use your API that you do not control. Say, you are also developing a mobile app that uses your API and you can't force someone to update to the latest version. (Or you prefer not to for UX reasons.)
33
14
@@ -94,7 +75,7 @@ components:
94 $ref: "#/components/schemas/Pet"
75 $ref: "#/components/schemas/Pet"
95```
76```
96
77
97−### Evolving your product
78+## Evolving your product
98
79
99Enthused over your initial success you hurry to release a new and improved version of your API and mobile app.
80Enthused over your initial success you hurry to release a new and improved version of your API and mobile app.
100
81
@@ -163,7 +144,7 @@ components:
163
144
164Looking at the very large and complex API description, you grow more and more concerned that your old mobile app might stop working when you update the server. But the spec is too large and too complex to reasonably assess this manually.
145Looking at the very large and complex API description, you grow more and more concerned that your old mobile app might stop working when you update the server. But the spec is too large and too complex to reasonably assess this manually.
165
146
166−### Assessing compatibility automatically
147+## Assessing compatibility automatically
167
148
168Luckily, you have access to compaREST which can programmatically analyze your APIs and determine what, if anything, breaks compatibility and what doesn't.
149Luckily, you have access to compaREST which can programmatically analyze your APIs and determine what, if anything, breaks compatibility and what doesn't.
169
150
@@ -177,15 +158,15 @@ Running this command will output a file `report.md`, containing the compatibilit
177
158
178> # Summary
159> # Summary
179>
160>
180−> | [❌ Breaking changes](#breaking-changes) | [⚠️ Non-breaking changes](#non-breaking-changes) |
161+> | [⚠️ Breaking changes](#breaking-changes) | [🙆 Non-breaking changes](#non-breaking-changes) | 🤷 Unsupported feature changes |
181−> |------------------------------------------|--------------------------------------------------|
162+> |------------------------------------------|-------------------------------------------------|-------------------------------|
182−> | 5 | 6 |
163+> | 5 | 6 | 0 |
183>
164>
184−> # <span id="breaking-changes"></span>❌ Breaking changes
165+> # <span id="breaking-changes"></span>⚠️ Breaking changes
185>
166>
186> ## **GET** /pets
167> ## **GET** /pets
187>
168>
188−> ### ⬅️☁️ JSON Response – 200
169+> ### 📱⬅️ JSON Response – 200
189>
170>
190> #### `$[*].name(String)`
171> #### `$[*].name(String)`
191>
172>
@@ -195,7 +176,7 @@ Running this command will output a file `report.md`, containing the compatibilit
195>
176>
196> ## **POST** /pets
177> ## **POST** /pets
197>
178>
198−> ### ➡️☁️ JSON Request
179+> ### 📱➡️ JSON Request
199>
180>
200> #### `$.weight`
181> #### `$.weight`
201>
182>
@@ -210,7 +191,7 @@ Running this command will output a file `report.md`, containing the compatibilit
210>
191>
211> Value is now a multiple of 1.0.
192> Value is now a multiple of 1.0.
212>
193>
213−> # <span id="non-breaking-changes"></span>⚠️ Non-breaking changes
194+> # <span id="non-breaking-changes"></span>🙆 Non-breaking changes
214>
195>
215> ## **GET** /pets
196> ## **GET** /pets
216>
197>
@@ -222,7 +203,7 @@ Running this command will output a file `report.md`, containing the compatibilit
222>
203>
223> Upper bound changed from 20.0 inclusive to 30.0 inclusive.
204> Upper bound changed from 20.0 inclusive to 30.0 inclusive.
224>
205>
225−> ### ⬅️☁️ JSON Response – 200
206+> ### 📱⬅️ JSON Response – 200
226>
207>
227> #### `$[*].weight`
208> #### `$[*].weight`
228>
209>
@@ -239,7 +220,7 @@ Running this command will output a file `report.md`, containing the compatibilit
239>
220>
240> ## **POST** /pets
221> ## **POST** /pets
241>
222>
242−> ### ➡️☁️ JSON Request
223+> ### 📱➡️ JSON Request
243>
224>
244> #### `$.name(String)`
225> #### `$.name(String)`
245>
226>
@@ -249,7 +230,7 @@ Running this command will output a file `report.md`, containing the compatibilit
249
230
250You now know exactly in what situations and in what way your 1.0 version of the app will break if you deploy your 1.1 version of the server.
231You now know exactly in what situations and in what way your 1.0 version of the app will break if you deploy your 1.1 version of the server.
251
232
252−### Additional formats
233+## Additional formats
253
234
254You can also produce a self-contained HTML report that you can open in your browser by simply omitting the file extension of the output file:
235You can also produce a self-contained HTML report that you can open in your browser by simply omitting the file extension of the output file:
255
236
@@ -257,9 +238,7 @@ You can also produce a self-contained HTML report that you can open in your brow
257docker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report
238docker run --rm -v $(pwd):/data:rw typeable/comparest --client /data/api-1.0.0.yaml --server /data/api-1.1.0.yaml --output /data/report
258```
239```
259
240
260−## CLI docs
241+# CLI docs
261−
262−For more detail please see our [user guide](docs/User_guide.md).
263
242
264```
243```
265Usage: comparest (-c|--client ARG) (-s|--server ARG)
244Usage: comparest (-c|--client ARG) (-s|--server ARG)
action.yaml+8−9
@@ -7,22 +7,21 @@ inputs:
7 default: "${{ github.token }}"
7 default: "${{ github.token }}"
8 required: false
8 required: false
9 repo:
9 repo:
10− description: The owner of the repo in which to post the results.
10+ description: The owner of the repo in which to post the comment.
11 default: "${{ github.repository }}"
11 default: "${{ github.repository }}"
12 required: false
12 required: false
13 project_name:
13 project_name:
14− description: The name of the project to which the API pertains. Used to name the check. Useful when you have multiple APIs in the same repo.
14+ description: The name of the project to which the API pertains.
15− required: false
15+ required: true
16− default: ""
17 footer:
16 footer:
18− description: A footer that can be appended to the check body.
17+ description: A footer that can be appended to the comment.
19 required: false
18 required: false
20 default: ""
19 default: ""
21 old:
20 old:
22− description: The path to the old (client) specification of the API.
21+ description: The path to old specification of the API.
23 required: true
22 required: true
24 new:
23 new:
25− description: The path to new (server) specification of the API.
24+ description: The path to new specification of the API.
26 required: true
25 required: true
27 sha:
26 sha:
28 description: The sha of the commit to post the check for.
27 description: The sha of the commit to post the check for.
@@ -30,7 +29,7 @@ inputs:
30 default: "${{ github.event.pull_request.head.sha }}"
29 default: "${{ github.event.pull_request.head.sha }}"
31runs:
30runs:
32 using: "docker"
31 using: "docker"
33− image: "docker://typeable/comparest-github-action:0.1.0.1"
32+ image: "docker://typeable/comparest-github-action:latest"
34 env:
33 env:
35 GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
34 GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
36 REPO: "${{ inputs.repo }}"
35 REPO: "${{ inputs.repo }}"
@@ -45,4 +44,4 @@ runs:
45
44
46branding:
45branding:
47 icon: crosshair
46 icon: crosshair
48− color: blue
47+ color: gray-dark
app/Data/OpenApi/Compare/Options.hs−1
@@ -9,7 +9,6 @@ import Data.OpenApi.Compare.Report
9import GHC.Generics (Generic)
9import GHC.Generics (Generic)
10import Options.Applicative
10import Options.Applicative
11import Options.Applicative.Help hiding (fullDesc)
11import Options.Applicative.Help hiding (fullDesc)
12−import Text.PrettyPrint.ANSI.Leijen ((<$$>),string)
13
12
14parseOptions :: IO Options
13parseOptions :: IO Options
15parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
14parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
app/Main.hs−1
@@ -2,7 +2,6 @@ module Main (main) where
2
2
3import Control.Monad
3import Control.Monad
4import Control.Monad.Except
4import Control.Monad.Except
5−import Control.Monad.Trans (lift)
6import Data.Aeson
5import Data.Aeson
7import qualified Data.ByteString.Lazy as BSL
6import qualified Data.ByteString.Lazy as BSL
8import Data.Default
7import Data.Default
awsm-cssnew file+1

Submodule changed.

compaREST.cabal+4−6
@@ -1,6 +1,6 @@
1cabal-version: 2.4
1cabal-version: 2.4
2name: compaREST
2name: compaREST
3−version: 0.1.0.1
3+version: 0.0.0.0
4synopsis: Compatibility checker for OpenAPI
4synopsis: Compatibility checker for OpenAPI
5description: Compatibility checker for OpenAPI.
5description: Compatibility checker for OpenAPI.
6license: MIT
6license: MIT
@@ -12,8 +12,8 @@ category: Web
12build-type: Simple
12build-type: Simple
13extra-doc-files: README.md
13extra-doc-files: README.md
14 CHANGELOG.md
14 CHANGELOG.md
15−tested-with: GHC == 9.6
15+tested-with: GHC == 8.10.4
16−extra-source-files: css/awsm.min.css
16+extra-source-files: awsm-css/dist/awsm.min.css
17extra-source-files:
17extra-source-files:
18 test/golden/**/*.yaml
18 test/golden/**/*.yaml
19 test/golden/**/*.md
19 test/golden/**/*.md
@@ -26,14 +26,13 @@ common common-options
26 -Wno-safe
26 -Wno-safe
27 -Wno-prepositive-qualified-module
27 -Wno-prepositive-qualified-module
28 -Wno-missing-import-lists
28 -Wno-missing-import-lists
29− -Wno-missing-kind-signatures
30 -Wno-partial-fields
29 -Wno-partial-fields
31 -Wno-all-missed-specialisations
30 -Wno-all-missed-specialisations
32 -Wno-missing-local-signatures
31 -Wno-missing-local-signatures
33 -Wno-unsafe
32 -Wno-unsafe
34 -fconstraint-solver-iterations=0
33 -fconstraint-solver-iterations=0
35 default-language: Haskell2010
34 default-language: Haskell2010
36− build-depends: base >= 4.12.0.0 && < 5
35+ build-depends: base >= 4.12.0.0 && < 4.16
37 , text
36 , text
38
37
39
38
@@ -166,7 +165,6 @@ executable compaREST
166 , containers
165 , containers
167 , doctemplates
166 , doctemplates
168 , pandoc-types
167 , pandoc-types
169− , prettyprinter-compat-ansi-wl-pprint
170 ghc-options: -threaded
168 ghc-options: -threaded
171 -rtsopts
169 -rtsopts
172 -with-rtsopts=-N
170 -with-rtsopts=-N
css/awsm.min.cssdeleted−1
@@ -1 +0,0 @@
1−@charset "UTF-8";html{font-family:"PT Serif",Georgia,serif;font-size:100%;line-height:1.6;background:#fff;color:#000;-webkit-overflow-scrolling:touch}body{margin:1em;font-size:1rem}@media (min-width:20rem){body{font-size:calc(1rem + .0125*(100vw - 20rem))}}@media (min-width:40rem){body{font-size:1.25rem}}body article,body footer,body header,body main{position:relative;max-width:40rem;margin:0 auto}body>header{margin-bottom:3.5em}body>header h1{margin:0;font-size:1.5em}body>header p{margin:0;font-size:.85em}body>footer{margin-top:4.5em;padding-bottom:1.5em;text-align:center;font-size:.8rem;color:#aaa}details,nav,p{margin:1em 0}nav ul{list-style:none;margin:0;padding:0}nav li{display:inline-block;margin-right:1em;margin-bottom:.25em}nav a:visited{color:#0064c1}article header h1 a:visited:hover,article header h2 a:visited:hover,nav a:hover{color:#3000c1}ol,ul{margin-top:0;padding-top:0;padding-left:2.5em}p{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}aside:first-child,p:first-child{margin-top:0}aside:last-child,p:last-child{margin-bottom:0}p+ol,p+ul{margin-top:-.75em}p img,p picture{float:right;margin-bottom:.5em;margin-left:.5em}p picture img{float:none;margin:0}blockquote,dd{padding-left:2.5em}dd{margin-bottom:1em;margin-left:0}dt{font-weight:700}blockquote{margin:0}aside{margin:.5em 0;font-style:italic;color:#aaa}@media (min-width:65rem){aside{position:absolute;right:-12.5rem;width:9.375rem;max-width:9.375rem;margin:0;padding-left:.5em;font-size:.8em;border-left:1px solid #f2f2f2}}section+section{margin-top:2em}h1,h2,h3,h4,h5,h6{margin:1.25em 0 0;line-height:1.2}h1:focus>a[href^="#"][id],h1:hover>a[href^="#"][id],h2:focus>a[href^="#"][id],h2:hover>a[href^="#"][id],h3:focus>a[href^="#"][id],h3:hover>a[href^="#"][id],h4:focus>a[href^="#"][id],h4:hover>a[href^="#"][id],h5:focus>a[href^="#"][id],h5:hover>a[href^="#"][id],h6:focus>a[href^="#"][id],h6:hover>a[href^="#"][id]{opacity:1;transition:opacity 0s,color 300ms ease-out}figure+p,h1+details,h1+p,h2+details,h2+p,h3+details,h3+p,h4+details,h4+p,h5+details,h5+p,h6+details,h6+p{margin-top:.5em}h1>a[href^="#"][id],h2>a[href^="#"][id],h3>a[href^="#"][id],h4>a[href^="#"][id],h5>a[href^="#"][id],h6>a[href^="#"][id]{position:absolute;left:-.5em;opacity:0;background:0 0;color:rgba(0,0,0,.5);transition:opacity 300ms ease-out}h1>a[href^="#"][id]:focus,h1>a[href^="#"][id]:hover,h1>a[href^="#"][id]:target,h2>a[href^="#"][id]:focus,h2>a[href^="#"][id]:hover,h2>a[href^="#"][id]:target,h3>a[href^="#"][id]:focus,h3>a[href^="#"][id]:hover,h3>a[href^="#"][id]:target,h4>a[href^="#"][id]:focus,h4>a[href^="#"][id]:hover,h4>a[href^="#"][id]:target,h5>a[href^="#"][id]:focus,h5>a[href^="#"][id]:hover,h5>a[href^="#"][id]:target,h6>a[href^="#"][id]:focus,h6>a[href^="#"][id]:hover,h6>a[href^="#"][id]:target{opacity:1;box-shadow:none;color:#000;transition:opacity 0s,color 0s}h1>a[href^="#"][id]:target:focus,h2>a[href^="#"][id]:target:focus,h3>a[href^="#"][id]:target:focus,h4>a[href^="#"][id]:target:focus,h5>a[href^="#"][id]:target:focus,h6>a[href^="#"][id]:target:focus{outline:0}h1>a[href^="#"][id]::before,h2>a[href^="#"][id]::before,h3>a[href^="#"][id]::before,h4>a[href^="#"][id]::before,h5>a[href^="#"][id]::before,h6>a[href^="#"][id]::before{content:"•"}h1{font-size:2em}h2{font-size:1.75em}h3{font-size:1.25em}h4{font-size:1.15em}h5,h6{font-size:1em}h6{margin-top:1em;color:#aaa}article+article{margin-top:5em}article header p{font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:.6em;color:#aaa}article header p+h1,article header p+h2{margin-top:-.25em}article header h1+p,article header h2+p{margin-top:.25em}article header h1 a,article header h2 a{color:#000;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(0, 0, 0, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){article header h1 a,article header h2 a{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(0, 0, 0, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}article header h1 a:visited,article header h2 a:visited{color:#aaa;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(170, 170, 170, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){article header h1 a:visited,article header h2 a:visited{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(170, 170, 170, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}article>footer{margin-top:1.5em;font-size:.85em}a,abbr{text-decoration:none}a{color:#0064c1;transition:color 300ms ease-out,box-shadow 300ms ease-out;background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="1"%3E%3Crect x="0" y="0.5" width="1" height="0.5" fill="rgba(0, 100, 193, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}@media screen and (-ms-high-contrast:active),(-ms-high-contrast:none){a{background:url('data:image/svg+xml;charset=utf8,%3Csvg xmlns="http://www.w3.org/2000/svg" width="1" height="2"%3E%3Crect x="0" y="1" width="1" height="1" fill="rgba(0, 100, 193, 0.35)"/%3E%3C/svg%3E') left bottom repeat-x}}a:visited{color:#80b2e0}a:active,a:hover{outline-width:0}a:hover{box-shadow:inset 0 -1px #3000c1;color:#3000c1;transition:color 0s,box-shadow 0s}abbr{margin-right:-.075em;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none;letter-spacing:.075em;font-size:.9em;border-bottom:1px dotted}img,picture{display:block;max-width:100%;margin:0 auto}audio,video{width:100%;max-width:100%}video{-o-object-position:0 -1px;object-position:0 -1px}figure{margin:1em 0 .5em;padding:0}figure figcaption{opacity:.65;font-size:.85em}table{display:inline-block;border-spacing:0;border-collapse:collapse;overflow-x:auto;max-width:100%;text-align:left;vertical-align:top;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}table caption{font-size:.9em;background:#fff}table td,table th{padding:.35em .75em;vertical-align:top;font-size:.9em;border:1px solid #f2f2f2;border-top:0;border-left:0}table td:first-child,table th:first-child{padding-left:0;background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%);background-size:2px 100%;background-repeat:no-repeat}table td:last-child,table th:last-child{padding-right:0;border-right:0;background-image:linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:100% 0;background-size:2px 100%;background-repeat:no-repeat}table td:only-child,table th:only-child{background-image:linear-gradient(to right,#fff 50%,rgba(255,255,255,0) 100%),linear-gradient(to left,#fff 50%,rgba(255,255,255,0) 100%);background-position:0 0,100% 0;background-size:2px 100%,2px 100%;background-repeat:no-repeat,no-repeat}table th{line-height:1.2}code,kbd,samp,var{font-family:Consolas,"Lucida Console",Monaco,monospace;font-style:normal}pre{overflow-x:auto;font-size:.8em;background:linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 0 0,linear-gradient(rgba(0,0,0,.15) 0%,rgba(0,0,0,.15) 100%) 100% 0;background-attachment:scroll,scroll;background-size:1px 100%,1px 100%;background-repeat:no-repeat,no-repeat}pre>code,summary{display:inline-block}pre>code{overflow-x:visible;box-sizing:border-box;min-width:100%;border-right:3px solid #fff;border-left:1px solid #fff}hr{height:1px;margin:2em 0;border:0;background:#f2f2f2}details[open]{padding-bottom:.5em;border-bottom:1px solid #f2f2f2}summary{font-weight:700;border-bottom:1px dashed;cursor:pointer}summary::-webkit-details-marker{display:none}noscript{color:#d00000}::selection{background:rgba(0,100,193,.15)}
default.nix+7−18
@@ -1,13 +1,11 @@
1{ sources ? import ./nix/sources.nix
1{ sources ? import ./nix/sources.nix
2, haskellNix ? import sources.haskellNix { inherit system; }
2, haskellNix ? import sources.haskellNix { inherit system; }
3−, pkgs ? import haskellNix.sources.nixpkgs-2311 (haskellNix.nixpkgsArgs // { inherit system; })
3+, pkgs ? import haskellNix.sources.nixpkgs-2105 (haskellNix.nixpkgsArgs // { inherit system; })
4, system ? builtins.currentSystem
4, system ? builtins.currentSystem
5, nix-filter ? import sources.nix-filter
5, nix-filter ? import sources.nix-filter
6}:
6}:
7let
7let
8 masterPkgs = import sources.nixpkgs { inherit system; };
8 masterPkgs = import sources.nixpkgs { inherit system; };
9− yq = import ./nix/yq.nix { pkgs = masterPkgs; };
10− diffYaml = import ./nix/diff-yaml.nix { pkgs = masterPkgs; };
11
9
12 hsPkgs = pkgs.haskell-nix.stackProject {
10 hsPkgs = pkgs.haskell-nix.stackProject {
13 src = nix-filter {
11 src = nix-filter {
@@ -40,7 +38,7 @@ let
40 (inDirectory ./src)
38 (inDirectory ./src)
41 (inDirectory ./app)
39 (inDirectory ./app)
42 (inDirectory ./github-action)
40 (inDirectory ./github-action)
43− ./css/awsm.min.css
41+ ./awsm-css/dist/awsm.min.css
44 ./LICENSE
42 ./LICENSE
45 ];
43 ];
46 };
44 };
@@ -99,18 +97,6 @@ let
99 };
97 };
100
98
101 WindowsCompaRESTBin = hsPkgs.projectCross.mingwW64.hsPkgs.compaREST.components.exes.compaREST;
99 WindowsCompaRESTBin = hsPkgs.projectCross.mingwW64.hsPkgs.compaREST.components.exes.compaREST;
102−
103− # We use the static version so that we don't have to rebuild everything on CI.
104− # The only binaries build on CI are static.
105− test = hsPkgs.projectCross.musl64.hsPkgs.compaREST.components.tests.compaREST-tests.overrideAttrs (final: old: {
106− buildInputs = old.buildInputs ++ [ diffYaml yq ];
107− nativeBuildInputs = old.nativeBuildInputs ++ (with masterPkgs; [ makeWrapper ]);
108−
109− postInstall = ''
110− wrapProgram $out/bin/compaREST-tests \
111− --prefix PATH : ${masterPkgs.lib.makeBinPath [ diffYaml yq ]}
112− '';
113− });
114in
100in
115{
101{
116 inherit
102 inherit
@@ -120,6 +106,9 @@ in
120 compaRESTBin
106 compaRESTBin
121 hsPkgs
107 hsPkgs
122 macOSCompaRESTBundle
108 macOSCompaRESTBundle
123− WindowsCompaRESTBin
109+ WindowsCompaRESTBin;
124− test;
110+
111+ # We use the static version so that we don't have to rebuild everything on CI.
112+ # The only binaries build on CI are static.
113+ test = hsPkgs.projectCross.musl64.hsPkgs.compaREST.components.tests.compaREST-tests;
125}
114}
docs/Integration_guide.md+2
@@ -28,6 +28,8 @@ In our example we have already generated the two OpenAPI specs and placed them i
28
28
29We can now run our action:
29We can now run our action:
30
30
31+##### NOTE: will only work after public release
32+
31```yaml
33```yaml
32- uses: typeable/comparest
34- uses: typeable/comparest
33 with:
35 with:
docs/Releasing.mddeleted−15
@@ -1,15 +0,0 @@
1−# The release procedure
2−
3−1. Update the version number everywhere:
4− 1. Version in [compaREST.cabal](../compaREST.cabal)
5− 2. Docker tag in [action.yaml](../action.yaml)
6− 3. Set the version of unreleased changes in [CHANGELOG.md](../CHANGELOG.md)
7−2. Publish!
8− 1. Create a pre-release on GitHub:
9− ![](img/pre-release.png)
10− 2. This will automatically start the release procedure. You can check the state of it in the "Actions" tab on GitHub:
11− ![](img/pre-release-ci.png)
12− 3. If everything goes as planned, the release action should pass and all assets should be added to the release:
13− ![](img/pre-release-artifacts.png)
14− 4. The new version should be automatically uploaded a release candidate to [Hackage](https://hackage.haskell.org/package/compaREST/candidates/). Make sure everything looks okay and publish it.
15− 5. Go to the Releases tab on GitHub and edit the release to make it not a "pre-release".
docs/img/pre-release-artifacts.pngdeleted

Binary file not shown.

docs/img/pre-release-ci.pngdeleted

Binary file not shown.

docs/img/pre-release.pngdeleted

Binary file not shown.

github-action/CompaREST/GitHub/API.hs+2−2
@@ -29,7 +29,7 @@ postStatusProcessing = do
29 repoOwner
29 repoOwner
30 repoName
30 repoName
31 Check
31 Check
32− { checkName = mkName Proxy checkName
32+ { checkName = mkName Proxy $ "compaREST – " <> projectName
33 , checkSha = sha
33 , checkSha = sha
34 , checkDetailsURL = Nothing
34 , checkDetailsURL = Nothing
35 , checkExternalId = Nothing
35 , checkExternalId = Nothing
@@ -60,7 +60,7 @@ postStatus x = do
60 repoOwner
60 repoOwner
61 repoName
61 repoName
62 Check
62 Check
63− { checkName = mkName Proxy checkName
63+ { checkName = mkName Proxy $ "compaREST – " <> projectName
64 , checkSha = sha
64 , checkSha = sha
65 , checkDetailsURL = Nothing
65 , checkDetailsURL = Nothing
66 , checkExternalId = Nothing
66 , checkExternalId = Nothing
github-action/CompaREST/GitHub/Action/Config.hs+3−7
@@ -8,14 +8,13 @@ import Data.Text (Text)
8import qualified Data.Text as T
8import qualified Data.Text as T
9import qualified GitHub as GH
9import qualified GitHub as GH
10
10
11−import Data.Functor
12import System.Envy
11import System.Envy
13
12
14data Config = Config
13data Config = Config
15 { githubToken :: GH.Auth
14 { githubToken :: GH.Auth
16 , repoOwner :: GH.Name GH.Owner
15 , repoOwner :: GH.Name GH.Owner
17 , repoName :: GH.Name GH.Repo
16 , repoName :: GH.Name GH.Repo
18− , checkName :: Text
17+ , projectName :: Text
19 , footerText :: Text
18 , footerText :: Text
20 , root :: FilePath
19 , root :: FilePath
21 , sha :: GH.Name GH.Commit
20 , sha :: GH.Name GH.Commit
@@ -28,10 +27,7 @@ instance FromEnv Config where
28 T.split (== '/') <$> env "REPO" >>= \case
27 T.split (== '/') <$> env "REPO" >>= \case
29 [owner, name] -> pure (owner, name)
28 [owner, name] -> pure (owner, name)
30 _ -> fail "malformed repo"
29 _ -> fail "malformed repo"
31− checkName <-
32− envMaybe "PROJECT_NAME" <&> \case
30+ projectName <- env "PROJECT_NAME"
33− Just pName | not . T.null . T.strip $ pName -> "compaREST – " <> pName
34− _ -> "compaREST"
35 footerText <- env "FOOTER"
31 footerText <- env "FOOTER"
36 root <- envMaybe "ROOT" .!= "."
32 root <- envMaybe "ROOT" .!= "."
37 sha <- env "SHA"
33 sha <- env "SHA"
@@ -40,7 +36,7 @@ instance FromEnv Config where
40 { githubToken = token
36 { githubToken = token
41 , repoOwner = GH.mkName Proxy owner
37 , repoOwner = GH.mkName Proxy owner
42 , repoName = GH.mkName Proxy repo
38 , repoName = GH.mkName Proxy repo
43− , checkName = checkName
39+ , projectName = projectName
44 , footerText = footerText
40 , footerText = footerText
45 , root = root
41 , root = root
46 , sha = GH.mkName Proxy sha
42 , sha = GH.mkName Proxy sha
github-action/Main.hs+7−13
@@ -9,7 +9,6 @@ import Control.Monad.Freer.GitHub
9import Control.Monad.Freer.Reader
9import Control.Monad.Freer.Reader
10import Data.OpenApi.Compare.Run
10import Data.OpenApi.Compare.Run
11import Data.Text (Text)
11import Data.Text (Text)
12−import qualified Data.Text as T
13import qualified Data.Yaml.Aeson as Yaml
12import qualified Data.Yaml.Aeson as Yaml
14import qualified GitHub as GH
13import qualified GitHub as GH
15import System.Environment
14import System.Environment
@@ -23,18 +22,13 @@ import Text.Pandoc.Writers
23main :: IO ()
22main :: IO ()
24main = do
23main = do
25 cfg <- decodeEnv >>= either error pure
24 cfg <- decodeEnv >>= either error pure
26− case sha cfg of
27− x | T.null . T.strip . GH.untagName $ x -> do
28− putStrLn "SHA not specified. Exiting without doing anything."
29− pure ()
30− _ ->
31− getArgs >>= \case
25+ getArgs >>= \case
32− ["pre"] -> runPre cfg
26+ ["pre"] -> runPre cfg
33− ["run"] -> do
27+ ["run"] -> do
34− oldFile <- getEnv "OLD"
28+ oldFile <- getEnv "OLD"
35− newFile <- getEnv "NEW"
29+ newFile <- getEnv "NEW"
36− runRun cfg (root cfg </> oldFile) (root cfg </> newFile)
30+ runRun cfg (root cfg </> oldFile) (root cfg </> newFile)
37− _ -> error "Invalid arguments."
31+ _ -> error "Invalid arguments."
38
32
39runner :: Config -> Eff '[GitHub, Error GH.Error, Reader Config, IO] a -> IO a
33runner :: Config -> Eff '[GitHub, Error GH.Error, Reader Config, IO] a -> IO a
40runner cfg =
34runner cfg =
nix/ci.nix+1−6
@@ -1,11 +1,6 @@
1{ sources ? import ./sources.nix
1{ sources ? import ./sources.nix
2, pkgs ? import sources.nixpkgs { }
2, pkgs ? import sources.nixpkgs { }
3}:
3}:
4−
5−let
6− yq = import ./yq.nix { inherit pkgs; };
7− diff-yaml = import ./diff-yaml.nix { inherit pkgs; };
8−in
9pkgs.mkShell {
4pkgs.mkShell {
10− packages = [ pkgs.haskellPackages.fourmolu diff-yaml yq ];
5+ packages = [ pkgs.haskellPackages.fourmolu ];
11}
6}
nix/diff-yaml.nixdeleted−20
@@ -1,20 +0,0 @@
1−{ pkgs ? import <nixpkgs> {} }:
2−
3−let
4− inherit (pkgs) stdenv;
5− yq = import ./yq.nix { inherit pkgs; };
6−in
7−stdenv.mkDerivation {
8− name = "diff-yaml";
9−
10− src = ../scripts/diff-yaml;
11−
12− buildInputs = [ pkgs.bash yq ];
13−
14− phases = [ "installPhase" ];
15−
16− installPhase = ''
17− mkdir -p $out/bin
18− cp $src $out/bin/diff-yaml
19− '';
20−}
nix/shell.nixdeleted−11
@@ -1,11 +0,0 @@
1−{ sources ? import ./sources.nix
2−, pkgs ? import sources.nixpkgs { }
3−}:
4−
5−let
6− patched-yq = import ./yq.nix { inherit pkgs; };
7− diffYaml = import ./diff-yaml.nix { inherit pkgs; };
8−in
9−pkgs.mkShell {
10− buildInputs = with pkgs; [ pkg-config diffYaml patched-yq zlib ];
11−}
nix/sources.json+13−13
@@ -5,10 +5,10 @@
5 "homepage": "https://input-output-hk.github.io/haskell.nix",
5 "homepage": "https://input-output-hk.github.io/haskell.nix",
6 "owner": "input-output-hk",
6 "owner": "input-output-hk",
7 "repo": "haskell.nix",
7 "repo": "haskell.nix",
8− "rev": "d7f95903c84a5a50d6fe0844280da82c3c81680a",
8+ "rev": "c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e",
9− "sha256": "02870rk4sx44lwwa0k20iwdhqcx0ayz34yb3b0qy045p22q45815",
9+ "sha256": "0frzmvz8rhb4vgx20qms9xxqbkmg5pwivis4qis63ny5wxclzb34",
10 "type": "tarball",
10 "type": "tarball",
11− "url": "https://github.com/input-output-hk/haskell.nix/archive/d7f95903c84a5a50d6fe0844280da82c3c81680a.tar.gz",
11+ "url": "https://github.com/input-output-hk/haskell.nix/archive/c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e.tar.gz",
12 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
12 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13 },
13 },
14 "niv": {
14 "niv": {
@@ -17,22 +17,22 @@
17 "homepage": "https://github.com/nmattia/niv",
17 "homepage": "https://github.com/nmattia/niv",
18 "owner": "nmattia",
18 "owner": "nmattia",
19 "repo": "niv",
19 "repo": "niv",
20− "rev": "f7c538837892dd2eb83567c9f380a11efb59b53f",
20+ "rev": "5830a4dd348d77e39a0f3c4c762ff2663b602d4c",
21− "sha256": "0xl33k24vfc29cg9lnp95kvcq69qbq5fzb7jk9ig4lgrhaarh651",
21+ "sha256": "1d3lsrqvci4qz2hwjrcnd8h5vfkg8aypq3sjd4g3izbc8frwz5sm",
22 "type": "tarball",
22 "type": "tarball",
23− "url": "https://github.com/nmattia/niv/archive/f7c538837892dd2eb83567c9f380a11efb59b53f.tar.gz",
23+ "url": "https://github.com/nmattia/niv/archive/5830a4dd348d77e39a0f3c4c762ff2663b602d4c.tar.gz",
24 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
24 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
25 },
25 },
26 "nix-filter": {
26 "nix-filter": {
27− "branch": "main",
27+ "branch": "master",
28 "description": "a small self-container source filtering lib",
28 "description": "a small self-container source filtering lib",
29 "homepage": "",
29 "homepage": "",
30 "owner": "numtide",
30 "owner": "numtide",
31 "repo": "nix-filter",
31 "repo": "nix-filter",
32− "rev": "3342559a24e85fc164b295c3444e8a139924675b",
32+ "rev": "3c9e33ed627e009428197b07216613206f06ed80",
33− "sha256": "08xia32g5jzaiyhfl3kzxslzbr4w1i56i0mhy5gpfggv8gqy8sym",
33+ "sha256": "19w142crrkywxynmyw4rhz4nglrg64yjawfkw3j91qwkwbfjds84",
34 "type": "tarball",
34 "type": "tarball",
35− "url": "https://github.com/numtide/nix-filter/archive/3342559a24e85fc164b295c3444e8a139924675b.tar.gz",
35+ "url": "https://github.com/numtide/nix-filter/archive/3c9e33ed627e009428197b07216613206f06ed80.tar.gz",
36 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
36 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
37 },
37 },
38 "nixpkgs": {
38 "nixpkgs": {
@@ -41,10 +41,10 @@
41 "homepage": "",
41 "homepage": "",
42 "owner": "NixOS",
42 "owner": "NixOS",
43 "repo": "nixpkgs",
43 "repo": "nixpkgs",
44− "rev": "bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7",
44+ "rev": "f0fe5e9ba08e658474476317717aca7acacef4d4",
45− "sha256": "0ivvwdmg9fipj6ylq5ipxqpb0xnz6hsx3lyn377jacfpiqi9w0cv",
45+ "sha256": "1n5syynwmg3x8lj2kyb2ilbxw5nmw7f2kw6yxsi8qadx91hrvkwm",
46 "type": "tarball",
46 "type": "tarball",
47− "url": "https://github.com/NixOS/nixpkgs/archive/bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7.tar.gz",
47+ "url": "https://github.com/NixOS/nixpkgs/archive/f0fe5e9ba08e658474476317717aca7acacef4d4.tar.gz",
48 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
48 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
49 }
49 }
50}
50}
nix/yq.nixdeleted−26
@@ -1,26 +0,0 @@
1−{ pkgs ? import <nixpkgs> {} }:
2−
3−# Make yq work inside whatever `stack test` launches.
4−# Nuke this when https://github.com/kislyuk/yq/pull/193 is merged
5−# and nixpkgs includes that fix.
6−
7−let
8− yq-patch = pkgs.writeText "yq-tty-fix.patch" ''
9−diff --git a/yq/__init__.py b/yq/__init__.py
10−index d95ac4b..ae7d59e 100644
11−--- a/yq/__init__.py
12−+++ b/yq/__init__.py
13−@@ -110,7 +110,7 @@ def cli(args=None, input_format="yaml", program_name="yq"):
14− in_place = args.in_place
15− delattr(args, "in_place")
16−
17−- if sys.stdin.isatty() and not args.input_streams:
18−+ if (sys.stdin is None or sys.stdin.isatty()) and not args.input_streams:
19− parser.print_help()
20− sys.exit(2)
21− elif not args.input_streams:
22− '';
23−in
24−pkgs.yq.overrideAttrs (final: old: {
25− patches = old.patches ++ [ yq-patch ];
26−})
policeman.jsonnew file+6
@@ -0,0 +1,6 @@
1+[{
2+ "file": "compaREST.cabal",
3+ "annotation_level": "notice",
4+ "end_line": 0,
5+ "start_line": 0
6+}]
scripts/diff-yamldeleted−35
@@ -1,35 +0,0 @@
1−#!/usr/bin/env bash
2−set -e
3−
4−# Normalise YAML files passed as inputs, then run diff on them.
5−
6−check_util() {
7− local util=$1
8−
9− if [ -z $util ]; then
10− echo "Error: $util not found in PATH"
11− exit 1
12− fi
13−}
14−
15−DIFF=`which diff`
16−check_util $DIFF
17−
18−YQ=`which yq`
19−check_util $YQ
20−
21−# Only normalise YAML files.
22−# Print anything else as is.
23−normalise() {
24− local file=$1
25− local contents=($YQ -y -S '.' $file)
26−
27− # if $contents contains actual YAML data, print it
28− if [[ $? == 0 ]]; then
29− echo $contents
30− else
31− cat $file
32− fi
33−}
34−
35−$DIFF -u <(normalise $1) <(normalise $2)
src/Data/OpenApi/Compare/PathsPrefixTree.hs+4−5
@@ -23,8 +23,7 @@ where
23import Control.Monad
23import Control.Monad
24import Data.Aeson
24import Data.Aeson
25import Data.Foldable hiding (null, toList)
25import Data.Foldable hiding (null, toList)
26−import qualified Data.Aeson.Key as Key
26+import qualified Data.HashMap.Strict as HM
27−import qualified Data.Aeson.KeyMap as KeyMap
28import Data.Kind
27import Data.Kind
29import qualified Data.Map as M
28import qualified Data.Map as M
30import Data.Monoid
29import Data.Monoid
@@ -257,7 +256,7 @@ newtype MergableObject = MergableObject {getMergableObject :: Object}
257
256
258instance Semigroup MergableObject where
257instance Semigroup MergableObject where
259 (MergableObject x) <> (MergableObject y) =
258 (MergableObject x) <> (MergableObject y) =
260− MergableObject $ KeyMap.unionWith mergeValue x y
259+ MergableObject $ HM.unionWith mergeValue x y
261 where
260 where
262 mergeValue :: Value -> Value -> Value
261 mergeValue :: Value -> Value -> Value
263 mergeValue (Object a) (Object b) =
262 mergeValue (Object a) (Object b) =
@@ -272,6 +271,6 @@ instance Monoid MergableObject where
272
271
273traceObject :: Paths q r a -> Value -> Object
272traceObject :: Paths q r a -> Value -> Object
274traceObject Root (Object o) = o
273traceObject Root (Object o) = o
275−traceObject Root v = KeyMap.singleton "root" v
274+traceObject Root v = HM.singleton "root" v
276traceObject (root `Snoc` s) v =
275traceObject (root `Snoc` s) v =
277− traceObject root . Object $ KeyMap.singleton (Key.fromText . T.pack . show $ s) v
276+ traceObject root . Object $ HM.singleton (T.pack . show $ s) v
src/Data/OpenApi/Compare/Report.hs+1−1
@@ -198,7 +198,7 @@ showErrs x@(P.PathsPrefixNode currentIssues _) =
198 let -- Extract this pattern if more cases like this arise
198 let -- Extract this pattern if more cases like this arise
199 ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
199 ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
200 , otherIssues :: Set (AnIssue a)
200 , otherIssues :: Set (AnIssue a)
201− ) = case eqT @a @'APILevel of
201+ ) = case eqT @a @ 'APILevel of
202 Just Refl
202 Just Refl
203 | (S.toList -> p@((AnIssue ori _) : _), o) <-
203 | (S.toList -> p@((AnIssue ori _) : _), o) <-
204 S.partition
204 S.partition
src/Data/OpenApi/Compare/Report/Html/Template.hs+1−1
@@ -36,4 +36,4 @@ template =
36 \</html>"
36 \</html>"
37
37
38awsmCss :: ByteString
38awsmCss :: ByteString
39−awsmCss = $(makeRelativeToProject "css/awsm.min.css" >>= embedFile)
39+awsmCss = $(makeRelativeToProject "awsm-css/dist/awsm.min.css" >>= embedFile)
src/Data/OpenApi/Compare/Validate/OpenApi.hs+1−2
@@ -38,8 +38,7 @@ tracedSecuritySchemes :: Traced OpenApi -> Traced (Definitions SecurityScheme)
38tracedSecuritySchemes oa =
38tracedSecuritySchemes oa =
39 traced
39 traced
40 (ask oa >>> step ComponentsSecurityScheme)
40 (ask oa >>> step ComponentsSecurityScheme)
41− (unSecurityDefinitions . _componentsSecuritySchemes . _openApiComponents . extract $ oa)
41+ (_componentsSecuritySchemes . _openApiComponents . extract $ oa)
42− where unSecurityDefinitions (SecurityDefinitions ds) = ds
43
42
44tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
43tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
45tracedResponses oa =
44tracedResponses oa =
src/Data/OpenApi/Compare/Validate/Schema.hs+1−1
@@ -5,7 +5,7 @@ module Data.OpenApi.Compare.Validate.Schema
5 )
5 )
6where
6where
7
7
8−import Control.Monad (when,unless)
8+import Control.Monad.Writer
9import qualified Data.Aeson as A
9import qualified Data.Aeson as A
10import Data.Coerce
10import Data.Coerce
11import Data.Foldable (for_, toList)
11import Data.Foldable (for_, toList)
src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hs+6−7
@@ -18,11 +18,10 @@ where
18
18
19import Algebra.Lattice
19import Algebra.Lattice
20import qualified Data.Aeson as A
20import qualified Data.Aeson as A
21−import qualified Data.Aeson.Key as Key
22−import qualified Data.Aeson.KeyMap as KeyMap
23import qualified Data.ByteString.Lazy as BSL
21import qualified Data.ByteString.Lazy as BSL
24import qualified Data.Foldable as F
22import qualified Data.Foldable as F
25import Data.Functor
23import Data.Functor
24+import qualified Data.HashMap.Strict as HM
26import Data.Int
25import Data.Int
27import Data.Kind
26import Data.Kind
28import qualified Data.Map as M
27import qualified Data.Map as M
@@ -40,7 +39,7 @@ import Data.Text (Text)
40import qualified Data.Text as T
39import qualified Data.Text as T
41import qualified Data.Text.Encoding as T
40import qualified Data.Text.Encoding as T
42import Data.Typeable
41import Data.Typeable
43−import Text.Pandoc.Builder hiding (Format)
42+import Text.Pandoc.Builder hiding (Format, Null)
44import Text.Regex.Pcre2
43import Text.Regex.Pcre2
45
44
46data Bound a = Exclusive !a | Inclusive !a
45data Bound a = Exclusive !a | Inclusive !a
@@ -178,10 +177,10 @@ satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
178satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
177satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
179satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
178satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
180satisfiesTyped (TObject o) (Properties props additional _) =
179satisfiesTyped (TObject o) (Properties props additional _) =
181− all (`KeyMap.member` o) (map Key.fromText $ M.keys (M.filter propRequired props))
180+ all (`HM.member` o) (M.keys (M.filter propRequired props))
182− && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup (Key.toText k) props) (KeyMap.toList o)
181+ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
183−satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (KeyMap.size o) <= m
182+satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
184−satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (KeyMap.size o) >= m
183+satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
185
184
186checkNumberFormat :: Format -> Scientific -> Bool
185checkNumberFormat :: Format -> Scientific -> Bool
187checkNumberFormat "int32" (toRational -> n) =
186checkNumberFormat "int32" (toRational -> n) =
src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+1−4
@@ -16,7 +16,6 @@ where
16import Algebra.Lattice
16import Algebra.Lattice
17import Algebra.Lattice.Lifted
17import Algebra.Lattice.Lifted
18import Control.Applicative
18import Control.Applicative
19−import Control.Monad (when)
20import Control.Monad.Reader hiding (ask)
19import Control.Monad.Reader hiding (ask)
21import qualified Control.Monad.Reader as R
20import qualified Control.Monad.Reader as R
22import Control.Monad.State
21import Control.Monad.State
@@ -32,7 +31,6 @@ import qualified Data.List as L
32import qualified Data.List.NonEmpty as NE
31import qualified Data.List.NonEmpty as NE
33import qualified Data.Map as M
32import qualified Data.Map as M
34import Data.Maybe
33import Data.Maybe
35−import Data.Monoid
36import Data.OpenApi
34import Data.OpenApi
37import Data.OpenApi.Compare.Memo
35import Data.OpenApi.Compare.Memo
38import Data.OpenApi.Compare.References
36import Data.OpenApi.Compare.References
@@ -45,8 +43,7 @@ import Data.Ord
45import qualified Data.Set as S
43import qualified Data.Set as S
46import Data.Text (Text)
44import Data.Text (Text)
47import qualified Data.Text as T
45import qualified Data.Text as T
48−import Data.Traversable (forM)
49−import Text.Pandoc.Builder hiding (Format)
46+import Text.Pandoc.Builder hiding (Format, Null)
50
47
51data PartitionData
48data PartitionData
52 = DByEnumValue (DNF (S.Set A.Value))
49 = DByEnumValue (DNF (S.Set A.Value))
src/Data/OpenApi/Compare/Validate/Schema/Process.hs−2
@@ -13,7 +13,6 @@ import Data.Functor.Identity
13import qualified Data.HashMap.Strict.InsOrd as IOHM
13import qualified Data.HashMap.Strict.InsOrd as IOHM
14import qualified Data.Map as M
14import qualified Data.Map as M
15import Data.Maybe
15import Data.Maybe
16−import Data.Monoid
17import Data.OpenApi hiding (get)
16import Data.OpenApi hiding (get)
18import Data.OpenApi.Compare.Behavior
17import Data.OpenApi.Compare.Behavior
19import Data.OpenApi.Compare.Memo
18import Data.OpenApi.Compare.Memo
@@ -29,7 +28,6 @@ import Data.OpenApi.Compare.Validate.Schema.Traced
29import Data.OpenApi.Compare.Validate.Schema.TypedJson
28import Data.OpenApi.Compare.Validate.Schema.TypedJson
30import Data.Ord
29import Data.Ord
31import qualified Data.Set as S
30import qualified Data.Set as S
32−import Data.Traversable (forM)
33
31
34-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
32-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
35newtype Silent w a = Silent {runSilent :: a}
33newtype Silent w a = Silent {runSilent :: a}
stack.yaml+4−16
@@ -1,23 +1,11 @@
1−resolver: lts-22.34
1+resolver: lts-18.16
2
2
3packages:
3packages:
4 - .
4 - .
5
5
6extra-deps:
6extra-deps:
7− - base16-bytestring-1.0.2.0
8− - freer-simple-1.2.1.2
9− - generics-sop-0.5.1.4
10− - github-0.29
11− - http-link-header-1.2.1
12 - open-union-0.4.0.0
7 - open-union-0.4.0.0
13− - th-abstraction-0.7.0.0
14 - type-fun-0.1.3
8 - type-fun-0.1.3
15− - typerep-map-0.6.0.0
9+ - github-0.26
16−
10+ - base16-bytestring-0.1.1.7
17−# Required for freer-simple and typerep-map
11+ - http-link-header-1.0.3.1
18−allow-newer: true
19−
20−nix:
21−# packages: [pkg-config yq zlib]
22− shell-file: ./nix/shell.nix
23− pure: false
stack.yaml.lock+4−4
@@ -41,7 +41,7 @@ packages:
41 hackage: http-link-header-1.0.3.1
41 hackage: http-link-header-1.0.3.1
42snapshots:
42snapshots:
43- completed:
43- completed:
44− size: 587393
44+ size: 586286
45− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/25.yaml
45+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/16.yaml
46− sha256: 1b74fb5e970497b5aefae56703f1bd44aa648bd1a5ef95c1eb8c29775087e2bf
46+ sha256: cdead65fca0323144b346c94286186f4969bf85594d649c49c7557295675d8a5
47− original: lts-18.25
47+ original: lts-18.16
test/Spec/Golden/Extra.hs+2−2
@@ -59,7 +59,7 @@ goldenInputsTree ::
59 s ->
59 s ->
60 (t -> IO BSL.ByteString) ->
60 (t -> IO BSL.ByteString) ->
61 IO TestTree
61 IO TestTree
62−goldenInputsTree name filepath golden inp f =
62+goldenInputsTree name filepath golden inp f = do
63 runTestInputTree golden f <$> getGoldenInputs name filepath inp
63 runTestInputTree golden f <$> getGoldenInputs name filepath inp
64
64
65runTestInputTree ::
65runTestInputTree ::
@@ -72,7 +72,7 @@ runTestInputTree golden f (TestInputNode name rest) =
72runTestInputTree golden f (TestInputLeaf name t path) =
72runTestInputTree golden f (TestInputLeaf name t path) =
73 goldenVsStringDiff
73 goldenVsStringDiff
74 name
74 name
75− (\ref new -> ["diff-yaml", ref, new])
75+ (\ref new -> ["diff", "-u", ref, new])
76 (path </> golden)
76 (path </> golden)
77 (f t)
77 (f t)
78
78
test/golden/common/random-example/trace-tree.yaml+4−4
@@ -23,10 +23,6 @@ forwardChanges:
23backwardChanges:
23backwardChanges:
24 AtPath "/pets":
24 AtPath "/pets":
25 InOperation GetMethod:
25 InOperation GetMethod:
26− InParam "limit":
27− InParamSchema:
28− OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0,
29− consumer = Inclusive 20.0})
30 WithStatusCode 200:
26 WithStatusCode 200:
31 ResponsePayload:
27 ResponsePayload:
32 PayloadSchema:
28 PayloadSchema:
@@ -37,6 +33,10 @@ backwardChanges:
37 - TypesRestricted [Number]
33 - TypesRestricted [Number]
38 - AdditionalToProperty
34 - AdditionalToProperty
39 - OfType Number: NoMatchingMultipleOf 1.0
35 - OfType Number: NoMatchingMultipleOf 1.0
36+ InParam "limit":
37+ InParamSchema:
38+ OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0,
39+ consumer = Inclusive 20.0})
40 InOperation PostMethod:
40 InOperation PostMethod:
41 InRequest:
41 InRequest:
42 InPayload:
42 InPayload: