git.iko.soy/typeable/compaREST
on master 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@v16
33+ uses: cachix/install-nix-action@v27
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@v10
39+ - uses: cachix/cachix-action@v15
40 with:
40 with:
41 name: typeable
41 name: typeable
42 authToken: "${{ inputs.authToken }}"
42 authToken: "${{ inputs.authToken }}"
.github/workflows/github-actions-image.yaml+63−53
@@ -9,29 +9,34 @@ 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
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
27+
28+ check_versions:
14 runs-on: ubuntu-latest
29 runs-on: ubuntu-latest
15 steps:
30 steps:
16 - uses: actions/checkout@v2
31 - uses: actions/checkout@v2
32+ with:
33+ submodules: recursive
17
34
18 - name: Common setup
35 - name: Common setup
19 uses: ./.github/actions/common_setup
36 uses: ./.github/actions/common_setup
20 with:
37 with:
21 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
38 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
22
39
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− check_versions:
29− runs-on: ubuntu-latest
30− steps:
31− - uses: actions/checkout@v2
32− with:
33− submodules: recursive
34−
35 - name: Check library version
40 - name: Check library version
36 if: github.event_name == 'release'
41 if: github.event_name == 'release'
37 run: |
42 run: |
@@ -154,13 +159,18 @@ jobs:
154 tag: ${{ github.ref }}
159 tag: ${{ github.ref }}
155
160
156 dist:
161 dist:
157− needs: check_versions
162+ needs: [check_versions, Linux]
158 runs-on: ubuntu-latest
163 runs-on: ubuntu-latest
159 steps:
164 steps:
160 - uses: actions/checkout@v2
165 - uses: actions/checkout@v2
161 with:
166 with:
162 submodules: recursive
167 submodules: recursive
163
168
169+ - name: Common setup
170+ uses: ./.github/actions/common_setup
171+ with:
172+ authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
173+
164 - name: Cache
174 - name: Cache
165 uses: actions/cache@v1
175 uses: actions/cache@v1
166 with:
176 with:
@@ -179,7 +189,7 @@ jobs:
179
189
180 - name: Build dist
190 - name: Build dist
181 run: |
191 run: |
182− stack sdist --pvp-bounds both --test-tarball
192+ stack sdist --pvp-bounds both
183 echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
193 echo "distPath=$(stack path | awk -F ": " '/dist-dir/ {print $2}')" >> $GITHUB_ENV
184
194
185 - name: Upload compaREST sources artifact
195 - name: Upload compaREST sources artifact
@@ -203,7 +213,7 @@ jobs:
203 env:
213 env:
204 HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
214 HACKAGE_KEY: ${{ secrets.HACKAGE_KEY }}
205 run: |
215 run: |
206− stack upload --pvp-bounds both --test-tarball --candidate .
216+ stack upload --pvp-bounds both --candidate .
207
217
208 macOS:
218 macOS:
209 needs: check_versions
219 needs: check_versions
@@ -242,39 +252,39 @@ jobs:
242 file: compaREST-macOS-x86.zip
252 file: compaREST-macOS-x86.zip
243 tag: ${{ github.ref }}
253 tag: ${{ github.ref }}
244
254
245− Linux-Windows:
255+# Linux-Windows:
246− needs: check_versions
256+# needs: check_versions
247− runs-on: ubuntu-latest
257+# runs-on: ubuntu-latest
248− steps:
258+# steps:
249− - uses: actions/checkout@v2
259+# - uses: actions/checkout@v2
250− with:
260+# with:
251− submodules: recursive
261+# submodules: recursive
252−
262+#
253− - name: Common setup
263+# - name: Common setup
254− uses: ./.github/actions/common_setup
264+# uses: ./.github/actions/common_setup
255− with:
265+# with:
256− authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
266+# authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
257−
267+#
258− - name: Build Windows binary
268+# - name: Build Windows binary
259− run: |
269+# run: |
260− cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
270+# cp -LR $(nix-build -A WindowsCompaRESTBin -j auto --no-out-link)/bin compaREST
261−
271+#
262− - name: Upload Windows compaREST bundle
272+# - name: Upload Windows compaREST bundle
263− uses: actions/upload-artifact@v2
273+# uses: actions/upload-artifact@v2
264− with:
274+# with:
265− name: compaREST binary – Windows
275+# name: compaREST binary – Windows
266− path: compaREST
276+# path: compaREST
267−
277+#
268− - name: Zip Release Assets
278+# - name: Zip Release Assets
269− if: github.event_name == 'release'
279+# if: github.event_name == 'release'
270− shell: bash
280+# shell: bash
271− run: |
281+# run: |
272− zip -r compaREST-Windows.zip compaREST
282+# zip -r compaREST-Windows.zip compaREST
273−
283+#
274− - name: Upload compaREST binary – Windows to release
284+# - name: Upload compaREST binary – Windows to release
275− if: github.event_name == 'release'
285+# if: github.event_name == 'release'
276− uses: svenstaro/upload-release-action@2.2.1
286+# uses: svenstaro/upload-release-action@2.2.1
277− with:
287+# with:
278− repo_token: ${{ secrets.GITHUB_TOKEN }}
288+# repo_token: ${{ secrets.GITHUB_TOKEN }}
279− file: compaREST-Windows.zip
289+# file: compaREST-Windows.zip
280− tag: ${{ github.ref }}
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
action.yaml+1−1
@@ -30,7 +30,7 @@ inputs:
30 default: "${{ github.event.pull_request.head.sha }}"
30 default: "${{ github.event.pull_request.head.sha }}"
31runs:
31runs:
32 using: "docker"
32 using: "docker"
33− image: "docker://typeable/comparest-github-action:0.1.0.0"
33+ image: "docker://typeable/comparest-github-action:0.1.0.1"
34 env:
34 env:
35 GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
35 GITHUB_TOKEN: "${{ inputs.GITHUB_TOKEN }}"
36 REPO: "${{ inputs.repo }}"
36 REPO: "${{ inputs.repo }}"
app/Data/OpenApi/Compare/Options.hs+1
@@ -9,6 +9,7 @@ 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)
12
13
13parseOptions :: IO Options
14parseOptions :: IO Options
14parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
15parseOptions = customExecParser (prefs $ showHelpOnError) optionsParserInfo
app/Main.hs+1
@@ -2,6 +2,7 @@ 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)
5import Data.Aeson
6import Data.Aeson
6import qualified Data.ByteString.Lazy as BSL
7import qualified Data.ByteString.Lazy as BSL
7import Data.Default
8import Data.Default
awsm-cssdeleted−1

Submodule changed.

compaREST.cabal+5−3
@@ -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 == 8.10.4
15+tested-with: GHC == 9.6
16−extra-source-files: awsm-css/dist/awsm.min.css
16+extra-source-files: css/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,13 +26,14 @@ 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
29 -Wno-partial-fields
30 -Wno-partial-fields
30 -Wno-all-missed-specialisations
31 -Wno-all-missed-specialisations
31 -Wno-missing-local-signatures
32 -Wno-missing-local-signatures
32 -Wno-unsafe
33 -Wno-unsafe
33 -fconstraint-solver-iterations=0
34 -fconstraint-solver-iterations=0
34 default-language: Haskell2010
35 default-language: Haskell2010
35− build-depends: base >= 4.12.0.0 && < 4.16
36+ build-depends: base >= 4.12.0.0 && < 5
36 , text
37 , text
37
38
38
39
@@ -165,6 +166,7 @@ executable compaREST
165 , containers
166 , containers
166 , doctemplates
167 , doctemplates
167 , pandoc-types
168 , pandoc-types
169+ , prettyprinter-compat-ansi-wl-pprint
168 ghc-options: -threaded
170 ghc-options: -threaded
169 -rtsopts
171 -rtsopts
170 -with-rtsopts=-N
172 -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 @@
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-2105 (haskellNix.nixpkgsArgs // { inherit system; })
3+, pkgs ? import haskellNix.sources.nixpkgs-2311 (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; };
9
11
10 hsPkgs = pkgs.haskell-nix.stackProject {
12 hsPkgs = pkgs.haskell-nix.stackProject {
11 src = nix-filter {
13 src = nix-filter {
@@ -38,7 +40,7 @@ let
38 (inDirectory ./src)
40 (inDirectory ./src)
39 (inDirectory ./app)
41 (inDirectory ./app)
40 (inDirectory ./github-action)
42 (inDirectory ./github-action)
41− ./awsm-css/dist/awsm.min.css
43+ ./css/awsm.min.css
42 ./LICENSE
44 ./LICENSE
43 ];
45 ];
44 };
46 };
@@ -97,6 +99,18 @@ let
97 };
99 };
98
100
99 WindowsCompaRESTBin = hsPkgs.projectCross.mingwW64.hsPkgs.compaREST.components.exes.compaREST;
101 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+ });
100in
114in
101{
115{
102 inherit
116 inherit
@@ -106,9 +120,6 @@ in
106 compaRESTBin
120 compaRESTBin
107 hsPkgs
121 hsPkgs
108 macOSCompaRESTBundle
122 macOSCompaRESTBundle
109− WindowsCompaRESTBin;
123+ WindowsCompaRESTBin
110−
124+ test;
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;
114}
125}
nix/ci.nix+6−1
@@ -1,6 +1,11 @@
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
4pkgs.mkShell {
9pkgs.mkShell {
5− packages = [ pkgs.haskellPackages.fourmolu ];
10+ packages = [ pkgs.haskellPackages.fourmolu diff-yaml yq ];
6}
11}
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 @@
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": "50c6984263f14c110551a74d36020d0f39160019",
8+ "rev": "d7f95903c84a5a50d6fe0844280da82c3c81680a",
9− "sha256": "1nbv78127dq01vyhgaw7l6hnz2qdsv115vv2gy4vvayh0y39km91",
9+ "sha256": "02870rk4sx44lwwa0k20iwdhqcx0ayz34yb3b0qy045p22q45815",
10 "type": "tarball",
10 "type": "tarball",
11− "url": "https://github.com/input-output-hk/haskell.nix/archive/50c6984263f14c110551a74d36020d0f39160019.tar.gz",
11+ "url": "https://github.com/input-output-hk/haskell.nix/archive/d7f95903c84a5a50d6fe0844280da82c3c81680a.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": "9cb7ef336bb71fd1ca84fc7f2dff15ef4b033f2a",
20+ "rev": "f7c538837892dd2eb83567c9f380a11efb59b53f",
21− "sha256": "1ajyqr8zka1zlb25jx1v4xys3zqmdy3prbm1vxlid6ah27a8qnzh",
21+ "sha256": "0xl33k24vfc29cg9lnp95kvcq69qbq5fzb7jk9ig4lgrhaarh651",
22 "type": "tarball",
22 "type": "tarball",
23− "url": "https://github.com/nmattia/niv/archive/9cb7ef336bb71fd1ca84fc7f2dff15ef4b033f2a.tar.gz",
23+ "url": "https://github.com/nmattia/niv/archive/f7c538837892dd2eb83567c9f380a11efb59b53f.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": "master",
27+ "branch": "main",
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": "38bc843f1ce76958a9f6f0a1e4e3455221c8ecf6",
32+ "rev": "3342559a24e85fc164b295c3444e8a139924675b",
33− "sha256": "1lgznp706q5ngyl4zm39j0dlrpam2ds5miiwmc9j9vq4jg5z8sfg",
33+ "sha256": "08xia32g5jzaiyhfl3kzxslzbr4w1i56i0mhy5gpfggv8gqy8sym",
34 "type": "tarball",
34 "type": "tarball",
35− "url": "https://github.com/numtide/nix-filter/archive/38bc843f1ce76958a9f6f0a1e4e3455221c8ecf6.tar.gz",
35+ "url": "https://github.com/numtide/nix-filter/archive/3342559a24e85fc164b295c3444e8a139924675b.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": "276f639ac2cbfa55beb554e13cc091ecf8a65b19",
44+ "rev": "bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7",
45− "sha256": "1y4ddnwb6y2l0lbs3661ymjlj3m9r2ibv6pfajjdyarmjb7qph1c",
45+ "sha256": "0ivvwdmg9fipj6ylq5ipxqpb0xnz6hsx3lyn377jacfpiqi9w0cv",
46 "type": "tarball",
46 "type": "tarball",
47− "url": "https://github.com/NixOS/nixpkgs/archive/276f639ac2cbfa55beb554e13cc091ecf8a65b19.tar.gz",
47+ "url": "https://github.com/NixOS/nixpkgs/archive/bf038bd724982de67a2ee9a6b2f1fcb7d6a87bd7.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.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+})
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
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.HashMap.Strict as HM
26+import qualified Data.Aeson.Key as Key
27+import qualified Data.Aeson.KeyMap as KeyMap
27import Data.Kind
28import Data.Kind
28import qualified Data.Map as M
29import qualified Data.Map as M
29import Data.Monoid
30import Data.Monoid
@@ -256,7 +257,7 @@ newtype MergableObject = MergableObject {getMergableObject :: Object}
256
257
257instance Semigroup MergableObject where
258instance Semigroup MergableObject where
258 (MergableObject x) <> (MergableObject y) =
259 (MergableObject x) <> (MergableObject y) =
259− MergableObject $ HM.unionWith mergeValue x y
260+ MergableObject $ KeyMap.unionWith mergeValue x y
260 where
261 where
261 mergeValue :: Value -> Value -> Value
262 mergeValue :: Value -> Value -> Value
262 mergeValue (Object a) (Object b) =
263 mergeValue (Object a) (Object b) =
@@ -271,6 +272,6 @@ instance Monoid MergableObject where
271
272
272traceObject :: Paths q r a -> Value -> Object
273traceObject :: Paths q r a -> Value -> Object
273traceObject Root (Object o) = o
274traceObject Root (Object o) = o
274−traceObject Root v = HM.singleton "root" v
275+traceObject Root v = KeyMap.singleton "root" v
275traceObject (root `Snoc` s) v =
276traceObject (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 _) =
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 "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)
38tracedSecuritySchemes oa =
38tracedSecuritySchemes oa =
39 traced
39 traced
40 (ask oa >>> step ComponentsSecurityScheme)
40 (ask oa >>> step ComponentsSecurityScheme)
41− (_componentsSecuritySchemes . _openApiComponents . extract $ oa)
41+ (unSecurityDefinitions . _componentsSecuritySchemes . _openApiComponents . extract $ oa)
42+ where unSecurityDefinitions (SecurityDefinitions ds) = ds
42
43
43tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
44tracedResponses :: Traced OpenApi -> Traced (Definitions Response)
44tracedResponses oa =
45tracedResponses 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.Writer
8+import Control.Monad (when,unless)
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+7−6
@@ -18,10 +18,11 @@ 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
21import qualified Data.ByteString.Lazy as BSL
23import qualified Data.ByteString.Lazy as BSL
22import qualified Data.Foldable as F
24import qualified Data.Foldable as F
23import Data.Functor
25import Data.Functor
24−import qualified Data.HashMap.Strict as HM
25import Data.Int
26import Data.Int
26import Data.Kind
27import Data.Kind
27import qualified Data.Map as M
28import qualified Data.Map as M
@@ -39,7 +40,7 @@ import Data.Text (Text)
39import qualified Data.Text as T
40import qualified Data.Text as T
40import qualified Data.Text.Encoding as T
41import qualified Data.Text.Encoding as T
41import Data.Typeable
42import Data.Typeable
42−import Text.Pandoc.Builder hiding (Format, Null)
43+import Text.Pandoc.Builder hiding (Format)
43import Text.Regex.Pcre2
44import Text.Regex.Pcre2
44
45
45data Bound a = Exclusive !a | Inclusive !a
46data Bound a = Exclusive !a | Inclusive !a
@@ -177,10 +178,10 @@ satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
177satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
178satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
178satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
179satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
179satisfiesTyped (TObject o) (Properties props additional _) =
180satisfiesTyped (TObject o) (Properties props additional _) =
180− all (`HM.member` o) (M.keys (M.filter propRequired props))
181+ all (`KeyMap.member` o) (map Key.fromText $ M.keys (M.filter propRequired props))
181− && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
182+ && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup (Key.toText k) props) (KeyMap.toList o)
182−satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (HM.size o) <= m
183+satisfiesTyped (TObject o) (MaxProperties m) = fromIntegral (KeyMap.size o) <= m
183−satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (HM.size o) >= m
184+satisfiesTyped (TObject o) (MinProperties m) = fromIntegral (KeyMap.size o) >= m
184
185
185checkNumberFormat :: Format -> Scientific -> Bool
186checkNumberFormat :: Format -> Scientific -> Bool
186checkNumberFormat "int32" (toRational -> n) =
187checkNumberFormat "int32" (toRational -> n) =
src/Data/OpenApi/Compare/Validate/Schema/Partition.hs+4−1
@@ -16,6 +16,7 @@ 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)
19import Control.Monad.Reader hiding (ask)
20import Control.Monad.Reader hiding (ask)
20import qualified Control.Monad.Reader as R
21import qualified Control.Monad.Reader as R
21import Control.Monad.State
22import Control.Monad.State
@@ -31,6 +32,7 @@ import qualified Data.List as L
31import qualified Data.List.NonEmpty as NE
32import qualified Data.List.NonEmpty as NE
32import qualified Data.Map as M
33import qualified Data.Map as M
33import Data.Maybe
34import Data.Maybe
35+import Data.Monoid
34import Data.OpenApi
36import Data.OpenApi
35import Data.OpenApi.Compare.Memo
37import Data.OpenApi.Compare.Memo
36import Data.OpenApi.Compare.References
38import Data.OpenApi.Compare.References
@@ -43,7 +45,8 @@ import Data.Ord
43import qualified Data.Set as S
45import qualified Data.Set as S
44import Data.Text (Text)
46import Data.Text (Text)
45import qualified Data.Text as T
47import qualified Data.Text as T
48+import Data.Traversable (forM)
46−import Text.Pandoc.Builder hiding (Format, Null)
49+import Text.Pandoc.Builder hiding (Format)
47
50
48data PartitionData
51data PartitionData
49 = DByEnumValue (DNF (S.Set A.Value))
52 = DByEnumValue (DNF (S.Set A.Value))
src/Data/OpenApi/Compare/Validate/Schema/Process.hs+2
@@ -13,6 +13,7 @@ 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
16import Data.OpenApi hiding (get)
17import Data.OpenApi hiding (get)
17import Data.OpenApi.Compare.Behavior
18import Data.OpenApi.Compare.Behavior
18import Data.OpenApi.Compare.Memo
19import Data.OpenApi.Compare.Memo
@@ -28,6 +29,7 @@ import Data.OpenApi.Compare.Validate.Schema.Traced
28import Data.OpenApi.Compare.Validate.Schema.TypedJson
29import Data.OpenApi.Compare.Validate.Schema.TypedJson
29import Data.Ord
30import Data.Ord
30import qualified Data.Set as S
31import qualified Data.Set as S
32+import Data.Traversable (forM)
31
33
32-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
34-- | A fake writer monad that doesn't actually record anything and allows lazy recursion.
33newtype Silent w a = Silent {runSilent :: a}
35newtype Silent w a = Silent {runSilent :: a}
stack.yaml+16−4
@@ -1,11 +1,23 @@
1−resolver: lts-18.27
1+resolver: lts-22.34
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
7 - open-union-0.4.0.0
12 - open-union-0.4.0.0
13+ - th-abstraction-0.7.0.0
8 - type-fun-0.1.3
14 - type-fun-0.1.3
9− - github-0.26
15+ - typerep-map-0.6.0.0
10− - base16-bytestring-0.1.1.7
16+
11− - http-link-header-1.0.3.1
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
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 = do
62+goldenInputsTree name filepath golden inp f =
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", "-u", ref, new])
75+ (\ref new -> ["diff-yaml", ref, new])
76 (path </> golden)
76 (path </> golden)
77 (f t)
77 (f t)
78
78