A flake checker (treefmt & nix-unit) for testing other flakes with zero dependencies.

init

+515
+13
.github/workflows/test.yml
··· 1 + on: 2 + pull_request: 3 + push: 4 + branches: [main] 5 + jobs: 6 + flake-check: 7 + name: nix flake check 8 + runs-on: ubuntu-latest 9 + steps: 10 + - uses: actions/checkout@v4 11 + - uses: cachix/install-nix-action@v30 12 + - run: nix flake check --override-input mate path:$PWD/ 13 + - run: nix flake check --override-input mate path:$PWD/mate
+201
LICENSE
··· 1 + Apache License 2 + Version 2.0, January 2004 3 + http://www.apache.org/licenses/ 4 + 5 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 + 7 + 1. Definitions. 8 + 9 + "License" shall mean the terms and conditions for use, reproduction, 10 + and distribution as defined by Sections 1 through 9 of this document. 11 + 12 + "Licensor" shall mean the copyright owner or entity authorized by 13 + the copyright owner that is granting the License. 14 + 15 + "Legal Entity" shall mean the union of the acting entity and all 16 + other entities that control, are controlled by, or are under common 17 + control with that entity. For the purposes of this definition, 18 + "control" means (i) the power, direct or indirect, to cause the 19 + direction or management of such entity, whether by contract or 20 + otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 + outstanding shares, or (iii) beneficial ownership of such entity. 22 + 23 + "You" (or "Your") shall mean an individual or Legal Entity 24 + exercising permissions granted by this License. 25 + 26 + "Source" form shall mean the preferred form for making modifications, 27 + including but not limited to software source code, documentation 28 + source, and configuration files. 29 + 30 + "Object" form shall mean any form resulting from mechanical 31 + transformation or translation of a Source form, including but 32 + not limited to compiled object code, generated documentation, 33 + and conversions to other media types. 34 + 35 + "Work" shall mean the work of authorship, whether in Source or 36 + Object form, made available under the License, as indicated by a 37 + copyright notice that is included in or attached to the work 38 + (an example is provided in the Appendix below). 39 + 40 + "Derivative Works" shall mean any work, whether in Source or Object 41 + form, that is based on (or derived from) the Work and for which the 42 + editorial revisions, annotations, elaborations, or other modifications 43 + represent, as a whole, an original work of authorship. For the purposes 44 + of this License, Derivative Works shall not include works that remain 45 + separable from, or merely link (or bind by name) to the interfaces of, 46 + the Work and Derivative Works thereof. 47 + 48 + "Contribution" shall mean any work of authorship, including 49 + the original version of the Work and any modifications or additions 50 + to that Work or Derivative Works thereof, that is intentionally 51 + submitted to Licensor for inclusion in the Work by the copyright owner 52 + or by an individual or Legal Entity authorized to submit on behalf of 53 + the copyright owner. For the purposes of this definition, "submitted" 54 + means any form of electronic, verbal, or written communication sent 55 + to the Licensor or its representatives, including but not limited to 56 + communication on electronic mailing lists, source code control systems, 57 + and issue tracking systems that are managed by, or on behalf of, the 58 + Licensor for the purpose of discussing and improving the Work, but 59 + excluding communication that is conspicuously marked or otherwise 60 + designated in writing by the copyright owner as "Not a Contribution." 61 + 62 + "Contributor" shall mean Licensor and any individual or Legal Entity 63 + on behalf of whom a Contribution has been received by Licensor and 64 + subsequently incorporated within the Work. 65 + 66 + 2. Grant of Copyright License. Subject to the terms and conditions of 67 + this License, each Contributor hereby grants to You a perpetual, 68 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 + copyright license to reproduce, prepare Derivative Works of, 70 + publicly display, publicly perform, sublicense, and distribute the 71 + Work and such Derivative Works in Source or Object form. 72 + 73 + 3. Grant of Patent License. Subject to the terms and conditions of 74 + this License, each Contributor hereby grants to You a perpetual, 75 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 + (except as stated in this section) patent license to make, have made, 77 + use, offer to sell, sell, import, and otherwise transfer the Work, 78 + where such license applies only to those patent claims licensable 79 + by such Contributor that are necessarily infringed by their 80 + Contribution(s) alone or by combination of their Contribution(s) 81 + with the Work to which such Contribution(s) was submitted. If You 82 + institute patent litigation against any entity (including a 83 + cross-claim or counterclaim in a lawsuit) alleging that the Work 84 + or a Contribution incorporated within the Work constitutes direct 85 + or contributory patent infringement, then any patent licenses 86 + granted to You under this License for that Work shall terminate 87 + as of the date such litigation is filed. 88 + 89 + 4. Redistribution. You may reproduce and distribute copies of the 90 + Work or Derivative Works thereof in any medium, with or without 91 + modifications, and in Source or Object form, provided that You 92 + meet the following conditions: 93 + 94 + (a) You must give any other recipients of the Work or 95 + Derivative Works a copy of this License; and 96 + 97 + (b) You must cause any modified files to carry prominent notices 98 + stating that You changed the files; and 99 + 100 + (c) You must retain, in the Source form of any Derivative Works 101 + that You distribute, all copyright, patent, trademark, and 102 + attribution notices from the Source form of the Work, 103 + excluding those notices that do not pertain to any part of 104 + the Derivative Works; and 105 + 106 + (d) If the Work includes a "NOTICE" text file as part of its 107 + distribution, then any Derivative Works that You distribute must 108 + include a readable copy of the attribution notices contained 109 + within such NOTICE file, excluding those notices that do not 110 + pertain to any part of the Derivative Works, in at least one 111 + of the following places: within a NOTICE text file distributed 112 + as part of the Derivative Works; within the Source form or 113 + documentation, if provided along with the Derivative Works; or, 114 + within a display generated by the Derivative Works, if and 115 + wherever such third-party notices normally appear. The contents 116 + of the NOTICE file are for informational purposes only and 117 + do not modify the License. You may add Your own attribution 118 + notices within Derivative Works that You distribute, alongside 119 + or as an addendum to the NOTICE text from the Work, provided 120 + that such additional attribution notices cannot be construed 121 + as modifying the License. 122 + 123 + You may add Your own copyright statement to Your modifications and 124 + may provide additional or different license terms and conditions 125 + for use, reproduction, or distribution of Your modifications, or 126 + for any such Derivative Works as a whole, provided Your use, 127 + reproduction, and distribution of the Work otherwise complies with 128 + the conditions stated in this License. 129 + 130 + 5. Submission of Contributions. Unless You explicitly state otherwise, 131 + any Contribution intentionally submitted for inclusion in the Work 132 + by You to the Licensor shall be under the terms and conditions of 133 + this License, without any additional terms or conditions. 134 + Notwithstanding the above, nothing herein shall supersede or modify 135 + the terms of any separate license agreement you may have executed 136 + with Licensor regarding such Contributions. 137 + 138 + 6. Trademarks. This License does not grant permission to use the trade 139 + names, trademarks, service marks, or product names of the Licensor, 140 + except as required for reasonable and customary use in describing the 141 + origin of the Work and reproducing the content of the NOTICE file. 142 + 143 + 7. Disclaimer of Warranty. Unless required by applicable law or 144 + agreed to in writing, Licensor provides the Work (and each 145 + Contributor provides its Contributions) on an "AS IS" BASIS, 146 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 + implied, including, without limitation, any warranties or conditions 148 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 + PARTICULAR PURPOSE. You are solely responsible for determining the 150 + appropriateness of using or redistributing the Work and assume any 151 + risks associated with Your exercise of permissions under this License. 152 + 153 + 8. Limitation of Liability. In no event and under no legal theory, 154 + whether in tort (including negligence), contract, or otherwise, 155 + unless required by applicable law (such as deliberate and grossly 156 + negligent acts) or agreed to in writing, shall any Contributor be 157 + liable to You for damages, including any direct, indirect, special, 158 + incidental, or consequential damages of any character arising as a 159 + result of this License or out of the use or inability to use the 160 + Work (including but not limited to damages for loss of goodwill, 161 + work stoppage, computer failure or malfunction, or any and all 162 + other commercial damages or losses), even if such Contributor 163 + has been advised of the possibility of such damages. 164 + 165 + 9. Accepting Warranty or Additional Liability. While redistributing 166 + the Work or Derivative Works thereof, You may choose to offer, 167 + and charge a fee for, acceptance of support, warranty, indemnity, 168 + or other liability obligations and/or rights consistent with this 169 + License. However, in accepting such obligations, You may act only 170 + on Your own behalf and on Your sole responsibility, not on behalf 171 + of any other Contributor, and only if You agree to indemnify, 172 + defend, and hold each Contributor harmless for any liability 173 + incurred by, or claims asserted against, such Contributor by reason 174 + of your accepting any such warranty or additional liability. 175 + 176 + END OF TERMS AND CONDITIONS 177 + 178 + APPENDIX: How to apply the Apache License to your work. 179 + 180 + To apply the Apache License to your work, attach the following 181 + boilerplate notice, with the fields enclosed by brackets "[]" 182 + replaced with your own identifying information. (Don't include 183 + the brackets!) The text should be enclosed in the appropriate 184 + comment syntax for the file format. We also recommend that a 185 + file or class name and description of purpose be included on the 186 + same "printed page" as the copyright notice for easier 187 + identification within third-party archives. 188 + 189 + Copyright [yyyy] [name of copyright owner] 190 + 191 + Licensed under the Apache License, Version 2.0 (the "License"); 192 + you may not use this file except in compliance with the License. 193 + You may obtain a copy of the License at 194 + 195 + http://www.apache.org/licenses/LICENSE-2.0 196 + 197 + Unless required by applicable law or agreed to in writing, software 198 + distributed under the License is distributed on an "AS IS" BASIS, 199 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 + See the License for the specific language governing permissions and 201 + limitations under the License.
+28
README.md
··· 1 + # Checkmate - A flake checker (treefmt & nix-unit) for testing other flakes with zero dependencies. 2 + 3 + Checks include: 4 + 5 + - treefmt - nixfmt, deadnix, mdformat, yamlfmt. See `treefmt.nix`. 6 + 7 + - nix-unit - The flake being checked (ie, `inputs.mate`) is expected to expose the following attribute: 8 + 9 + ```nix 10 + # example from mate/flake.nix 11 + 12 + # Expose a `nix-unit` module with `perSystem` class. 13 + # see https://flake.parts/options/flake-parts-modules.html 14 + modules.perSystem.nix-unit = { lib, ... }: 15 + { 16 + nix-unit.tests.checkmate-mate."test lib works" = { 17 + expr = lib.removePrefix "hello" "hello.nix"; 18 + expected = ".nix"; 19 + }; 20 + }; 21 + ``` 22 + 23 + ### CI Usage 24 + 25 + ``` 26 + # On your github action 27 + nix check github:checkmate --override-input mate path:$PWD 28 + ```
+14
default.nix
··· 1 + { inputs, ... }: 2 + { 3 + imports = [ 4 + inputs.flake-parts.flakeModules.flakeModules 5 + inputs.flake-parts.flakeModules.modules 6 + inputs.nix-unit.modules.flake.default 7 + ./tests.nix 8 + ./treefmt.nix 9 + ]; 10 + 11 + systems = import inputs.systems; 12 + 13 + flake.flakeModules.default = ./default.nix; 14 + }
+182
flake.lock
··· 1 + { 2 + "nodes": { 3 + "flake-parts": { 4 + "inputs": { 5 + "nixpkgs-lib": [ 6 + "nixpkgs-lib" 7 + ] 8 + }, 9 + "locked": { 10 + "lastModified": 1741352980, 11 + "narHash": "sha256-+u2UunDA4Cl5Fci3m7S643HzKmIDAe+fiXrLqYsR2fs=", 12 + "owner": "hercules-ci", 13 + "repo": "flake-parts", 14 + "rev": "f4330d22f1c5d2ba72d3d22df5597d123fdb60a9", 15 + "type": "github" 16 + }, 17 + "original": { 18 + "owner": "hercules-ci", 19 + "repo": "flake-parts", 20 + "type": "github" 21 + } 22 + }, 23 + "mate": { 24 + "locked": { 25 + "lastModified": 1, 26 + "narHash": "sha256-1wflc1LQQuEns7EIQhh+8d8rWs/frfUCIGAK5BTRzIw=", 27 + "path": "mate", 28 + "type": "path" 29 + }, 30 + "original": { 31 + "path": "mate", 32 + "type": "path" 33 + } 34 + }, 35 + "nix-github-actions": { 36 + "inputs": { 37 + "nixpkgs": [ 38 + "nix-unit", 39 + "nixpkgs" 40 + ] 41 + }, 42 + "locked": { 43 + "lastModified": 1731952509, 44 + "narHash": "sha256-p4gB3Rhw8R6Ak4eMl8pqjCPOLCZRqaehZxdZ/mbFClM=", 45 + "owner": "nix-community", 46 + "repo": "nix-github-actions", 47 + "rev": "7b5f051df789b6b20d259924d349a9ba3319b226", 48 + "type": "github" 49 + }, 50 + "original": { 51 + "owner": "nix-community", 52 + "repo": "nix-github-actions", 53 + "type": "github" 54 + } 55 + }, 56 + "nix-unit": { 57 + "inputs": { 58 + "flake-parts": [ 59 + "flake-parts" 60 + ], 61 + "nix-github-actions": "nix-github-actions", 62 + "nixpkgs": [ 63 + "nixpkgs" 64 + ], 65 + "treefmt-nix": "treefmt-nix" 66 + }, 67 + "locked": { 68 + "lastModified": 1741624954, 69 + "narHash": "sha256-VjLS010BEfwuK343Dst08NnQNS8SRtVCDkz1zTsHuvI=", 70 + "owner": "nix-community", 71 + "repo": "nix-unit", 72 + "rev": "e9d81f6cffe67681e7c04a967d29f18c2c540af5", 73 + "type": "github" 74 + }, 75 + "original": { 76 + "owner": "nix-community", 77 + "repo": "nix-unit", 78 + "type": "github" 79 + } 80 + }, 81 + "nixpkgs": { 82 + "locked": { 83 + "lastModified": 1731603435, 84 + "narHash": "sha256-CqCX4JG7UiHvkrBTpYC3wcEurvbtTADLbo3Ns2CEoL8=", 85 + "owner": "nixos", 86 + "repo": "nixpkgs", 87 + "rev": "8b27c1239e5c421a2bbc2c65d52e4a6fbf2ff296", 88 + "type": "github" 89 + }, 90 + "original": { 91 + "owner": "nixos", 92 + "ref": "24.11", 93 + "repo": "nixpkgs", 94 + "type": "github" 95 + } 96 + }, 97 + "nixpkgs-lib": { 98 + "locked": { 99 + "lastModified": 1741481724, 100 + "narHash": "sha256-XkDGJ3UJ06OkyHiKX20wLIyqrVl8J9ppccSevDoZYg0=", 101 + "owner": "nix-community", 102 + "repo": "nixpkgs.lib", 103 + "rev": "4264843d949bd5fb28a96f47842b634919aa58fa", 104 + "type": "github" 105 + }, 106 + "original": { 107 + "owner": "nix-community", 108 + "repo": "nixpkgs.lib", 109 + "type": "github" 110 + } 111 + }, 112 + "root": { 113 + "inputs": { 114 + "flake-parts": "flake-parts", 115 + "mate": "mate", 116 + "nix-unit": "nix-unit", 117 + "nixpkgs": "nixpkgs", 118 + "nixpkgs-lib": "nixpkgs-lib", 119 + "systems": "systems", 120 + "treefmt-nix": "treefmt-nix_2" 121 + } 122 + }, 123 + "systems": { 124 + "locked": { 125 + "lastModified": 1681028828, 126 + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 127 + "owner": "nix-systems", 128 + "repo": "default", 129 + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 130 + "type": "github" 131 + }, 132 + "original": { 133 + "owner": "nix-systems", 134 + "repo": "default", 135 + "type": "github" 136 + } 137 + }, 138 + "treefmt-nix": { 139 + "inputs": { 140 + "nixpkgs": [ 141 + "nix-unit", 142 + "nixpkgs" 143 + ] 144 + }, 145 + "locked": { 146 + "lastModified": 1733662930, 147 + "narHash": "sha256-9qOp6jNdezzLMxwwXaXZWPXosHbNqno+f7Ii/xftqZ8=", 148 + "owner": "numtide", 149 + "repo": "treefmt-nix", 150 + "rev": "357cda84af1d74626afb7fb3bc12d6957167cda9", 151 + "type": "github" 152 + }, 153 + "original": { 154 + "owner": "numtide", 155 + "repo": "treefmt-nix", 156 + "type": "github" 157 + } 158 + }, 159 + "treefmt-nix_2": { 160 + "inputs": { 161 + "nixpkgs": [ 162 + "nixpkgs" 163 + ] 164 + }, 165 + "locked": { 166 + "lastModified": 1739829690, 167 + "narHash": "sha256-mL1szCeIsjh6Khn3nH2cYtwO5YXG6gBiTw1A30iGeDU=", 168 + "owner": "numtide", 169 + "repo": "treefmt-nix", 170 + "rev": "3d0579f5cc93436052d94b73925b48973a104204", 171 + "type": "github" 172 + }, 173 + "original": { 174 + "owner": "numtide", 175 + "repo": "treefmt-nix", 176 + "type": "github" 177 + } 178 + } 179 + }, 180 + "root": "root", 181 + "version": 7 182 + }
+19
flake.nix
··· 1 + { 2 + inputs = { 3 + mate.url = "path:mate"; 4 + 5 + nixpkgs.url = "github:nixos/nixpkgs/24.11"; 6 + systems.url = "github:nix-systems/default"; 7 + flake-parts.url = "github:hercules-ci/flake-parts"; 8 + flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs-lib"; 9 + nixpkgs-lib.url = "github:nix-community/nixpkgs.lib"; 10 + nix-unit.url = "github:nix-community/nix-unit"; 11 + nix-unit.inputs.nixpkgs.follows = "nixpkgs"; 12 + nix-unit.inputs.flake-parts.follows = "flake-parts"; 13 + treefmt-nix.url = "github:numtide/treefmt-nix"; 14 + treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; 15 + }; 16 + 17 + outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ./.; 18 + 19 + }
+15
mate/flake.nix
··· 1 + { 2 + outputs = _: { 3 + 4 + # Expose a `nix-unit` module with `perSystem` class. 5 + # see https://flake.parts/options/flake-parts-modules.html 6 + modules.perSystem.nix-unit = 7 + { lib, ... }: 8 + { 9 + nix-unit.tests.checkmate-mate."test lib works" = { 10 + expr = lib.removePrefix "hello" "hello.nix"; 11 + expected = ".nix"; 12 + }; 13 + }; 14 + }; 15 + }
+21
tests.nix
··· 1 + { inputs, ... }: 2 + { 3 + perSystem = ( 4 + { ... }: 5 + { 6 + imports = [ inputs.mate.modules.perSystem.nix-unit ]; 7 + nix-unit = { 8 + inherit inputs; 9 + }; 10 + } 11 + ); 12 + 13 + flake.modules.perSystem.nix-unit = 14 + { lib, ... }: 15 + { 16 + nix-unit.tests.checkmate-core."test lib works" = { 17 + expr = lib.removeSuffix ".nix" "hello.nix"; 18 + expected = "hello"; 19 + }; 20 + }; 21 + }
+22
treefmt.nix
··· 1 + { inputs, ... }: 2 + { 3 + perSystem = ( 4 + { pkgs, ... }: 5 + let 6 + treefmt = inputs.treefmt-nix.lib.evalModule pkgs { 7 + projectRootFile = "flake.nix"; 8 + programs.nixfmt.enable = true; 9 + programs.nixfmt.excludes = [ ".direnv" ]; 10 + programs.deadnix.enable = true; 11 + programs.mdformat.enable = true; 12 + programs.yamlfmt.enable = true; 13 + }; 14 + treefmt-wrapper = treefmt.config.build.wrapper; 15 + treefmt-check = treefmt.config.build.check inputs.mate; 16 + in 17 + { 18 + packages.checkmate-treefmt = treefmt-wrapper; 19 + checks.checkmate-treefmt = treefmt-check; 20 + } 21 + ); 22 + }