nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at master 210 lines 5.0 kB view raw
1{ 2 old, 3 new, 4 specifiedGems, 5 withData ? false, 6 # Use for `lib`. 7 pkgs ? import ../.. { }, 8}: 9 10# Rename inputs to re-use those names. 11let 12 old' = old; 13 new' = new; 14 specifiedGems' = specifiedGems; 15in 16 17let 18 inherit (builtins) 19 attrNames 20 concatStrings 21 filter 22 genList 23 isNull 24 length 25 stringLength 26 toJSON 27 ; 28 inherit (pkgs.lib) 29 concatMapStringsSep 30 concatStringsSep 31 intersectLists 32 splitString 33 subtractLists 34 versionOlder 35 ; 36 37 # Keeps non-nulls in a list. 38 # Mirroring Ruby's `Array#compact`. 39 compact = filter (v: !(isNull v)); 40 41 # The full gemsets attribute sets. 42 old = import old'; 43 new = import new'; 44 45 # All gem names. 46 allGems = attrNames (old // new); 47 48 # Gems found in both old and new. 49 keptGems = intersectLists (attrNames old) (attrNames new); 50 51 # Gems added or removed. 52 addedOrRemovedGems = subtractLists keptGems allGems; 53 54 # Gems specified in Gemfile. 55 specifiedGems = splitString "\n" specifiedGems'; 56 57 # Gems that were not specified. 58 nonSpecifiedGems = subtractLists specifiedGems keptGems; 59 60 # Generates data for the summary tables 61 # This is also used for `failedChecks`. 62 versionChangeDataFor = 63 gems: 64 let 65 results = map ( 66 name: 67 let 68 oldv = old.${name}.version or null; 69 newv = new.${name}.version or null; 70 in 71 if newv == oldv then 72 # Nothing changed. This will be filtered out. 73 null 74 else 75 { 76 inherit 77 name 78 ; 79 old = oldv; 80 new = newv; 81 } 82 ) gems; 83 in 84 compact results; 85 86 checkRegression = 87 entry: message: 88 let 89 isRemoval = isNull entry.new; 90 isAddition = isNull entry.old; 91 isRegression = versionOlder entry.new entry.old; 92 in 93 if 94 # Gems being added or gems being removed won't cause failures. 95 !isRemoval 96 && !isAddition 97 # A version being regressed is a failure. 98 && isRegression 99 then 100 message 101 else 102 null; 103 104 # This is a list of error messages to float up to the user. 105 # An empty list means no error. 106 failedChecks = compact ( 107 [ ] 108 ++ (map ( 109 entry: 110 checkRegression entry "Version regression for specified gem ${toJSON entry.name}, from ${toJSON entry.old} to ${toJSON entry.new}" 111 ) (versionChangeDataFor specifiedGems)) 112 ++ (map ( 113 entry: 114 checkRegression entry "Version regression for non-specified gem ${toJSON entry.name}, from ${toJSON entry.old} to ${toJSON entry.new}" 115 ) (versionChangeDataFor nonSpecifiedGems)) 116 ); 117 118 # Formats a version number (or null) as markdown. 119 gemVersionToMD = version: if isNull version then "*N/A*" else "`${version}`"; 120 121 # Formats a `versionChangeDataFor` output as markdown. 122 versionChangeDataMD = 123 gems: 124 let 125 result = versionChangeDataFor gems; 126 in 127 map ( 128 row: 129 [ row.name ] 130 ++ (map gemVersionToMD [ 131 row.old 132 row.new 133 ]) 134 ) result; 135 136 # Given a list of columns, and a list of list of column data, 137 # generates the markup for markdown table. 138 mkTable = 139 columns: entries: 140 let 141 entryToMarkdown = columns: "| ${concatStringsSep " | " columns} |"; 142 sep = entryToMarkdown (map (_: "---") columns); 143 in 144 if length entries == 0 then 145 "> *No data...*" 146 else 147 '' 148 ${entryToMarkdown columns} 149 ${sep} 150 ${concatMapStringsSep "\n" entryToMarkdown entries} 151 ''; 152 153 # The markdown report is built as this string. 154 report = '' 155 <!-- 156 ---------------------------------------------- 157 NOTE: You must copy this whole report section 158 to your pull request! 159 ---------------------------------------------- 160 --> 161 162 #### Nixpkgs Ruby packages update report 163 164 **Specified gems changed:** 165 166 ${mkTable [ "Name" "old" "new" ] (versionChangeDataMD specifiedGems)} 167 168 **Gems added or removed:** 169 170 ${mkTable [ "Name" "old" "new" ] (versionChangeDataMD addedOrRemovedGems)} 171 172 <details> 173 174 <summary><strong>(Non-specified gem changes)</strong></summary> 175 176 ${mkTable [ "Name" "old" "new" ] (versionChangeDataMD nonSpecifiedGems)} 177 178 </details> 179 180 <!-- --------------- End ----------------- --> 181 ''; 182in 183if (length failedChecks) > 0 then 184 # Fail the update script via `abort` on checks failure. 185 builtins.abort '' 186 ${"\n"}Gem upgrade aborted with the following failures: 187 188 ${concatMapStringsSep "\n" (msg: " - ${msg}") failedChecks} 189 '' 190else 191 # Output the report. 192 builtins.trace "(Report follows...)\n\n${report}" ( 193 # And if `withData` is true, expose the data for REPL usage. 194 if withData then 195 { 196 inherit 197 # The gemsets used 198 old 199 new 200 # The lists of gems 201 allGems 202 specifiedGems 203 nonSpecifiedGems 204 addedOrRemovedGems 205 keptGems 206 ; 207 } 208 else 209 null 210 )