git.iko.soy/typeable/compaREST
on master help sign in
33 files changed+269−154
since splitsnapshots
unifiedsplit
.github/actions/common_setup/action.yaml+2−2 .github/workflows/github-actions-image.yaml+60−74 .gitmodules−3 CHANGELOG.md+5−1 README.md+1−3 action.yaml+1−1 app/Data/OpenApi/Compare/Options.hs+1 app/Main.hs+1 awsm-css−1 compaREST.cabal+6−4 css/awsm.min.css+1 default.nix+18−7 docs/Integration_guide.md−2 github-action/Main.hs+13−7 nix/ci.nix+6−1 nix/diff-yaml.nix+20 nix/shell.nix+11 nix/sources.json+13−13 nix/yq.nix+26 policeman.json−6 scripts/diff-yaml+35 src/Data/OpenApi/Compare/PathsPrefixTree.hs+5−4 src/Data/OpenApi/Compare/Report.hs+1−1 src/Data/OpenApi/Compare/Report/Html/Template.hs+1−1 src/Data/OpenApi/Compare/Validate/OpenApi.hs+2−1 src/Data/OpenApi/Compare/Validate/Schema.hs+1−1 src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hs+7−6 src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+4−1 src/Data/OpenApi/Compare/Validate/Schema/Process.hs+2 stack.yaml+16−4 stack.yaml.lock+4−4 test/Spec/Golden/Extra.hs+2−2 test/golden/common/random-example/trace-tree.yaml+4−4
.github/actions/common_setup/action.yaml+2−2
@@ -30,13 +30,13 @@ runs:
3030 fi
3131
3232 - name: Install Nix
33− uses: cachix/install-nix-action@v16
33+ uses: cachix/install-nix-action@v27
3434 with:
3535 extra_nix_config: |
3636 system-features = kvm
3737 trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
3838 substituters = https://hydra.iohk.io https://cache.nixos.org/
39− - uses: cachix/cachix-action@v10
39+ - uses: cachix/cachix-action@v15
4040 with:
4141 name: typeable
4242 authToken: "${{ inputs.authToken }}"
.github/workflows/github-actions-image.yaml+60−74
@@ -9,23 +9,23 @@ on:
99 types: [prereleased]
1010
1111jobs:
12− check-formatting:
13− name: Check Haskell formatting
14− runs-on: ubuntu-latest
15− steps:
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
12+# check-formatting:
13+# name: Check Haskell formatting
14+# runs-on: ubuntu-latest
15+# steps:
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
2727
28− policeman:
28+ check_versions:
2929 runs-on: ubuntu-latest
3030 steps:
3131 - uses: actions/checkout@v2
@@ -37,25 +37,6 @@ jobs:
3737 with:
3838 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
3939
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−
5940 - name: Check library version
6041 if: github.event_name == 'release'
6142 run: |
@@ -178,13 +159,18 @@ jobs:
178159 tag: ${{ github.ref }}
179160
180161 dist:
181− needs: check_versions
162+ needs: [check_versions, Linux]
182163 runs-on: ubuntu-latest
183164 steps:
184165 - uses: actions/checkout@v2
185166 with:
186167 submodules: recursive
187168
169+ - name: Common setup
170+ uses: ./.github/actions/common_setup
171+ with:
172+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
173+
188174 - name: Cache
189175 uses: actions/cache@v1
190176 with:
@@ -203,7 +189,7 @@ jobs:
203189
204190 - name: Build dist
205191 run: |
206− stack sdist --pvp-bounds both --test-tarball
192+ stack sdist --pvp-bounds both
207193 echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
208194
209195 - name: Upload compaREST sources artifact
@@ -227,7 +213,7 @@ jobs:
227213 env:
228214 HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
229215 run: |
230− stack upload --pvp-bounds both --test-tarball --candidate .
216+ stack upload --pvp-bounds both --candidate .
231217
232218 macOS:
233219 needs: check_versions
@@ -266,39 +252,39 @@ jobs:
266252 file: compaREST-macOS-x86.zip
267253 tag: ${{ github.ref }}
268254
269− Linux-Windows:
270− needs: check_versions
271− runs-on: ubuntu-latest
272− steps:
273− - uses: actions/checkout@v2
274− with:
275− submodules: recursive
276−
277− - name: Common setup
278− uses: ./.github/actions/common_setup
279− with:
280− authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
281−
282− - name: Build Windows binary
283− run: |
284− cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
285−
286− - name: Upload Windows compaREST bundle
287− uses: actions/upload-artifact@v2
288− with:
289− name: compaREST binary – Windows
290− path: compaREST
291−
292− - name: Zip Release Assets
293− if: github.event_name == 'release'
294− shell: bash
295− run: |
296− zip -r compaREST-Windows.zip compaREST
297−
298− - name: Upload compaREST binary – Windows to release
299− if: github.event_name == 'release'
300− uses: svenstaro/upload-release-action@2.2.1
301− with:
302− repo_token: ${{ secrets.GITHUB_TOKEN }}
303− file: compaREST-Windows.zip
304− tag: ${{ github.ref }}
255+# Linux-Windows:
256+# needs: check_versions
257+# runs-on: ubuntu-latest
258+# steps:
259+# - uses: actions/checkout@v2
260+# with:
261+# submodules: recursive
262+#
263+# - name: Common setup
264+# uses: ./.github/actions/common_setup
265+# with:
266+# authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
267+#
268+# - name: Build Windows binary
269+# run: |
270+# cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
271+#
272+# - name: Upload Windows compaREST bundle
273+# uses: actions/upload-artifact@v2
274+# with:
275+# name: compaREST binary – Windows
276+# path: compaREST
277+#
278+# - name: Zip Release Assets
279+# if: github.event_name == 'release'
280+# shell: bash
281+# run: |
282+# zip -r compaREST-Windows.zip compaREST
283+#
284+# - name: Upload compaREST binary – Windows to release
285+# if: github.event_name == 'release'
286+# uses: svenstaro/upload-release-action@2.2.1
287+# with:
288+# repo_token: ${{ secrets.GITHUB_TOKEN }}
289+# file: compaREST-Windows.zip
290+# tag: ${{ github.ref }}
.gitmodulesdeleted−3
@@ -1,3 +0,0 @@
1−[submodule "awsm-css"]
2− path = awsm-css
3− url = https://github.com/igoradamenko/awsm.css.git
CHANGELOG.md+5−1
@@ -1,6 +1,10 @@
11# Changelog
22
3−`comparest` uses [PVP Versioning][1].
3+`compaREST` uses [PVP Versioning][1].
4+
5+## 0.1.0.1
6+
7+* Fixed an issue related to empty commit SHAs in GitHub Actions.
48
59## 0.1.0.0
610
README.md+1−3
@@ -1,8 +1,6 @@
11# compaREST
22
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)
3+[![Hackage](https://img.shields.io/hackage/v/compaREST.svg?logo=haskell)](https://hackage.haskell.org/package/compaREST)
64[![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
75
86Compatibility checker for OpenAPI
action.yaml+1−1
@@ -30,7 +30,7 @@ inputs:
3030 default: "${{ github.event.pull_request.head.sha }}"
3131runs:
3232 using: "docker"
33− image: "docker://typeable/comparest-github-action:0.1.0.0"
33+ image: "docker://typeable/comparest-github-action:0.1.0.1"
3434 env:
3535 GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
3636 REPO: "${{ inputs.repo }}"
app/Data/OpenApi/Compare/Options.hs+1
@@ -9,6 +9,7 @@ import Data.OpenApi.Compare.Report
99import GHC.Generics (Generic)
1010import Options.Applicative
1111import Options.Applicative.Help hiding (fullDesc)
12+import Text.PrettyPrint.ANSI.Leijen ((<$$>),string)
1213
1314parseOptions :: IO Options
1415parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
app/Main.hs+1
@@ -2,6 +2,7 @@ module Main (main) where
22
33import Control.Monad
44import Control.Monad.Except
5+import Control.Monad.Trans (lift)
56import Data.Aeson
67import qualified Data.ByteString.Lazy as BSL
78import Data.Default
awsm-cssdeleted−1

Submodule changed.

compaREST.cabal+6−4
@@ -1,6 +1,6 @@
11cabal-version: 2.4
22name: compaREST
3−version: 0.1.0.0
3+version: 0.1.0.1
44synopsis: Compatibility checker for OpenAPI
55description: Compatibility checker for OpenAPI.
66license: MIT
@@ -12,8 +12,8 @@ category: Web
1212build-type: Simple
1313extra-doc-files: README.md
1414 CHANGELOG.md
15−tested-with: GHC == 8.10.4
16−extra-source-files: awsm-css/dist/awsm.min.css
15+tested-with: GHC == 9.6
16+extra-source-files: css/awsm.min.css
1717extra-source-files:
1818 test/golden/**/*.yaml
1919 test/golden/**/*.md
@@ -26,13 +26,14 @@ common common-options
2626 -Wno-safe
2727 -Wno-prepositive-qualified-module
2828 -Wno-missing-import-lists
29+ -Wno-missing-kind-signatures
2930 -Wno-partial-fields
3031 -Wno-all-missed-specialisations
3132 -Wno-missing-local-signatures
3233 -Wno-unsafe
3334 -fconstraint-solver-iterations=0
3435 default-language: Haskell2010
35− build-depends: base >= 4.12.0.0 && < 4.16
36+ build-depends: base >= 4.12.0.0 && < 5
3637 , text
3738
3839
@@ -165,6 +166,7 @@ executable compaREST
165166 , containers
166167 , doctemplates
167168 , pandoc-types
169+ , prettyprinter-compat-ansi-wl-pprint
168170 ghc-options: -threaded
169171 -rtsopts
170172 -with-rtsopts=-N
css/awsm.min.cssnew file+1
@@ -0,0 +1 @@
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+18−7
@@ -1,11 +1,13 @@
11{ sources ? import ./nix/sources.nix
22, haskellNix ? import sources.haskellNix { inherit system; }
3−, pkgs ? import haskellNix.sources.nixpkgs-2105 (haskellNix.nixpkgsArgs // { inherit system; })
3+, pkgs ? import haskellNix.sources.nixpkgs-2311 (haskellNix.nixpkgsArgs // { inherit system; })
44, system ? builtins.currentSystem
55, nix-filter ? import sources.nix-filter
66}:
77let
88 masterPkgs = import sources.nixpkgs { inherit system; };
9+ yq = import ./nix/yq.nix { pkgs = masterPkgs; };
10+ diffYaml = import ./nix/diff-yaml.nix { pkgs = masterPkgs; };
911
1012 hsPkgs = pkgs.haskell-nix.stackProject {
1113 src = nix-filter {
@@ -38,7 +40,7 @@ let
3840 (inDirectory ./src)
3941 (inDirectory ./app)
4042 (inDirectory ./github-action)
41− ./awsm-css/dist/awsm.min.css
43+ ./css/awsm.min.css
4244 ./LICENSE
4345 ];
4446 };
@@ -97,6 +99,18 @@ let
9799 };
98100
99101 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+ });
100114in
101115{
102116 inherit
@@ -106,9 +120,6 @@ in
106120 compaRESTBin
107121 hsPkgs
108122 macOSCompaRESTBundle
109− WindowsCompaRESTBin;
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;
123+ WindowsCompaRESTBin
124+ test;
114125}
docs/Integration_guide.md−2
@@ -28,8 +28,6 @@ In our example we have already generated the two OpenAPI specs and placed them i
2828
2929We can now run our action:
3030
31−##### NOTE: will only work after public release
32−
3331```yaml
3432- uses: typeable/comparest
3533 with:
github-action/Main.hs+13−7
@@ -9,6 +9,7 @@ import Control.Monad.Freer.GitHub
99import Control.Monad.Freer.Reader
1010import Data.OpenApi.Compare.Run
1111import Data.Text (Text)
12+import qualified Data.Text as T
1213import qualified Data.Yaml.Aeson as Yaml
1314import qualified GitHub as GH
1415import System.Environment
@@ -22,13 +23,18 @@ import Text.Pandoc.Writers
2223main :: IO ()
2324main = do
2425 cfg <- decodeEnv >>= either error pure
25− getArgs >>= \case
26− ["pre"] -> runPre cfg
27− ["run"] -> do
28− oldFile <- getEnv "OLD"
29− newFile <- getEnv "NEW"
30− runRun cfg (root cfg </> oldFile) (root cfg </> newFile)
31− _ -> error "Invalid arguments."
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
32+ ["pre"] -> runPre cfg
33+ ["run"] -> do
34+ oldFile <- getEnv "OLD"
35+ newFile <- getEnv "NEW"
36+ runRun cfg (root cfg </> oldFile) (root cfg </> newFile)
37+ _ -> error "Invalid arguments."
3238
3339runner :: Config -> Eff '[GitHub, Error GH.Error, Reader Config, IO] a -> IO a
3440runner cfg =
nix/ci.nix+6−1
@@ -1,6 +1,11 @@
11{ sources ? import ./sources.nix
22, pkgs ? import sources.nixpkgs { }
33}:
4+
5+let
6+ yq = import ./yq.nix { inherit pkgs; };
7+ diff-yaml = import ./diff-yaml.nix { inherit pkgs; };
8+in
49pkgs.mkShell {
5− packages = [ pkgs.haskellPackages.fourmolu ];
10+ packages = [ pkgs.haskellPackages.fourmolu diff-yaml yq ];
611}
nix/diff-yaml.nixnew file+20
@@ -0,0 +1,20 @@
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.nixnew file+11
@@ -0,0 +1,11 @@
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 @@
55 "homepage": "https://input-output-hk.github.io/haskell.nix",
66 "owner": "input-output-hk",
77 "repo": "haskell.nix",
8− "rev": "c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e",
9− "sha256": "0frzmvz8rhb4vgx20qms9xxqbkmg5pwivis4qis63ny5wxclzb34",
8+ "rev": "d7f95903c84a5a50d6fe0844280da82c3c81680a",
9+ "sha256": "02870rk4sx44lwwa0k20iwdhqcx0ayz34yb3b0qy045p22q45815",
1010 "type": "tarball",
11− "url": "https://github.com/input-output-hk/haskell.nix/archive/c8a8f57de3c14fcf1c5cda045ed885fb6d06a00e.tar.gz",
11+ "url": "https://github.com/input-output-hk/haskell.nix/archive/d7f95903c84a5a50d6fe0844280da82c3c81680a.tar.gz",
1212 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
1313 },
1414 "niv": {
@@ -17,22 +17,22 @@
1717 "homepage": "https://github.com/nmattia/niv",
1818 "owner": "nmattia",
1919 "repo": "niv",
20− "rev": "5830a4dd348d77e39a0f3c4c762ff2663b602d4c",
21− "sha256": "1d3lsrqvci4qz2hwjrcnd8h5vfkg8aypq3sjd4g3izbc8frwz5sm",
20+ "rev": "f7c538837892dd2eb83567c9f380a11efb59b53f",
21+ "sha256": "0xl33k24vfc29cg9lnp95kvcq69qbq5fzb7jk9ig4lgrhaarh651",
2222 "type": "tarball",
23− "url": "https://github.com/nmattia/niv/archive/5830a4dd348d77e39a0f3c4c762ff2663b602d4c.tar.gz",
23+ "url": "https://github.com/nmattia/niv/archive/f7c538837892dd2eb83567c9f380a11efb59b53f.tar.gz",
2424 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
2525 },
2626 "nix-filter": {
27− "branch": "master",
27+ "branch": "main",
2828 "description": "a small self-container source filtering lib",
2929 "homepage": "",
3030 "owner": "numtide",
3131 "repo": "nix-filter",
32− "rev": "3c9e33ed627e009428197b07216613206f06ed80",
33− "sha256": "19w142crrkywxynmyw4rhz4nglrg64yjawfkw3j91qwkwbfjds84",
32+ "rev": "3342559a24e85fc164b295c3444e8a139924675b",
33+ "sha256": "08xia32g5jzaiyhfl3kzxslzbr4w1i56i0mhy5gpfggv8gqy8sym",
3434 "type": "tarball",
35− "url": "https://github.com/numtide/nix-filter/archive/3c9e33ed627e009428197b07216613206f06ed80.tar.gz",
35+ "url": "https://github.com/numtide/nix-filter/archive/3342559a24e85fc164b295c3444e8a139924675b.tar.gz",
3636 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
3737 },
3838 "nixpkgs": {
@@ -41,10 +41,10 @@
4141 "homepage": "",
4242 "owner": "NixOS",
4343 "repo": "nixpkgs",
44− "rev": "f0fe5e9ba08e658474476317717aca7acacef4d4",
45− "sha256": "1n5syynwmg3x8lj2kyb2ilbxw5nmw7f2kw6yxsi8qadx91hrvkwm",
44+ "rev": "bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7",
45+ "sha256": "0ivvwdmg9fipj6ylq5ipxqpb0xnz6hsx3lyn377jacfpiqi9w0cv",
4646 "type": "tarball",
47− "url": "https://github.com/NixOS/nixpkgs/archive/f0fe5e9ba08e658474476317717aca7acacef4d4.tar.gz",
47+ "url": "https://github.com/NixOS/nixpkgs/archive/bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7.tar.gz",
4848 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
4949 }
5050}
nix/yq.nixnew file+26
@@ -0,0 +1,26 @@
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.jsondeleted−6
@@ -1,6 +0,0 @@
1−[{
2− "file": "compaREST.cabal",
3− "annotation_level": "notice",
4− "end_line": 0,
5− "start_line": 0
6−}]
scripts/diff-yamlnew file+35
@@ -0,0 +1,35 @@
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+5−4
@@ -23,7 +23,8 @@ where
2323import Control.Monad
2424import Data.Aeson
2525import Data.Foldable hiding (null, toList)
26−import qualified Data.HashMap.Strict as HM
26+import qualified Data.Aeson.Key as Key
27+import qualified Data.Aeson.KeyMap as KeyMap
2728import Data.Kind
2829import qualified Data.Map as M
2930import Data.Monoid
@@ -256,7 +257,7 @@ newtype MergableObject = MergableObject {getMergableObject :: Object}
256257
257258instance Semigroup MergableObject where
258259 (MergableObject x) <> (MergableObject y) =
259− MergableObject $ HM.unionWith mergeValue x y
260+ MergableObject $ KeyMap.unionWith mergeValue x y
260261 where
261262 mergeValue :: Value -> Value -> Value
262263 mergeValue (Object a) (Object b) =
@@ -271,6 +272,6 @@ instance Monoid MergableObject where
271272
272273traceObject :: Paths q r a -> Value -> Object
273274traceObject Root (Object o) = o
274−traceObject Root v = HM.singleton "root" v
275+traceObject Root v = KeyMap.singleton "root" v
275276traceObject (root `Snoc` s) v =
276− traceObject root . Object $ HM.singleton (T.pack . show $ s) v
277+ traceObject root . Object $ KeyMap.singleton (Key.fromText . T.pack . show $ s) v
src/Data/OpenApi/Compare/Report.hs+1−1
@@ -198,7 +198,7 @@ showErrs x@(P.PathsPrefixNode currentIssues _) =
198198 let -- Extract this pattern if more cases like this arise
199199 ( removedPaths :: Maybe (Orientation, [Issue 'APILevel])
200200 , otherIssues :: Set (AnIssue a)
201− ) = case eqT @a @ 'APILevel of
201+ ) = case eqT @a @'APILevel of
202202 Just Refl
203203 | (S.toList -> p@((AnIssue ori _) : _), o) <-
204204 S.partition
src/Data/OpenApi/Compare/Report/Html/Template.hs+1−1
@@ -36,4 +36,4 @@ template =
3636 \</html>"
3737
3838awsmCss :: ByteString
39−awsmCss = $(makeRelativeToProject "awsm-css/dist/awsm.min.css" >>= embedFile)
39+awsmCss = $(makeRelativeToProject "css/awsm.min.css" >>= embedFile)
src/Data/OpenApi/Compare/Validate/OpenApi.hs+2−1
@@ -38,7 +38,8 @@ tracedSecuritySchemes :: Traced OpenApi -> Traced (Definitions SecurityScheme)
3838tracedSecuritySchemes oa =
3939 traced
4040 (ask oa >>> step ComponentsSecurityScheme)
41− (_componentsSecuritySchemes . _openApiComponents . extract $ oa)
41+ (unSecurityDefinitions . _componentsSecuritySchemes . _openApiComponents . extract $ oa)
42+ where unSecurityDefinitions (SecurityDefinitions ds) = ds
4243
4344tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
4445tracedResponses oa =
src/Data/OpenApi/Compare/Validate/Schema.hs+1−1
@@ -5,7 +5,7 @@ module Data.OpenApi.Compare.Validate.Schema
55 )
66where
77
8−import Control.Monad.Writer
8+import Control.Monad (when,unless)
99import qualified Data.Aeson as A
1010import Data.Coerce
1111import Data.Foldable (for_, toList)
src/Data/OpenApi/Compare/Validate/Schema/JsonFormula.hs+7−6
@@ -18,10 +18,11 @@ where
1818
1919import Algebra.Lattice
2020import qualified Data.Aeson as A
21+import qualified Data.Aeson.Key as Key
22+import qualified Data.Aeson.KeyMap as KeyMap
2123import qualified Data.ByteString.Lazy as BSL
2224import qualified Data.Foldable as F
2325import Data.Functor
24−import qualified Data.HashMap.Strict as HM
2526import Data.Int
2627import Data.Kind
2728import qualified Data.Map as M
@@ -39,7 +40,7 @@ import Data.Text (Text)
3940import qualified Data.Text as T
4041import qualified Data.Text.Encoding as T
4142import Data.Typeable
42−import Text.Pandoc.Builder hiding (Format, Null)
43+import Text.Pandoc.Builder hiding (Format)
4344import Text.Regex.Pcre2
4445
4546data Bound a = Exclusive !a | Inclusive !a
@@ -177,10 +178,10 @@ satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
177178satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
178179satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
179180satisfiesTyped (TObject o) (Properties props additional _) =
180− all (`HM.member` o) (M.keys (M.filter propRequired props))
181− && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
182−satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
183−satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
181+ all (`KeyMap.member` o) (map Key.fromText $ M.keys (M.filter propRequired props))
182+ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup (Key.toText k) props) (KeyMap.toList o)
183+satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (KeyMap.size o) <= m
184+satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (KeyMap.size o) >= m
184185
185186checkNumberFormat :: Format -> Scientific -> Bool
186187checkNumberFormat "int32" (toRational -> n) =
src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+4−1
@@ -16,6 +16,7 @@ where
1616import Algebra.Lattice
1717import Algebra.Lattice.Lifted
1818import Control.Applicative
19+import Control.Monad (when)
1920import Control.Monad.Reader hiding (ask)
2021import qualified Control.Monad.Reader as R
2122import Control.Monad.State
@@ -31,6 +32,7 @@ import qualified Data.List as L
3132import qualified Data.List.NonEmpty as NE
3233import qualified Data.Map as M
3334import Data.Maybe
35+import Data.Monoid
3436import Data.OpenApi
3537import Data.OpenApi.Compare.Memo
3638import Data.OpenApi.Compare.References
@@ -43,7 +45,8 @@ import Data.Ord
4345import qualified Data.Set as S
4446import Data.Text (Text)
4547import qualified Data.Text as T
46−import Text.Pandoc.Builder hiding (Format, Null)
48+import Data.Traversable (forM)
49+import Text.Pandoc.Builder hiding (Format)
4750
4851data PartitionData
4952 = DByEnumValue (DNF (S.Set A.Value))
src/Data/OpenApi/Compare/Validate/Schema/Process.hs+2
@@ -13,6 +13,7 @@ import Data.Functor.Identity
1313import qualified Data.HashMap.Strict.InsOrd as IOHM
1414import qualified Data.Map as M
1515import Data.Maybe
16+import Data.Monoid
1617import Data.OpenApi hiding (get)
1718import Data.OpenApi.Compare.Behavior
1819import Data.OpenApi.Compare.Memo
@@ -28,6 +29,7 @@ import Data.OpenApi.Compare.Validate.Schema.Traced
2829import Data.OpenApi.Compare.Validate.Schema.TypedJson
2930import Data.Ord
3031import qualified Data.Set as S
32+import Data.Traversable (forM)
3133
3234-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
3335newtype Silent w a = Silent {runSilent :: a}
stack.yaml+16−4
@@ -1,11 +1,23 @@
1−resolver: lts-18.16
1+resolver: lts-22.34
22
33packages:
44 - .
55
66extra-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
712 - open-union-0.4.0.0
13+ - th-abstraction-0.7.0.0
814 - type-fun-0.1.3
9− - github-0.26
10− - base16-bytestring-0.1.1.7
11− - http-link-header-1.0.3.1
15+ - typerep-map-0.6.0.0
16+
17+# Required for freer-simple and typerep-map
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:
4141 hackage: http-link-header-1.0.3.1
4242snapshots:
4343- completed:
44− size: 586286
45− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/16.yaml
46− sha256: cdead65fca0323144b346c94286186f4969bf85594d649c49c7557295675d8a5
47− original: lts-18.16
44+ size: 587393
45+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/25.yaml
46+ sha256: 1b74fb5e970497b5aefae56703f1bd44aa648bd1a5ef95c1eb8c29775087e2bf
47+ original: lts-18.25
test/Spec/Golden/Extra.hs+2−2
@@ -59,7 +59,7 @@ goldenInputsTree ::
5959 s ->
6060 (t -> IO BSL.ByteString) ->
6161 IO TestTree
62−goldenInputsTree name filepath golden inp f = do
62+goldenInputsTree name filepath golden inp f =
6363 runTestInputTree golden f <$> getGoldenInputs name filepath inp
6464
6565runTestInputTree ::
@@ -72,7 +72,7 @@ runTestInputTree golden f (TestInputNode name rest) =
7272runTestInputTree golden f (TestInputLeaf name t path) =
7373 goldenVsStringDiff
7474 name
75− (\ref new -> ["diff", "-u", ref, new])
75+ (\ref new -> ["diff-yaml", ref, new])
7676 (path </> golden)
7777 (f t)
7878
test/golden/common/random-example/trace-tree.yaml+4−4
@@ -23,6 +23,10 @@ forwardChanges:
2323backwardChanges:
2424 AtPath "/pets":
2525 InOperation GetMethod:
26+ InParam "limit":
27+ InParamSchema:
28+ OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0,
29+ consumer = Inclusive 20.0})
2630 WithStatusCode 200:
2731 ResponsePayload:
2832 PayloadSchema:
@@ -33,10 +37,6 @@ backwardChanges:
3337 - TypesRestricted [Number]
3438 - AdditionalToProperty
3539 - OfType Number: NoMatchingMultipleOf 1.0
36− InParam "limit":
37− InParamSchema:
38− OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 30.0,
39− consumer = Inclusive 20.0})
4040 InOperation PostMethod:
4141 InRequest:
4242 InPayload: