git.delta.rocks / jrsonnet / refs/commits / 7d81a164bfcd

difftreelog

feat(jrb) compute hash

plxxxlvtYaroslav Bolyukin2026-07-31parent: #b5fcc26.patch.diff
in: master

5 files changed

modifiedcmds/jrb/src/main.rsdiffbeforeafterboth
18 /// The directory used to cache packages in.18 /// The directory used to cache packages in.
19 #[clap(long, default_value = "vendor")]19 #[clap(long, default_value = "vendor")]
20 jsonnetpkg_home: PathBuf,20 jsonnetpkg_home: PathBuf,
21 /// Accept checksums of trees jsonnet-bundler hashes incorrectly. Correct
22 /// checksums are written back, so this is only needed once per lockfile.
23 #[clap(long)]
24 compat: bool,
21 #[clap(subcommand)]25 #[clap(subcommand)]
22 command: Command,26 command: Command,
23}27}
103 manifest: &JsonnetFile,107 manifest: &JsonnetFile,
104 lock: Option<&JsonnetFile>,108 lock: Option<&JsonnetFile>,
105 vendor_dir: &Path,109 vendor_dir: &Path,
106 dry_run: bool,110 opts: install::Options,
107) {111) {
112 let dry_run = opts.dry_run;
108 let new_lock = install::install(manifest, lock, vendor_dir, dry_run).unwrap_or_else(|e| {113 let new_lock = install::install(manifest, lock, vendor_dir, opts).unwrap_or_else(|e| {
109 error!("install failed: {e}");114 error!("install failed: {e}");
110 exit(1);115 exit(1);
111 });116 });
169 &manifest,
170 lock.as_ref(),
171 &opts.jsonnetpkg_home,
172 install::Options {
173 dry_run,
174 compat: opts.compat,
175 },
176 );
164 }177 }
165 Command::Update { uris, dry_run } => {178 Command::Update { uris, dry_run } => {
201 &manifest,
202 None,
203 &opts.jsonnetpkg_home,
204 install::Options {
205 dry_run,
206 compat: opts.compat,
207 },
208 );
188 }209 }
189 Command::Remove { names, dry_run } => {210 Command::Remove { names, dry_run } => {
modifiedcrates/jrsonnet-pkg/Cargo.tomldiffbeforeafterboth
29# Global cache dir29# Global cache dir
30directories.workspace = true30directories.workspace = true
31
32# Lockfile checksums
33sha2.workspace = true
34base64.workspace = true
3135
addedcrates/jrsonnet-pkg/src/install/hash.rsdiffbeforeafterboth

no changes

modifiedcrates/jrsonnet-pkg/src/install/mod.rsdiffbeforeafterboth
3pub mod accessor;3pub mod accessor;
4mod git;4mod git;
5mod github;5mod github;
6mod hash;
67
7use std::{8use std::{
8 collections::{BTreeMap, HashSet},9 collections::{BTreeMap, HashSet},
11 result,12 result,
12};13};
1314
14use camino::Utf8PathBuf;15use camino::{Utf8Path, Utf8PathBuf};
15use tracing::info;16use tracing::{info, warn};
1617
17use crate::jsonnet_bundler::{Dependency, GitScheme, GitSource, JsonnetFile, Source, SubDir};18use crate::{
19 install::hash::{Exclusions, Mode, hash_dir},
20 jsonnet_bundler::{Dependency, GitScheme, GitSource, JsonnetFile, Source, SubDir},
21};
1822
19pub const PKG_USER_AGENT: &str = "jrsonnet-pkg (https://delta.rocks/jrsonnet)";23pub const PKG_USER_AGENT: &str = "jrsonnet-pkg (https://delta.rocks/jrsonnet)";
2024
87 pub entries: BTreeMap<Utf8PathBuf, VendorSource>,91 pub entries: BTreeMap<Utf8PathBuf, VendorSource>,
88}92}
93
94#[derive(Debug, Clone, Copy, Default)]
95pub struct Options {
96 pub dry_run: bool,
97 /// Accept checksums of trees `jsonnet-bundler` hashes incorrectly. Correct
98 /// checksums are written back, so this is only needed once per lockfile.
99 pub compat: bool,
100}
89101
90pub fn install(102pub fn install(
91 manifest: &JsonnetFile,103 manifest: &JsonnetFile,
92 lock: Option<&JsonnetFile>,104 lock: Option<&JsonnetFile>,
93 vendor_dir: &Path,105 vendor_dir: &Path,
94 dry_run: bool,106 opts: Options,
95) -> Result<JsonnetFile, Error> {107) -> Result<JsonnetFile, Error> {
96 let plan = resolve(manifest, lock)?;108 let mut plan = resolve(manifest, lock)?;
97 execute(&plan, vendor_dir, dry_run)?;109 execute(&plan, vendor_dir, opts)?;
110 if !opts.dry_run {
111 update_sums(&mut plan, vendor_dir, opts.compat)?;
112 }
98 Ok(plan.lock)113 Ok(plan.lock)
99}114}
100115
138 ))153 ))
139}154}
140155
141fn is_up_to_date(dest: &Path, version: &str) -> bool {156fn is_up_to_date(
157 plan: &InstallPlan,
158 vendor_dir: &Path,
159 path: &Utf8PathBuf,
160 version: &str,
161 compat: bool,
162) -> bool {
163 let dest = vendor_dir.join(path);
142 fs::read_to_string(dest.join(VERSION_FILE)).is_ok_and(|v| v.trim() == version)164 if !fs::read_to_string(dest.join(VERSION_FILE)).is_ok_and(|v| v.trim() == version) {
165 return false;
166 }
167 // The vendored tree may have been modified since it was extracted.
168 let Some(expected) = locked_sum(plan, path) else {
169 return true;
170 };
171 let exclude = exclusions(&plan.entries, vendor_dir, path);
172 let matches =
173 |mode| hash_dir(&dest, &exclude, Some(version), mode).is_ok_and(|sum| sum == expected);
174 matches(Mode::Correct) || (compat && matches(Mode::JsonnetBundler))
143}175}
144176
145fn write_version(dest: &Path, version: &str) -> Result<(), Error> {177fn write_version(dest: &Path, version: &str) -> Result<(), Error> {
178 let marker = dest.join(VERSION_FILE);
179 if marker.exists() {
180 warn!(
181 "{}: dependency ships its own {VERSION_FILE}, keeping it and re-extracting on every install",
182 dest.display()
183 );
184 return Ok(());
185 }
146 fs::write(dest.join(VERSION_FILE), format!("{version}\n"))186 fs::write(&marker, format!("{version}\n")).map_err(|e| Error::Io(marker, e))
147 .map_err(|e| Error::Io(dest.join(VERSION_FILE), e))
148}187}
149188
150pub fn execute(plan: &InstallPlan, vendor_dir: &Path, dry_run: bool) -> Result<(), Error> {189pub fn execute(plan: &InstallPlan, vendor_dir: &Path, opts: Options) -> Result<(), Error> {
190 let dry_run = opts.dry_run;
151 if !dry_run {191 if !dry_run {
152 for (path, source) in &plan.entries {192 for (path, source) in &plan.entries {
153 let dest = vendor_dir.join(path);193 let dest = vendor_dir.join(path);
157 commit_sha,197 commit_sha,
158 subdir,198 subdir,
159 } => {199 } => {
160 if is_up_to_date(&dest, commit_sha) {200 if is_up_to_date(plan, vendor_dir, path, commit_sha, opts.compat) {
161 continue;201 continue;
162 }202 }
163 info!("extract {path}");203 info!("extract {path}");
173 commit_sha,213 commit_sha,
174 subdir,214 subdir,
175 } => {215 } => {
176 if is_up_to_date(&dest, commit_sha) {216 if is_up_to_date(plan, vendor_dir, path, commit_sha, opts.compat) {
177 continue;217 continue;
178 }218 }
179 info!("extract {path}");219 info!("extract {path}");
208 Ok(())248 Ok(())
209}249}
250
251/// Nested dependencies are not part of the checksum of the dependency they are
252/// nested in, as `jsonnet-bundler` wipes them when extracting the parent.
253fn exclusions(
254 entries: &BTreeMap<Utf8PathBuf, VendorSource>,
255 vendor_dir: &Path,
256 path: &Utf8Path,
257) -> Exclusions {
258 let prefix = format!("{path}/");
259 Exclusions(
260 entries
261 .keys()
262 .filter(|k| k.as_str().starts_with(&prefix))
263 .map(|k| vendor_dir.join(k))
264 .collect(),
265 )
266}
267
268fn locked_sum<'a>(plan: &'a InstallPlan, path: &Utf8Path) -> Option<&'a str> {
269 plan.lock
270 .dependencies
271 .iter()
272 .find(|d| d.canonical_name() == path)?
273 .sum
274 .as_deref()
275}
276
277/// Verify checksums of the vendored trees against the ones carried over from
278/// the lockfile, and record the missing ones.
279fn update_sums(plan: &mut InstallPlan, vendor_dir: &Path, compat: bool) -> Result<(), Error> {
280 let InstallPlan { lock, entries } = plan;
281 for dep in &mut lock.dependencies {
282 if !matches!(dep.source, Source::Git(_)) {
283 continue;
284 }
285 let path = dep.canonical_name();
286 if !entries.contains_key(&path) {
287 continue;
288 }
289 let dir = vendor_dir.join(&path);
290 let exclude = exclusions(entries, vendor_dir, &path);
291 if !exclude.0.is_empty() {
292 warn!(
293 "{path}: nested dependencies are excluded from its checksum, jsonnet-bundler's value depends on install order here"
294 );
295 }
296 let version = dep.version.as_deref();
297 let sum = hash_dir(&dir, &exclude, version, Mode::Correct)?;
298 if let Some(expected) = &dep.sum
299 && *expected != sum
300 {
301 // The tree itself is intact, the lockfile just carries a checksum
302 // jsonnet-bundler computed incorrectly. Replace it with a correct one.
303 let bundler_sum = compat
304 .then(|| hash_dir(&dir, &exclude, version, Mode::JsonnetBundler))
305 .transpose()?;
306 if bundler_sum.as_deref() != Some(expected.as_str()) {
307 return Err(Error::ChecksumMismatch {
308 dep: path,
309 expected: expected.clone(),
310 got: sum,
311 });
312 }
313 warn!("{path}: replacing the checksum written by jsonnet-bundler");
314 }
315 dep.sum = Some(sum);
316 }
317 Ok(())
318}
210319
211fn prune(plan: &InstallPlan, vendor_dir: &Path, dry_run: bool) -> Result<(), Error> {320fn prune(plan: &InstallPlan, vendor_dir: &Path, dry_run: bool) -> Result<(), Error> {
212 if !vendor_dir.is_dir() {321 if !vendor_dir.is_dir() {
289 git::resolve(git_source, version)398 git::resolve(git_source, version)
290}399}
291400
292fn locked_version<'a>(dep: &Dependency, lock: Option<&'a JsonnetFile>) -> Option<&'a str> {401fn locked_dep<'a>(dep: &Dependency, lock: Option<&'a JsonnetFile>) -> Option<&'a Dependency> {
293 let lock = lock?;
294 let key = dep.canonical_name();402 let key = dep.canonical_name();
295 lock.dependencies403 lock?
296 .iter()404 .dependencies
297 .find(|d| d.canonical_name() == key)405 .iter()
298 .and_then(|d| d.version.as_deref())406 .find(|d| d.canonical_name() == key)
299}407}
300408
301fn resolve_deps(409fn resolve_deps(
315 continue;423 continue;
316 }424 }
317425
426 let locked = locked_dep(dep, lock);
318 let version = locked_version(dep, lock).or(dep.version.as_deref());427 let version = locked
428 .and_then(|d| d.version.as_deref())
429 .or(dep.version.as_deref());
319430
320 info!(431 info!(
324435
325 let result = resolve_one(git_source, version)?;436 let result = resolve_one(git_source, version)?;
437
438 // Only the lockfile checksum is authoritative, and only for the exact
439 // version it was recorded for.
440 let expected_sum = locked
441 .filter(|d| d.version.as_deref() == Some(result.version.as_str()))
442 .and_then(|d| d.sum.clone());
326443
327 plan.lock.dependencies.push(Dependency {444 plan.lock.dependencies.push(Dependency {
328 source: dep.source.clone(),445 source: dep.source.clone(),
329 version: Some(result.version),446 version: Some(result.version),
330 sum: dep.sum.clone(),447 sum: expected_sum,
331 name: dep.name.clone(),448 name: dep.name.clone(),
332 single: dep.single,449 single: dep.single,
333 });450 });
417 Zip(Box<zip::result::ZipError>),534 Zip(Box<zip::result::ZipError>),
418 #[error(transparent)]535 #[error(transparent)]
419 Accessor(#[from] accessor::Error),536 Accessor(#[from] accessor::Error),
537 #[error(
538 "checksum mismatch for {dep}: expected {expected}, got {got}. If the lockfile was written by jsonnet-bundler, pass --compat to accept and rewrite its checksums"
539 )]
540 ChecksumMismatch {
541 dep: Utf8PathBuf,
542 expected: String,
543 got: String,
544 },
420 #[error("unknown subdir: {0}")]545 #[error("unknown subdir: {0}")]
421 SubdirNotFound(String),546 SubdirNotFound(String),
422 #[error("invalid path in tree: {0}")]547 #[error("invalid path in tree: {0}")]
modifiedtests/realworld/jsonnetfile.lock.jsondiffbeforeafterboth
7 "remote": "https://github.com/prometheus-operator/kube-prometheus"7 "remote": "https://github.com/prometheus-operator/kube-prometheus"
8 }8 }
9 },9 },
10 "version": "392c6c5e8e83c9a0f76355d4b0837dccf76ad7ea"10 "version": "392c6c5e8e83c9a0f76355d4b0837dccf76ad7ea",
11 "sum": "wGFFNc+cprdcsemJ+Fx1738tiRWXPaV9uqFie7UoBlE="
11 },12 },
12 {13 {
13 "source": {14 "source": {
16 "subdir": "mixin-utils"17 "subdir": "mixin-utils"
17 }18 }
18 },19 },
19 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"20 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
21 "sum": "zVkvwae4zHP6xeIoDvde/wldI6ClprFjnk50mMD9/z4="
20 },22 },
21 {23 {
22 "source": {24 "source": {
25 "subdir": "grafana"27 "subdir": "grafana"
26 }28 }
27 },29 },
28 "version": "5698c8940b6dadca3f42107b7839557bc041761f"30 "version": "5698c8940b6dadca3f42107b7839557bc041761f",
31 "sum": "l6fPvh3tW6fWot308w71QY/amrYsFPeitvz1IgJxqQA="
29 },32 },
30 {33 {
31 "source": {34 "source": {
34 "subdir": "grafonnet"37 "subdir": "grafonnet"
35 }38 }
36 },39 },
37 "version": "a1d61cce1da59c71409b99b5c7568511fec661ea"40 "version": "a1d61cce1da59c71409b99b5c7568511fec661ea",
41 "sum": "342u++/7rViR/zj2jeJOjshzglkZ1SY+hFNuyCBFMdc="
38 },42 },
39 {43 {
40 "source": {44 "source": {
44 }48 }
45 },49 },
46 "version": "278a9c4cb758a546229e2b408def7e3dcb5f4ec0",50 "version": "278a9c4cb758a546229e2b408def7e3dcb5f4ec0",
51 "sum": "sRjOJwJhhkCDmMQls7clo/csVix/b47W+Wc3YCzn64Y=",
47 "name": "grafana-mixin"52 "name": "grafana-mixin"
48 },53 },
49 {54 {
53 "subdir": "contrib/mixin"58 "subdir": "contrib/mixin"
54 }59 }
55 },60 },
56 "version": "0cbc031e7f224102bd1ec42a81f659a2b8c3350c"61 "version": "0cbc031e7f224102bd1ec42a81f659a2b8c3350c",
62 "sum": "XmXkOCriQIZmXwlIIFhqlJMa0e6qGWdxZD+ZDYaN0Po="
57 },63 },
58 {64 {
59 "source": {65 "source": {
62 "subdir": "gen/grafonnet-v10.0.0"68 "subdir": "gen/grafonnet-v10.0.0"
63 }69 }
64 },70 },
65 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058"71 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058",
72 "sum": "xdcrJPJlpkq4+5LpGwN4tPAuheNNLXZjE6tDcyvFjr0="
66 },73 },
67 {74 {
68 "source": {75 "source": {
71 "subdir": "doc-util"78 "subdir": "doc-util"
72 }79 }
73 },80 },
74 "version": "bf6f08ae02a51c48bdcec4629b1c1a5a62c6f803"81 "version": "bf6f08ae02a51c48bdcec4629b1c1a5a62c6f803",
82 "sum": "BrAL/k23jq+xy9oA7TWIhUx07dsA/QLm3g7ktCwe//U="
75 },83 },
76 {84 {
77 "source": {85 "source": {
78 "git": {86 "git": {
79 "remote": "https://github.com/jsonnet-libs/xtd.git"87 "remote": "https://github.com/jsonnet-libs/xtd.git"
80 }88 }
81 },89 },
82 "version": "4d7f8cb24d613430799f9d56809cc6964f35cea9"90 "version": "4d7f8cb24d613430799f9d56809cc6964f35cea9",
91 "sum": "hOrwkOx34tOXqoDVnwuI/Uf/dr9HFFSPWpDPOvnEGrk="
83 },92 },
84 {93 {
85 "source": {94 "source": {
88 "subdir": "jsonnet/prometheus-operator"97 "subdir": "jsonnet/prometheus-operator"
89 }98 }
90 },99 },
91 "version": "288f0ae3f4ef14e3c75078cbd7dfe1857c3fb066"100 "version": "288f0ae3f4ef14e3c75078cbd7dfe1857c3fb066",
101 "sum": "fftlgLNJpgRQQjT32E3w/pGqnHK32NIbYX19IiWSTls="
92 },102 },
93 {103 {
94 "source": {104 "source": {
98 }108 }
99 },109 },
100 "version": "288f0ae3f4ef14e3c75078cbd7dfe1857c3fb066",110 "version": "288f0ae3f4ef14e3c75078cbd7dfe1857c3fb066",
111 "sum": "gi+knjdxs2T715iIQIntrimbHRgHnpM8IFBJDD1gYfs=",
101 "name": "prometheus-operator-mixin"112 "name": "prometheus-operator-mixin"
102 },113 },
103 {114 {
106 "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin"117 "remote": "https://github.com/kubernetes-monitoring/kubernetes-mixin"
107 }118 }
108 },119 },
109 "version": "acd544dbd02ebce1e000abe006df6d2e4ac1438e"120 "version": "acd544dbd02ebce1e000abe006df6d2e4ac1438e",
121 "sum": "aRBESvZpnMG7iDNIR0CP+8yuvZyF4rQn8FLlXpBxGW8="
110 },122 },
111 {123 {
112 "source": {124 "source": {
115 "subdir": "gen/grafonnet-latest"127 "subdir": "gen/grafonnet-latest"
116 }128 }
117 },129 },
118 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058"130 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058",
131 "sum": "V9vAj21qJOc2DlMPDgB1eEjSQU4A+sAA4AXuJ6bd4xc="
119 },132 },
120 {133 {
121 "source": {134 "source": {
124 "subdir": "gen/grafonnet-v11.4.0"137 "subdir": "gen/grafonnet-v11.4.0"
125 }138 }
126 },139 },
127 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058"140 "version": "7380c9c64fb973f34c3ec46265621a2b0dee0058",
141 "sum": "aVAX09paQYNOoCSKVpuk1exVIyBoMt/C50QJI+Q/3nA="
128 },142 },
129 {143 {
130 "source": {144 "source": {
133 "subdir": "jsonnet/kube-state-metrics"147 "subdir": "jsonnet/kube-state-metrics"
134 }148 }
135 },149 },
136 "version": "cd5430fd1834f43ffd093e3e22c2af1a625dbe2e"150 "version": "cd5430fd1834f43ffd093e3e22c2af1a625dbe2e",
151 "sum": "7FPi/0YmErTgBmFQWavjoI/9WpWe5eL9G+OHnyc9d5A="
137 },152 },
138 {153 {
139 "source": {154 "source": {
142 "subdir": "jsonnet/kube-state-metrics-mixin"157 "subdir": "jsonnet/kube-state-metrics-mixin"
143 }158 }
144 },159 },
145 "version": "cd5430fd1834f43ffd093e3e22c2af1a625dbe2e"160 "version": "cd5430fd1834f43ffd093e3e22c2af1a625dbe2e",
161 "sum": "qclI7LwucTjBef3PkGBkKxF0mfZPbHnn4rlNWKGtR4c="
146 },162 },
147 {163 {
148 "source": {164 "source": {
151 "subdir": "docs/node-mixin"167 "subdir": "docs/node-mixin"
152 }168 }
153 },169 },
154 "version": "d6d0e710bb7daf07a2743fde060f0d5f32c565f3"170 "version": "d6d0e710bb7daf07a2743fde060f0d5f32c565f3",
171 "sum": "PGx1okd1Ny4U+Ma3AV0haZWvXnX8eJBN4+BsQInWUo4="
155 },172 },
156 {173 {
157 "source": {174 "source": {
161 }178 }
162 },179 },
163 "version": "91c184a899b8e8237cdd08876fba54aa5f9feb6c",180 "version": "91c184a899b8e8237cdd08876fba54aa5f9feb6c",
181 "sum": "UuADJwhNploRwfJYGb0sr2mi+MvswKpumoOMXnGs0Dc=",
164 "name": "prometheus"182 "name": "prometheus"
165 },183 },
166 {184 {
171 }189 }
172 },190 },
173 "version": "c85e06d3cd4ba24d003454ee11834404224d7763",191 "version": "c85e06d3cd4ba24d003454ee11834404224d7763",
192 "sum": "diZM7b/jQKqaIjuVSiseRaxgpgdQyVCtCgh0XhyPnXQ=",
174 "name": "alertmanager"193 "name": "alertmanager"
175 },194 },
176 {195 {
181 }200 }
182 },201 },
183 "version": "25bac00a6c478211326eed4aa46583d1b9466ca8",202 "version": "25bac00a6c478211326eed4aa46583d1b9466ca8",
203 "sum": "vY3+ZELH6GFEpNJ0tKeU8ybCMLOQePKnnqFP4CSLSWo=",
184 "name": "pyrra"204 "name": "pyrra"
185 },205 },
186 {206 {
191 }211 }
192 },212 },
193 "version": "cdca5483752e1635d249fbb1271978262775dc1b",213 "version": "cdca5483752e1635d249fbb1271978262775dc1b",
214 "sum": "ieCD4eMgGbOlrI8GmckGPHBGQDcLasE1rULYq56W/bs=",
194 "name": "thanos-mixin"215 "name": "thanos-mixin"
195 },216 },
196 {217 {
200 "subdir": "grafana-builder"221 "subdir": "grafana-builder"
201 }222 }
202 },223 },
203 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"224 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
225 "sum": "TWpxm5vPO23V3hoF3pdwGs1NvR+PQce9baN716mJq+4="
204 },226 },
205 {227 {
206 "source": {228 "source": {
207 "git": {229 "git": {
208 "remote": "https://github.com/oracle/graal"230 "remote": "https://github.com/oracle/graal"
209 }231 }
210 },232 },
211 "version": "d24e4efdac60ee798d7a795cf015f084556c912e"233 "version": "d24e4efdac60ee798d7a795cf015f084556c912e",
234 "sum": "6Ht2xkgFs2xIjRBF2Mb1AiRWDoEUCXsmICmsa9qw6iU="
212 },235 },
213 {236 {
214 "source": {237 "source": {
217 "subdir": "production/ksonnet/loki"240 "subdir": "production/ksonnet/loki"
218 }241 }
219 },242 },
220 "version": "fe7f43b7f36d8f90931a3bfd35fadc83e1c23d5f"243 "version": "fe7f43b7f36d8f90931a3bfd35fadc83e1c23d5f",
244 "sum": "2yQh4LZE2q1vqF6ReW1FXY3Hu43WL+vrJnm3Dw6w3sM="
221 },245 },
222 {246 {
223 "source": {247 "source": {
226 "subdir": "consul"250 "subdir": "consul"
227 }251 }
228 },252 },
229 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"253 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
254 "sum": "Po3c1Ic96ngrJCtOazic/7OsLkoILOKZWXWyZWl+od8="
230 },255 },
231 {256 {
232 "source": {257 "source": {
235 "subdir": "jaeger-agent-mixin"260 "subdir": "jaeger-agent-mixin"
236 }261 }
237 },262 },
238 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"263 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
264 "sum": "h/nMdmRK8Ep4bnRXKOuVL+RlUm85hhtD0LGIsf2THAY="
239 },265 },
240 {266 {
241 "source": {267 "source": {
244 "subdir": "ksonnet-util"270 "subdir": "ksonnet-util"
245 }271 }
246 },272 },
247 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"273 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
274 "sum": "0y3AFX9LQSpfWTxWKSwoLgbt0Wc9nnCwhMH2szKzHv0="
248 },275 },
249 {276 {
250 "source": {277 "source": {
253 "subdir": "memcached"280 "subdir": "memcached"
254 }281 }
255 },282 },
256 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"283 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
284 "sum": "zNTCDRaCqJUHjQSQRsxGR3jLrMP9tU7YNQb13dbm1bU="
257 },285 },
258 {286 {
259 "source": {287 "source": {
262 "subdir": "operations/mimir"290 "subdir": "operations/mimir"
263 }291 }
264 },292 },
265 "version": "39dd4ffb859d0abb3951d406495bc4bd422600dd"293 "version": "39dd4ffb859d0abb3951d406495bc4bd422600dd",
294 "sum": "9YmzQyhMEVRj6OcLgkk02Uk2FOw3vykuvRXA3CA6E5k="
266 },295 },
267 {296 {
268 "source": {297 "source": {
271 "subdir": "operations/rollout-operator"300 "subdir": "operations/rollout-operator"
272 }301 }
273 },302 },
274 "version": "2afe062893496f0554b4764bbe1638f8019832fb"303 "version": "2afe062893496f0554b4764bbe1638f8019832fb",
304 "sum": "t3nMMxw7cEOOmpdtKfadQRhvu2XQVvPigDq4CipmPIg="
275 },305 },
276 {306 {
277 "source": {307 "source": {
281 }311 }
282 },312 },
283 "version": "dbc8cf1a9847f123d8325378111155fb135983ab",313 "version": "dbc8cf1a9847f123d8325378111155fb135983ab",
314 "sum": "EVCNg9VpU9ghIYHZtbQffHbZs+EqKOD0cw+ZPilWR48=",
284 "name": "keda-libsonnet"315 "name": "keda-libsonnet"
285 },316 },
286 {317 {
290 "subdir": "operations/jsonnet/microservices"321 "subdir": "operations/jsonnet/microservices"
291 }322 }
292 },323 },
293 "version": "f6124c0dea954763dbaa461dcc7b8a89bc8d2635"324 "version": "f6124c0dea954763dbaa461dcc7b8a89bc8d2635",
325 "sum": "uKkEEUq2qR69lmrDDDQAR2nVVYdQewz7MR0iJnyn3Kw="
294 },326 },
295 {327 {
296 "source": {328 "source": {
299 "subdir": "1.32"331 "subdir": "1.32"
300 }332 }
301 },333 },
302 "version": "55380470fb7979e6ce0c4316cb9c27a266caf298"334 "version": "55380470fb7979e6ce0c4316cb9c27a266caf298",
335 "sum": "L70C3SiMFOsNCuIGOxRKAzd6wUBuabAoEGrgvCyeCBc="
303 },336 },
304 {337 {
305 "source": {338 "source": {
308 "subdir": "1.0.0"341 "subdir": "1.0.0"
309 }342 }
310 },343 },
311 "version": "5d16cd466d12489e6ffba5b17813a0203016e68d"344 "version": "5d16cd466d12489e6ffba5b17813a0203016e68d",
345 "sum": "ksOv5A0fQkz4fRz4KMCHloLUiD7BPwGKvUn2sHIAB7s="
312 },346 },
313 {347 {
314 "source": {348 "source": {
315 "git": {349 "git": {
316 "remote": "https://gitlab.com/gitlab-com/runbooks"350 "remote": "https://gitlab.com/gitlab-com/runbooks"
317 }351 }
318 },352 },
319 "version": "c4082c94065b1b6a521eed59ed624478131cd9c0"353 "version": "c4082c94065b1b6a521eed59ed624478131cd9c0",
354 "sum": "GPAWtUsS3aCFXOHWbk6qdwMH0jA2kFpHknagnRYd4sw="
320 },355 },
321 {356 {
322 "source": {357 "source": {
325 "subdir": "memcached-mixin"360 "subdir": "memcached-mixin"
326 }361 }
327 },362 },
328 "version": "3b8056670048416f5fb660dc039e473eb20a40b2"363 "version": "3b8056670048416f5fb660dc039e473eb20a40b2",
364 "sum": "qv5EBh5EVpWSpzXRtrgn5CBb1W60kLqVEGkItfVAgd4="
329 },365 },
330 {366 {
331 "source": {367 "source": {
334 "subdir": "jsonnetunit"370 "subdir": "jsonnetunit"
335 }371 }
336 },372 },
337 "version": "6927c58cae7624a00f368b977ccc477d4f74071f"373 "version": "6927c58cae7624a00f368b977ccc477d4f74071f",
374 "sum": "9FFqqln65hooRF0l6rjICDtnTxUlmDj34+sKMh4sjPI="
338 }375 }
339 ],376 ],
340 "legacyImports": true377 "legacyImports": true