2021-02-05 patches (#739)
This commit is contained in:
Родитель
899121ae27
Коммит
77bfb7c1e7
|
@ -0,0 +1,32 @@
|
|||
#-------------------------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
|
||||
#-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
ARG ORIGINAL_IMAGE=mcr.microsoft.com/vscode/devcontainers/javascript-node@sha256:58ecafbc0455c024b3bcdde60036f262edc3d139b8308c8f5e6e17c55252253a
|
||||
FROM ${ORIGINAL_IMAGE}
|
||||
|
||||
ARG PACKAGE_LIST="\
|
||||
sudo \
|
||||
linux-libc-dev \
|
||||
libp11-kit0 \
|
||||
"
|
||||
|
||||
# Script to iterate through the above list and update packages
|
||||
ARG PATCH_SCRIPT="\
|
||||
export DEBIAN_FRONTEND=noninteractive \
|
||||
&& if type yarn > /dev/null 2>&1; then curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | (OUT=$(apt-key add - 2>&1) || echo $OUT); fi \
|
||||
&& apt-get update \
|
||||
&& echo \"${PACKAGE_LIST}\" | tr ' ' '\n' | while read PKG; do \
|
||||
echo \"Checking \$PKG...\" \
|
||||
&& if [ \"\$PKG\" != '' ] && dpkg -s \$PKG >/dev/null 2>&1; then apt-get install -yq --only-upgrade --no-install-recommends \$PKG; fi; \
|
||||
done \
|
||||
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
|
||||
"
|
||||
|
||||
RUN echo "${PATCH_SCRIPT}" \
|
||||
&& if [ "$(id -u)" -ne 0 ]; then \
|
||||
sudo bash -c "${PATCH_SCRIPT}"; \
|
||||
else \
|
||||
bash -c "${PATCH_SCRIPT}"; \
|
||||
fi
|
|
@ -0,0 +1,7 @@
|
|||
Updates older image versions to resolve the following:
|
||||
|
||||
- sudo CVE-2021-3156 https://nvd.nist.gov/vuln/detail/CVE-2021-3156
|
||||
- DLA 2534-1 https://lists.debian.org/debian-lts-announce/2021/01/msg00022.html
|
||||
- DSA 4839-1 https://lists.debian.org/debian-security-announce/2021/msg00020.html
|
||||
- linux-libc-dev USN-4679-1 https://lists.ubuntu.com/archives/ubuntu-security-announce/2021-January/005821.html
|
||||
- libp11-kit0 USN-4677-1 https://lists.ubuntu.com/archives/ubuntu-security-announce/2021-January/005819.html
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"dockerFile": "Dockerfile",
|
||||
"bumpVersion": false,
|
||||
"deleteUntaggedImages": true,
|
||||
"imageIds": [
|
||||
"sha256:a8af1da60b101b796a03180b2c7c493e99072e5bbc82a3be888efa17702dd443",
|
||||
"sha256:1aa71b81f47df7267aa011521cdb2cf157af19d9f41613ee322bfb3ce6ca2256",
|
||||
"sha256:c85f692b1e10a7f6721df8cfed510970d7dbb05bc2238b411745e5a267702321",
|
||||
"sha256:58ecafbc0455c024b3bcdde60036f262edc3d139b8308c8f5e6e17c55252253a",
|
||||
"sha256:846ef00e742cdb5f7f1f1dfbbee26aefcaf580313e7b1fda84c5d4b29fb5eb26",
|
||||
"sha256:fe16aacc07a0d757cbf43184daf79486db8ff11eb79b7d2c1dd24f6a48959cbd",
|
||||
"sha256:220bb3d3271d212ab6040b357ee3f26dd0b77b9fae6ac9a25857f82235b9d484",
|
||||
"sha256:abd89f78ee61b6820b212d8c28aceff483cef8a269c550fdd7f8a877935b339a",
|
||||
"sha256:3728eb9fb9382c8ebf6109bb514c34108b03d0480ec399ac7213e01810bd487f",
|
||||
"sha256:094cce53876529d47aed4b808dca00e8ce6995392b9f2ec707035e431e759cde",
|
||||
"sha256:c00b045739a1ee10e6841bab14dd8a88b4dafa65ff806c039e6d3beb05a5c1f3",
|
||||
"sha256:c46e9895bf79b2c67cdaf08cd9f7ea45f94d38c6e0a7470c68111117d42e7f98",
|
||||
"sha256:4e419bba619b323c622ed1f4bdb92d937121e52a467370a8707a40d3364d5d33",
|
||||
"sha256:aa9827df6f29367d5fb7c5d423b89a1c5edabba5533472f22858c60eafcd5c71",
|
||||
"sha256:9be22307104d4fdeb9a7443bf2860e517f9a549b41cb6f5909d48215b0efa138",
|
||||
"sha256:bd5e106fc3251e20b62923f0b09123e254134dced5eb7c816902cb20c81d8e0b",
|
||||
"sha256:704949a2073c39a51d8b73d81afccceab15a7e99390dc070581b15f43e65366e",
|
||||
"sha256:76a6605d6671a6fdbfbedaa6772de9aef56605a787dbb3440e1bc20ddbfb186d",
|
||||
"sha256:f499eed429600fb2586940eff10fe7deda5208ddaad3334f06613e651daef7a5",
|
||||
"sha256:fd30f003f6946b3efb3dcd2aadf94addfdfa3399440593557b0001a8be8288ab",
|
||||
"sha256:cd0152b458c1104e35f1b5a2a0c83164009b4004decf17a89d5f524876d65f96",
|
||||
"sha256:9189178f892933772d345b166508ae8e89206e38ed7e2a47699acef2ae1cd08c",
|
||||
"sha256:09b49131f112d84d2e2005902199dbbc4a13c312fce558c45165f3ac0408d225",
|
||||
"sha256:57912dc8d5486e94e2263c47c4fbf60e55863d7b20e735ad6356d7b38f806662",
|
||||
"sha256:7105c6f97fe9fc19e7dc3242733ea216bb3f9ba3f649b15c090d8a123f695943",
|
||||
"sha256:19a697ce72942f7a0d1ccaea256e9d1fc924cb62360a3d8dfa4c9542e0687b43",
|
||||
"sha256:71386ec768c04ee034eee0c3deb9284ad22f088e8f1c767175a43528fba8def2",
|
||||
"sha256:329aff27952af3c5b5de84b63a9c25b0e09e0ba095798623442b746079433415",
|
||||
"sha256:987ba6fc0bb700a70308f92c5179d6bb569a28c9eebf76bebc2fea56a3be45ff",
|
||||
"sha256:205fb6ab5bd3fbcffaf7bcaac92b56b22d4c9d3025ae705bc2f351e61f7e0217",
|
||||
"sha256:c22d4f9a9230d8439846e255a2095bd8e6a0e867f06fb0570c9ed4f94d475fbd",
|
||||
"sha256:291f4dbe1cbf121727ada9d408be622268321fcae5b9d6877d3a61808c203eca",
|
||||
"sha256:95dfa49338ae7cf6f5c78921bf379fad1ab75a0a777bfeca20eca953f166aac7",
|
||||
"sha256:f57ac35a45c7e1e36597aaa6ab38b27885c01f41ed5ec05a519fd87a645358ff",
|
||||
"sha256:2b64771de4263263a16cf56a6bd9318e3ce9ae9dc1186eb91a947c5033db8711",
|
||||
"sha256:c60647384fa178e6a7827e0b95f974243260877bcf947099d4605cca78c814f0",
|
||||
"sha256:8d56f479cbb8f80d8e1f87051cade28ef9d97516ce4f9efe5d83601e3d626d5a",
|
||||
"sha256:29455e08b45bafa18db92aa1bc4ee70cbe7f0a3447b192106b26a22b36c74b04",
|
||||
"sha256:a9e8abd46e7b4be3889a03daddfa5a9bf98c448d6d1ede30f20966f50d5edd2f",
|
||||
"sha256:1840c0083355ea755292623c8ba7e28e7aa1650db59c6ce9c82539920658e685",
|
||||
"sha256:3723215b151e405ddc391236675235932c5ab4200882b30ef7f2a7c154a25a1b",
|
||||
"sha256:f0b487271278db3b6d421c2d18a8befe5f2f32b005e936b451a41a8e2cfd14fa",
|
||||
"sha256:f13f11e0d2d58fe6fbc7d4a226dfb5d48f8d14458b4fc1f17f0a8d8b9c5e29f9",
|
||||
"sha256:84af29fd2a8cedff36b584f544d7295b5dc03c3efc47f79a031743dc33c175d1",
|
||||
"sha256:f454429ccfc77a3f6d66d792804850c7843bc5f953a87f6bbcffeec8f78436fd",
|
||||
"sha256:99cb56e8b6d662c3344b438301ee6ed9747dfd5ddc0b755ee7169b589c899a7e",
|
||||
"sha256:ca2876046864529c73765309822942e95e1c2709719fed9410b768b38afb648f",
|
||||
"sha256:8d05a8cdd9337da08ded4593fa9865e16147da762471ba06a9ff0803e5b21fb9",
|
||||
"sha256:315dbfa0c70f165b7f22dfb09c7982abfd20f7feaeefe4c1208d5160f4801a74",
|
||||
"sha256:c7abfb8f059514d49cef0e14feee6f19db212b044634a80da87c82d333edae2f",
|
||||
"sha256:6bfc0114353764257989e8fd8830df107e02c93f26b9f7e01fef09e873b4c04a",
|
||||
"sha256:484c90c05dc7c4792a1f72de95fbaec3d73da7438aac0851c79d64478ea76617",
|
||||
"sha256:fbcc9403bc8fb35ae591a6f2a862b62a09f683c69fd7f4fd39938993561f39ba",
|
||||
"sha256:c9d24da5ac1339f8341676c057ad58d41842125f8ced2e78bb5a1cb494a0e7e6",
|
||||
"sha256:ffb4ebc7804ed52924d62da9b2711202eacf8b6c352812014d9fa2ae1668826e",
|
||||
"sha256:4ca4e26c022f8ad95182dc28ff9a6a45b42e419fe765d969653020d626fc86ae",
|
||||
"sha256:c696ec70ff7410b47acbf8fb3776b1865d260061bfa5c00933ccc1ed85f68a05",
|
||||
"sha256:8449ccb0580d9c3a1779e19b030bf2220ea79f8f126475e84152ac006ab22e45",
|
||||
"sha256:64338b2eb6863f4b4cc46c8174137a5d5858c874cd9fc61fd274fe257f67b470",
|
||||
"sha256:05a76d1393d8b3e02f956c7f2adcc9348cf1bfb8d59162363e31149fcafb11f5",
|
||||
"sha256:c7822c2989fb5e8f6d905334539c97e19e41439e50df2b5764f02870e22476ea",
|
||||
"sha256:e45350b7868b7e82b05977803505407e955db6b401ca2a15ed3b1bf2a162450f",
|
||||
"sha256:60800829368bb9b35bc825a2240a290121c908f2bb93dfd1917cfe6b32aeb747",
|
||||
"sha256:5d464ca75577cbff78c380b713d0f236f4ec4292a4b36e36801820bd02af4115",
|
||||
"sha256:0440d8e47a045353a58600e94199309a83d464e78221a4520c570f05eeae02dd",
|
||||
"sha256:cc483fda87dbe26c833a3f857e07b57c92587ab866764721b3f53d654d20e8be",
|
||||
"sha256:18b3a18b81b6fbbb590dbd998b2eaaaca5a98d192b08c2e0dec717db3e98cf56",
|
||||
"sha256:3c55f58d30ca8c580650057c92b4303a218eb629521bd5e8fb60e541008a4096",
|
||||
"sha256:035a3d9e0021dcfe296445c88f0ccdc9c98b12169f64e0f7e13b2fb11bb23d57",
|
||||
"sha256:78433e82bc36c78d799087efb62d251a4b18d0b95c30e6d2556c77164737ab38",
|
||||
"sha256:5b51fcd014e37de1795034ec74f33cea65ba21b4c6d0940ee72047471219cdf4",
|
||||
"sha256:f5ab061c6df520602bfbadf6a764d501346a551b25cd3fda7ca4e1121036b1b3",
|
||||
"sha256:55ef0c5e4ed5de9aae13f42b4d8e71ab95b3c1e7bf2ea7c42cd1b91cedc5da8b",
|
||||
"sha256:0dd988931313673ac1f24900de5184b560c9bcc144ce57bdfdaf01110e9f5286",
|
||||
"sha256:a30ac278d31f0336ebf2a6c7638071bf1230105492daba2a4ba6bd5ebfe8519d",
|
||||
"sha256:d14987bb9d4736717e7f5167870ec5fbab4d67a7bb46e95c1330ac68fd2bb9d3",
|
||||
"sha256:a440f947c858ca29f4b02eafae5853c77c24bd078cbf734817aa16a2f40fff62",
|
||||
"sha256:2a642eb222fb1cbef78ffa97f73c80d9418a150a4e3582ecf21c8d20a66eadaf",
|
||||
"sha256:d422d36b76bf653bbcabb43b9a81bfac7cc2d453e4879d8f191b2839951accf4",
|
||||
"sha256:0d5337570b3478f2f2b1da793bd38c23e39e023aaab9f2a112e1b765bb5bc093",
|
||||
"sha256:7f62de18c4c9b366fc8451f9096eec2768104e3e36faaded744fa5a2ce92fbdf",
|
||||
"sha256:011357a8697b1087db48d5315b6cc8ad52875c8904a5399944d1d0c50dad7be7"
|
||||
]
|
||||
}
|
|
@ -10,81 +10,101 @@ const jsonc = require('jsonc').jsonc;
|
|||
async function patch(patchPath, registry, registryPath) {
|
||||
patchPath = path.resolve(patchPath);
|
||||
const patchConfig = await getPatchConfig(patchPath);
|
||||
// ACR registry name is the registry minus .azurecr.io
|
||||
const registryName = registry.replace(/\..*/, '');
|
||||
|
||||
console.log(`(*) Applying patch located at "${patchPath}"...`);
|
||||
let tagList = patchConfig.tagList || [];
|
||||
// If imageIds specified, get the complete list of tags to update
|
||||
if (patchConfig.imageIds) {
|
||||
const manifests = await getImageManifests(registryName, patchConfig.imageIds);
|
||||
tagList = tagList.concat(manifests.reduce((prev, manifest) => {
|
||||
return prev.concat(manifest.tags.map((tag) => {
|
||||
return `${manifest.repository}:${tag}`;
|
||||
}));
|
||||
}, []));
|
||||
const dockerFilePath = `${patchPath}/${patchConfig.dockerFile || 'Dockerfile'}`;
|
||||
if (patchConfig.tagList) {
|
||||
throw new Error('tagList property has been deprecated.')
|
||||
}
|
||||
console.log(`(*) Tags to patch: ${JSON.stringify(tagList, undefined, 4)}`);
|
||||
|
||||
const spawnOpts = { stdio: 'inherit', cwd: patchPath, shell: true };
|
||||
await asyncUtils.forEach(tagList, async (tag) => {
|
||||
const newTag = patchConfig.bumpVersion ? updateVersionTag(tag, registryPath) : tag;
|
||||
console.log(`\n(*) Patching ${tag}...`);
|
||||
|
||||
// Pull and build patched image for tag
|
||||
let retry = false;
|
||||
do {
|
||||
try {
|
||||
await asyncUtils.spawn('docker', [
|
||||
'build',
|
||||
'--pull',
|
||||
'--build-arg', `ORIGINAL_IMAGE=${registry}/${tag}`,
|
||||
'--tag', `${registry}/${newTag}`,
|
||||
'-f', `${patchPath}/${patchConfig.dockerFile || 'Dockerfile'}`,
|
||||
patchPath
|
||||
], spawnOpts);
|
||||
done = true;
|
||||
} catch (ex) {
|
||||
// Try to clean out unused images and retry once if get an out of storage response
|
||||
if (ex.result.indexOf('no space left on device') >= 0 && retry === false) {
|
||||
console.log(`(*) Out of space - pruning images..`);
|
||||
asyncUtils.spawn('docker', ['image', 'prune', '--all', '--force'], spawnOpts);
|
||||
console.log(`(*) Retrying..`);
|
||||
retry = true;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
|
||||
// Push update
|
||||
await asyncUtils.spawn('docker', ['push', `${registry}/${newTag}`], spawnOpts);
|
||||
// Update each listed imageId
|
||||
await asyncUtils.forEach(patchConfig.imageIds, async (imageId) => {
|
||||
await patchImage(imageId, patchPath, dockerFilePath, patchConfig.bumpVersion, registry, registryPath);
|
||||
});
|
||||
|
||||
// If config says to delete any untagged images mentioned in the patch, do so.
|
||||
if (patchConfig.deleteUntaggedImages && patchConfig.imageIds) {
|
||||
await deleteUntaggedImages(patchConfig.imageIds, registry);
|
||||
}
|
||||
|
||||
|
||||
console.log('\n(*) Done!')
|
||||
}
|
||||
|
||||
function updateVersionTag(fullTag, registryPath) {
|
||||
const tag = fullTag.replace(registryPath + '/', '');
|
||||
// Get the version number section of the tag if it exists
|
||||
const colon = tag.indexOf(':');
|
||||
const firstDash = tag.indexOf('-', colon);
|
||||
if (firstDash > 0) {
|
||||
const versionSection = tag.substring(colon + 1, firstDash - 1);
|
||||
// See if there are three digits in the version number
|
||||
const versionParts = versionSection.split('.');
|
||||
if (versionParts.length === 3) {
|
||||
// If there are, update the break fix version
|
||||
return `${tag.substring(0, colon + 1)}${versionParts[0]}.${versionParts[1]}.${versionParts[2] + 1}${tag.substring(firstDash)}`;
|
||||
}
|
||||
return `${registryPath}:${tag}`;
|
||||
async function patchImage(imageId, patchPath, dockerFilePath, bumpVersion, registry) {
|
||||
console.log(`\n*** Updating Image: ${imageId} ***`);
|
||||
const spawnOpts = { stdio: 'inherit', cwd: patchPath, shell: true };
|
||||
|
||||
// Get repository and tag list for imageId
|
||||
let repoAndTagList = await getImageRepositoryAndTags(imageId, registry);
|
||||
if(repoAndTagList.length === 0) {
|
||||
console.log('(*) No tags to patch. Skipping.');
|
||||
return;
|
||||
}
|
||||
return tag;
|
||||
|
||||
console.log(`(*) Tags to update: ${
|
||||
JSON.stringify(repoAndTagList.reduce((prev, repoAndTag) => { return prev + repoAndTag.repository + ':' + repoAndTag.tag + ' ' }, ''), undefined, 4)
|
||||
}`);
|
||||
|
||||
// Bump breakfix number of it applies
|
||||
if(bumpVersion) {
|
||||
repoAndTagList = updateVersionTags(repoAndTagList);
|
||||
}
|
||||
|
||||
//Generate tag arguments
|
||||
const tagArgs = repoAndTagList.reduce((prev, repoAndTag) => {
|
||||
return prev.concat(['--tag', `${registry}/${repoAndTag.repository}:${repoAndTag.tag}`])
|
||||
}, []);
|
||||
|
||||
// Pull and build patched image for tag
|
||||
let retry = false;
|
||||
do {
|
||||
try {
|
||||
await asyncUtils.spawn('docker', [
|
||||
'build',
|
||||
'--pull',
|
||||
'--build-arg',
|
||||
`ORIGINAL_IMAGE=${registry}/${repoAndTagList[0].repository}@${imageId}`]
|
||||
.concat(tagArgs)
|
||||
.concat('-f', dockerFilePath, patchPath), spawnOpts);
|
||||
done = true;
|
||||
} catch (ex) {
|
||||
// Try to clean out unused images and retry once if get an out of storage response
|
||||
if (ex.result && ex.result.indexOf('no space left on device') >= 0 && retry === false) {
|
||||
console.log(`(*) Out of space - pruning images...`);
|
||||
await asyncUtils.spawn('docker', ['image', 'prune', '--all', '--force'], spawnOpts);
|
||||
console.log(`(*) Retrying...`);
|
||||
retry = true;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
} while (retry);
|
||||
|
||||
// Push updates
|
||||
await asyncUtils.forEach(repoAndTagList, async (repoAndTag) => {
|
||||
await asyncUtils.spawn('docker', ['push', `${registry}/${repoAndTag.repository}:${repoAndTag.tag}`], spawnOpts);
|
||||
});
|
||||
}
|
||||
|
||||
function updateVersionTags(repoAndTagList) {
|
||||
return repoAndTagList.reduce((prev, repoAndTag) => {
|
||||
let tag = repoAndTag.tag;
|
||||
// Get the version number section of the tag if it exists
|
||||
const firstDash = tag.indexOf('-');
|
||||
if (firstDash > 0) {
|
||||
const versionSection = tag.substring(0, firstDash - 1);
|
||||
// See if there are three digits in the version number
|
||||
const versionParts = versionSection.split('.');
|
||||
if (versionParts.length === 3) {
|
||||
// If there are, update the break fix version
|
||||
tag = `${versionParts[0]}.${versionParts[1]}.${versionParts[2] + 1}${tag.substring(firstDash)}`;
|
||||
}
|
||||
}
|
||||
return prev.push({
|
||||
name: repoAndTag.repository,
|
||||
tag: tag
|
||||
});
|
||||
}, []);
|
||||
}
|
||||
|
||||
async function deleteUnpatchedImages(patchPath, registry) {
|
||||
|
@ -99,11 +119,11 @@ async function deleteUnpatchedImages(patchPath, registry) {
|
|||
|
||||
async function deleteUntaggedImages(imageIds, registry) {
|
||||
|
||||
console.log(`(*) Deleting untagged images...`);
|
||||
console.log('\n*** Deleting untagged images ***');
|
||||
// ACR registry name is the registry minus .azurecr.io
|
||||
const registryName = registry.replace(/\..*/, '');
|
||||
|
||||
const manifests = await getImageManifests(registryName, imageIds);
|
||||
const manifests = await getImageManifests(imageIds, registry);
|
||||
|
||||
console.log(`(*) Manifests to delete: ${JSON.stringify(manifests, undefined, 4)}`);
|
||||
|
||||
|
@ -126,10 +146,42 @@ async function deleteUntaggedImages(imageIds, registry) {
|
|||
], spawnOpts);
|
||||
});
|
||||
|
||||
console.log('\n(*) Done deleting manifests!')
|
||||
console.log('(*) Done deleting manifests!')
|
||||
}
|
||||
|
||||
async function getImageManifests(registryName, imageIds) {
|
||||
// Find tags for image
|
||||
async function getImageRepositoryAndTags(imageId, registry) {
|
||||
// ACR registry name is the registry minus .azurecr.io
|
||||
const registryName = registry.replace(/\..*/, '');
|
||||
|
||||
// Get list of repositories
|
||||
console.log(`(*) Getting repository list for ACR "${registryName}"...`)
|
||||
const repositoryListOutput = await asyncUtils.spawn('az',
|
||||
['acr', 'repository', 'list', '--name', registryName],
|
||||
{ shell: true, stdio: 'pipe' });
|
||||
const repositoryList = JSON.parse(repositoryListOutput);
|
||||
|
||||
let repoAndTagList = [];
|
||||
await asyncUtils.forEach(repositoryList, async (repository) => {
|
||||
console.log(`(*) Checking in for "${imageId}" in "${repository}"...`);
|
||||
const tagListOutput = await asyncUtils.spawn('az',
|
||||
['acr', 'repository', 'show-tags', '--detail', '--name', registryName, '--repository', repository, "--query", `"[?digest=='${imageId}'].name"`],
|
||||
{ shell: true, stdio: 'pipe' });
|
||||
const additionalTags = JSON.parse(tagListOutput);
|
||||
repoAndTagList = repoAndTagList.concat(additionalTags.map((tag) => {
|
||||
return {
|
||||
repository:repository,
|
||||
tag:tag
|
||||
};
|
||||
}));
|
||||
});
|
||||
return repoAndTagList;
|
||||
}
|
||||
|
||||
async function getImageManifests(imageIds, registry) {
|
||||
// ACR registry name is the registry minus .azurecr.io
|
||||
const registryName = registry.replace(/\..*/, '');
|
||||
|
||||
let manifests = [];
|
||||
|
||||
// Get list of repositories
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
"latest": true,
|
||||
"rootDistro": "debian",
|
||||
"tags": [
|
||||
"rust:${VERSION}-1",
|
||||
"rust:${VERSION}"
|
||||
"rust:${VERSION}-1"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
Загрузка…
Ссылка в новой задаче