From 41807610069e5db29e2f27e1f4ff3bbee882dffa Mon Sep 17 00:00:00 2001 From: Christof Marti Date: Thu, 26 Feb 2026 10:01:09 +0100 Subject: [PATCH] Update templates to match latest image tags --- .gitignore | 1 + build/check-image-tags.ts | 260 ++++++++++++++++++ build/list-template-images.ts | 99 +++++++ package-lock.json | 29 ++ package.json | 5 + src/cpp-mariadb/.devcontainer/Dockerfile | 2 +- src/cpp-mariadb/devcontainer-template.json | 2 +- src/cpp/.devcontainer/Dockerfile | 2 +- src/cpp/devcontainer-template.json | 2 +- src/java-postgres/.devcontainer/Dockerfile | 2 +- src/java-postgres/devcontainer-template.json | 14 +- src/java/.devcontainer/devcontainer.json | 2 +- src/java/devcontainer-template.json | 14 +- .../.devcontainer/Dockerfile | 2 +- .../devcontainer-template.json | 6 +- .../.devcontainer/Dockerfile | 2 +- .../devcontainer-template.json | 8 +- .../.devcontainer/devcontainer.json | 2 +- .../devcontainer-template.json | 8 +- src/jekyll/devcontainer-template.json | 3 +- src/php-mariadb/devcontainer-template.json | 10 +- src/php/devcontainer-template.json | 12 +- src/postgres/.devcontainer/Dockerfile | 2 +- src/postgres/devcontainer-template.json | 22 +- src/python/.devcontainer/devcontainer.json | 2 +- src/python/devcontainer-template.json | 11 +- .../.devcontainer/Dockerfile | 2 +- .../devcontainer-template.json | 14 +- src/ruby/.devcontainer/devcontainer.json | 2 +- src/ruby/devcontainer-template.json | 16 +- .../.devcontainer/devcontainer.json | 2 +- .../devcontainer-template.json | 7 +- tsconfig.json | 11 + 33 files changed, 489 insertions(+), 89 deletions(-) create mode 100644 build/check-image-tags.ts create mode 100644 build/list-template-images.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 01a33708..1dc59b5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.DS_Store Thumbs.db +node_modules \ No newline at end of file diff --git a/build/check-image-tags.ts b/build/check-image-tags.ts new file mode 100644 index 00000000..0d319d8e --- /dev/null +++ b/build/check-image-tags.ts @@ -0,0 +1,260 @@ +/** + * Compares the concrete image tags that each template would produce (for every + * proposed option value) against the set of tags the images repo would publish + * (based on each manifest's version, variants, tags and variantTags). + * + * Usage: npx tsx build/check-image-tags.ts + * Example: npx tsx build/check-image-tags.ts ../images + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +const RED = '\x1b[0;31m'; +const GREEN = '\x1b[0;32m'; +const YELLOW = '\x1b[0;33m'; +const NC = '\x1b[0m'; + +const MCR_PREFIX = 'mcr.microsoft.com/devcontainers/'; +const IMAGE_REF_PATTERN = /mcr\.microsoft\.com\/devcontainers\/([^"]+)/g; +const TEMPLATE_OPTION_PATTERN = /\$\{templateOption:([^}]+)\}/; + +interface ImageManifest { + version: string; + variants?: string[]; + build: { + tags?: string[]; + variantTags?: Record; + }; +} + +interface TemplateJson { + options?: Record; +} + +interface TemplateTag { + templateName: string; + relFile: string; + tag: string; +} + +// --- Step 1: Compute all tags that images would publish --- + +function computeImageTags(imagesRepo: string): Set { + const tags = new Set(); + const srcDir = path.join(imagesRepo, 'src'); + + for (const imageDir of fs.readdirSync(srcDir)) { + const manifestPath = path.join(srcDir, imageDir, 'manifest.json'); + if (!fs.existsSync(manifestPath)) continue; + + const manifest: ImageManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')); + const major = manifest.version.split('.')[0]; + const variants = manifest.variants ?? []; + const buildTags = manifest.build.tags ?? []; + const variantTags = manifest.build.variantTags ?? {}; + const versionedTagsOnly = (manifest as any).build?.versionedTagsOnly; + + // The build system generates tags for each version granularity + // (e.g. 2.1.6 -> ['2.1.6', '2.1', '2', '']). We only need major + // and floating (empty) for comparison purposes. + const versions = [major]; + if (!versionedTagsOnly) { + versions.push(''); + } + + // Apply a version+variant to a tag pattern, mimicking the build + // system's replacement logic. + function expandTag(pattern: string, version: string, variant?: string): string | null { + let tag = pattern + .replace(/\$\{VERSION\}/g, version) + .replace(':-', ':') + .replace(/\$\{?VARIANT\}?/g, variant ?? 'NOVARIANT') + .replace('-NOVARIANT', ''); + if (tag.endsWith(':')) return null; + return tag; + } + + for (const version of versions) { + if (variants.length > 0) { + // Expand tags × variants + for (const variant of variants) { + for (const tagPattern of buildTags) { + const tag = expandTag(tagPattern, version, variant); + if (tag) tags.add(tag); + } + } + } else { + // No variants — expand tags directly (e.g. anaconda, universal) + for (const tagPattern of buildTags) { + const tag = expandTag(tagPattern, version); + if (tag) tags.add(tag); + } + } + + // Expand variantTags (these don't use ${VARIANT}) + for (const extraTags of Object.values(variantTags)) { + for (const tagPattern of extraTags) { + const tag = expandTag(tagPattern, version); + if (tag) tags.add(tag); + } + } + } + } + + return tags; +} + +// --- Step 2: Compute all tags that templates would produce --- + +function findFiles(dir: string, names: string[]): string[] { + const results: string[] = []; + function walk(d: string) { + for (const entry of fs.readdirSync(d, { withFileTypes: true })) { + const full = path.join(d, entry.name); + if (entry.isDirectory()) { + walk(full); + } else if (names.includes(entry.name) || names.some(n => n.startsWith('*.') && entry.name.endsWith(n.slice(1)))) { + results.push(full); + } + } + } + walk(dir); + return results; +} + +function computeTemplateTags(templatesDir: string): TemplateTag[] { + const results: TemplateTag[] = []; + + for (const templateName of fs.readdirSync(templatesDir)) { + const templateDir = path.join(templatesDir, templateName); + if (!fs.statSync(templateDir).isDirectory()) continue; + + const templateJsonPath = path.join(templateDir, 'devcontainer-template.json'); + if (!fs.existsSync(templateJsonPath)) continue; + + const templateJson: TemplateJson = JSON.parse(fs.readFileSync(templateJsonPath, 'utf-8')); + const files = findFiles(templateDir, ['devcontainer.json', 'Dockerfile', '*.yml', '*.yaml']); + + for (const file of files) { + const content = fs.readFileSync(file, 'utf-8'); + const relFile = path.relative(templatesDir, file); + const isDockerfile = path.basename(file) === 'Dockerfile'; + + for (const line of content.split('\n')) { + // Skip comment lines + if (isDockerfile && /^\s*#/.test(line)) continue; + if (/^\s*\/\//.test(line)) continue; + + for (const match of line.matchAll(IMAGE_REF_PATTERN)) { + const pattern = match[1]; // e.g. "typescript-node:1-${templateOption:imageVariant}" + const optionMatch = pattern.match(TEMPLATE_OPTION_PATTERN); + + if (optionMatch) { + const optionName = optionMatch[1]; + const option = templateJson.options?.[optionName]; + + if (option) { + const values = [...new Set([...(option.proposals ?? []), ...(option.default != null ? [option.default] : [])])]; + for (const value of values) { + const tag = pattern.replace(`\${templateOption:${optionName}}`, value); + results.push({ templateName, relFile, tag }); + } + } else { + // Option not found in template.json — output raw + results.push({ templateName, relFile, tag: pattern }); + } + } else { + // Static tag + results.push({ templateName, relFile, tag: pattern }); + } + } + } + } + } + + // Deduplicate by templateName + tag, keeping first relFile + const seen = new Map(); + for (const entry of results) { + const key = `${entry.templateName}\t${entry.tag}`; + if (!seen.has(key)) { + seen.set(key, entry); + } + } + + return [...seen.values()].sort((a, b) => + a.templateName.localeCompare(b.templateName) || a.tag.localeCompare(b.tag) + ); +} + +// --- Step 3: Compare --- + +function main() { + const imagesRepo = process.argv[2]; + if (!imagesRepo) { + console.error('Usage: npx tsx build/check-image-tags.ts '); + process.exit(1); + } + + const templatesDir = path.resolve(__dirname, '..', 'src'); + + const imageTags = computeImageTags(imagesRepo); + console.log('=== Published image tags (from manifests) ==='); + console.log(`${imageTags.size} unique tags\n`); + + const templateTags = computeTemplateTags(templatesDir); + console.log('=== Template tags ==='); + console.log(`${templateTags.length} unique template/tag combinations\n`); + + console.log('=== Comparison ===\n'); + + let errors = 0; + let prevTemplate = ''; + + for (const { templateName, relFile, tag } of templateTags) { + if (templateName !== prevTemplate) { + if (prevTemplate) console.log(''); + console.log(`${templateName.padEnd(30)} (${relFile})`); + prevTemplate = templateName; + } + + if (imageTags.has(tag)) { + console.log(` ${GREEN}OK${NC} ${tag}`); + } else { + console.log(` ${RED}MISSING${NC} ${tag}`); + errors++; + } + } + + // Collect the set of all tags referenced by templates + const templateTagSet = new Set(templateTags.map(t => t.tag)); + + // Find image tags not referenced by any template + const unreferencedImageTags = [...imageTags].filter(t => !templateTagSet.has(t)).sort(); + + if (unreferencedImageTags.length > 0) { + console.log('\n=== Image tags not in any template ===\n'); + for (const tag of unreferencedImageTags) { + console.log(` ${YELLOW}UNUSED${NC} ${tag}`); + } + } + + console.log('\n'); + if (errors > 0) { + console.log(`${RED}Found ${errors} template tag(s) not in image manifests.${NC}`); + if (unreferencedImageTags.length > 0) { + console.log(`${YELLOW}Found ${unreferencedImageTags.length} image tag(s) not referenced by any template.${NC}`); + } + process.exit(1); + } else { + console.log(`${GREEN}All template tags match published image tags.${NC}`); + if (unreferencedImageTags.length > 0) { + console.log(`${YELLOW}Found ${unreferencedImageTags.length} image tag(s) not referenced by any template.${NC}`); + } + } +} + +main(); diff --git a/build/list-template-images.ts b/build/list-template-images.ts new file mode 100644 index 00000000..525a5106 --- /dev/null +++ b/build/list-template-images.ts @@ -0,0 +1,99 @@ +/** + * Lists the fully qualified image references (mcr.microsoft.com/devcontainers/...) + * that each template would produce, expanding all proposed option values. + * + * Usage: npx tsx build/list-template-images.ts + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +const MCR_PREFIX = 'mcr.microsoft.com/devcontainers/'; +const IMAGE_REF_PATTERN = /mcr\.microsoft\.com\/devcontainers\/([^"]+)/g; +const TEMPLATE_OPTION_PATTERN = /\$\{templateOption:([^}]+)\}/; + +interface TemplateJson { + options?: Record; +} + +function findFiles(dir: string, names: string[]): string[] { + const results: string[] = []; + function walk(d: string) { + for (const entry of fs.readdirSync(d, { withFileTypes: true })) { + const full = path.join(d, entry.name); + if (entry.isDirectory()) { + walk(full); + } else if (names.includes(entry.name) || names.some(n => n.startsWith('*.') && entry.name.endsWith(n.slice(1)))) { + results.push(full); + } + } + } + walk(dir); + return results; +} + +function main() { + const templatesDir = path.resolve(__dirname, '..', 'src'); + const seen = new Set(); + + for (const templateName of fs.readdirSync(templatesDir).sort()) { + const templateDir = path.join(templatesDir, templateName); + if (!fs.statSync(templateDir).isDirectory()) continue; + + const templateJsonPath = path.join(templateDir, 'devcontainer-template.json'); + if (!fs.existsSync(templateJsonPath)) continue; + + const templateJson: TemplateJson = JSON.parse(fs.readFileSync(templateJsonPath, 'utf-8')); + const files = findFiles(templateDir, ['devcontainer.json', 'Dockerfile', '*.yml', '*.yaml']); + const images: string[] = []; + + for (const file of files) { + const content = fs.readFileSync(file, 'utf-8'); + const isDockerfile = path.basename(file) === 'Dockerfile'; + + for (const line of content.split('\n')) { + if (isDockerfile && /^\s*#/.test(line)) continue; + if (/^\s*\/\//.test(line)) continue; + + for (const match of line.matchAll(IMAGE_REF_PATTERN)) { + const pattern = match[1]; + const optionMatch = pattern.match(TEMPLATE_OPTION_PATTERN); + + if (optionMatch) { + const optionName = optionMatch[1]; + const option = templateJson.options?.[optionName]; + if (option) { + const values = [...new Set([...(option.proposals ?? []), ...(option.default != null ? [option.default] : [])])]; + for (const value of values) { + const ref = MCR_PREFIX + pattern.replace(`\${templateOption:${optionName}}`, value); + if (!seen.has(ref)) { + seen.add(ref); + images.push(ref); + } + } + } + } else { + const ref = MCR_PREFIX + pattern; + if (!seen.has(ref)) { + seen.add(ref); + images.push(ref); + } + } + } + } + } + + if (images.length > 0) { + console.log(`# ${templateName}`); + for (const img of images) { + console.log(img); + } + console.log(''); + } + } +} + +main(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..c06670f0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,29 @@ +{ + "name": "templates", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "devDependencies": { + "@types/node": "^25.3.1" + } + }, + "node_modules/@types/node": { + "version": "25.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.1.tgz", + "integrity": "sha512-hj9YIJimBCipHVfHKRMnvmHg+wfhKc0o4mTtXh9pKBjC8TLJzz0nzGmLi5UJsYAUgSvXFHgb0V2oY10DUFtImw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..ce69e441 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "devDependencies": { + "@types/node": "^25.3.1" + } +} diff --git a/src/cpp-mariadb/.devcontainer/Dockerfile b/src/cpp-mariadb/.devcontainer/Dockerfile index fab07762..cf32009b 100644 --- a/src/cpp-mariadb/.devcontainer/Dockerfile +++ b/src/cpp-mariadb/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/cpp:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/cpp:2-${templateOption:imageVariant} # Everything below this is needed for installing MariaDB # Instructions are copied and modified from: https://mariadb.com/docs/clients/mariadb-connectors/connector-cpp/install/ diff --git a/src/cpp-mariadb/devcontainer-template.json b/src/cpp-mariadb/devcontainer-template.json index 0456ddbf..bcc2b3cf 100644 --- a/src/cpp-mariadb/devcontainer-template.json +++ b/src/cpp-mariadb/devcontainer-template.json @@ -11,8 +11,8 @@ "type": "string", "description": "Debian / Ubuntu version (use Debian 12, Debian 11, Ubuntu 24.04, and Ubuntu 22.04 on local arm64/Apple Silicon):", "proposals": [ + "debian13", "debian12", - "debian11", "ubuntu24.04", "ubuntu22.04" ], diff --git a/src/cpp/.devcontainer/Dockerfile b/src/cpp/.devcontainer/Dockerfile index c105b812..1f7e4e08 100644 --- a/src/cpp/.devcontainer/Dockerfile +++ b/src/cpp/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/cpp:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/cpp:2-${templateOption:imageVariant} ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="${templateOption:reinstallCmakeVersionFromSource}" diff --git a/src/cpp/devcontainer-template.json b/src/cpp/devcontainer-template.json index 11ac0b29..deab8551 100644 --- a/src/cpp/devcontainer-template.json +++ b/src/cpp/devcontainer-template.json @@ -11,8 +11,8 @@ "type": "string", "description": "Debian / Ubuntu version (use Debian 12, Debian 11, Ubuntu 24.04, and Ubuntu 22.04 on local arm64/Apple Silicon):", "proposals": [ + "debian13", "debian12", - "debian11", "ubuntu24.04", "ubuntu22.04" ], diff --git a/src/java-postgres/.devcontainer/Dockerfile b/src/java-postgres/.devcontainer/Dockerfile index 13cbe7e5..1a3ea84d 100644 --- a/src/java-postgres/.devcontainer/Dockerfile +++ b/src/java-postgres/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/java:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/java:3-${templateOption:imageVariant} ARG INSTALL_MAVEN="${templateOption:installMaven}" ARG MAVEN_VERSION="" diff --git a/src/java-postgres/devcontainer-template.json b/src/java-postgres/devcontainer-template.json index 23d07574..9a33ba7b 100644 --- a/src/java-postgres/devcontainer-template.json +++ b/src/java-postgres/devcontainer-template.json @@ -11,16 +11,18 @@ "type": "string", "description": "Java version (use -bookworm, or -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "25-trixie", + "25-bookworm", + "21-trixie", "21-bookworm", + "17-trixie", "17-bookworm", + "11-trixie", "11-bookworm", - "8-bookworm", - "21-bullseye", - "17-bullseye", - "11-bullseye", - "8-bullseye" + "8-trixie", + "8-bookworm" ], - "default": "21-bullseye" + "default": "21-bookworm" }, "installMaven": { "type": "boolean", diff --git a/src/java/.devcontainer/devcontainer.json b/src/java/.devcontainer/devcontainer.json index 4664b357..a3ef6304 100644 --- a/src/java/.devcontainer/devcontainer.json +++ b/src/java/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Java", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/java:1-${templateOption:imageVariant}", + "image": "mcr.microsoft.com/devcontainers/java:3-${templateOption:imageVariant}", "features": { "ghcr.io/devcontainers/features/java:1": { diff --git a/src/java/devcontainer-template.json b/src/java/devcontainer-template.json index 4dc3c394..25252934 100644 --- a/src/java/devcontainer-template.json +++ b/src/java/devcontainer-template.json @@ -11,16 +11,18 @@ "type": "string", "description": "Java version (use -bookworm, or -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "25-trixie", + "25-bookworm", + "21-trixie", "21-bookworm", + "17-trixie", "17-bookworm", + "11-trixie", "11-bookworm", - "8-bookworm", - "21-bullseye", - "17-bullseye", - "11-bullseye", - "8-bullseye" + "8-trixie", + "8-bookworm" ], - "default": "21-bullseye" + "default": "21-bookworm" }, "installMaven": { "type": "boolean", diff --git a/src/javascript-node-mongo/.devcontainer/Dockerfile b/src/javascript-node-mongo/.devcontainer/Dockerfile index 796ba510..c97e3129 100644 --- a/src/javascript-node-mongo/.devcontainer/Dockerfile +++ b/src/javascript-node-mongo/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/javascript-node:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/javascript-node:4-${templateOption:imageVariant} # Install MongoDB command line tools - though mongo-database-tools not available on arm64 ARG MONGO_TOOLS_VERSION=6.0 diff --git a/src/javascript-node-mongo/devcontainer-template.json b/src/javascript-node-mongo/devcontainer-template.json index 6238ea1f..b1766f4f 100644 --- a/src/javascript-node-mongo/devcontainer-template.json +++ b/src/javascript-node-mongo/devcontainer-template.json @@ -11,13 +11,15 @@ "type": "string", "description": "Node.js version (use -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "24-trixie", "24-bookworm", "24-bullseye", + "22-trixie", "22-bookworm", "22-bullseye", + "20-trixie", "20-bookworm", - "20-bullseye", - "18-bullseye" + "20-bullseye" ], "default": "24-bookworm" } diff --git a/src/javascript-node-postgres/.devcontainer/Dockerfile b/src/javascript-node-postgres/.devcontainer/Dockerfile index 75a5be10..3af93a2b 100644 --- a/src/javascript-node-postgres/.devcontainer/Dockerfile +++ b/src/javascript-node-postgres/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/javascript-node:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/javascript-node:4-${templateOption:imageVariant} # [Optional] Uncomment this section to install additional OS packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ diff --git a/src/javascript-node-postgres/devcontainer-template.json b/src/javascript-node-postgres/devcontainer-template.json index d0c88454..cc919640 100644 --- a/src/javascript-node-postgres/devcontainer-template.json +++ b/src/javascript-node-postgres/devcontainer-template.json @@ -11,15 +11,15 @@ "type": "string", "description": "Node.js version (use -bookworm, -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "24-trixie", "24-bookworm", "24-bullseye", + "22-trixie", "22-bookworm", "22-bullseye", + "20-trixie", "20-bookworm", - "20-bullseye", - "18-bookworm", - "20-bullseye", - "18-bullseye" + "20-bullseye" ], "default": "24-bookworm" } diff --git a/src/javascript-node/.devcontainer/devcontainer.json b/src/javascript-node/.devcontainer/devcontainer.json index 1da06303..3cde0288 100644 --- a/src/javascript-node/.devcontainer/devcontainer.json +++ b/src/javascript-node/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Node.js", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/javascript-node:1-${templateOption:imageVariant}" + "image": "mcr.microsoft.com/devcontainers/javascript-node:4-${templateOption:imageVariant}" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/src/javascript-node/devcontainer-template.json b/src/javascript-node/devcontainer-template.json index b33f5861..ead712cc 100644 --- a/src/javascript-node/devcontainer-template.json +++ b/src/javascript-node/devcontainer-template.json @@ -11,15 +11,15 @@ "type": "string", "description": "Node.js version (use -bookworm, -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "24-trixie", "24-bookworm", "24-bullseye", + "22-trixie", "22-bookworm", "22-bullseye", + "20-trixie", "20-bookworm", - "20-bullseye", - "18-bookworm", - "20-bullseye", - "18-bullseye" + "20-bullseye" ], "default": "24-bookworm" } diff --git a/src/jekyll/devcontainer-template.json b/src/jekyll/devcontainer-template.json index dd3cc9f9..23b2db7c 100644 --- a/src/jekyll/devcontainer-template.json +++ b/src/jekyll/devcontainer-template.json @@ -12,8 +12,7 @@ "description": "Debian OS version (use bookworm, or bullseye on local arm64/Apple Silicon):", "proposals": [ "bookworm", - "bullseye", - "buster" + "bullseye" ], "default": "bullseye" } diff --git a/src/php-mariadb/devcontainer-template.json b/src/php-mariadb/devcontainer-template.json index a55dee83..fd506752 100644 --- a/src/php-mariadb/devcontainer-template.json +++ b/src/php-mariadb/devcontainer-template.json @@ -13,15 +13,13 @@ "proposals": [ "8.5-trixie", "8.5-bookworm", - "8.5-bullseye", "8.4-trixie", - "8.4-bookworm", - "8.4-bullseye", + "8.4-bookworm", "8.3-trixie", "8.3-bookworm", - "8.3-bullseye", - "8-bullseye", - "8-trixie" + "8.2-trixie", + "8.2-bookworm", + "8-trixie" ], "default": "8.5-trixie" } diff --git a/src/php/devcontainer-template.json b/src/php/devcontainer-template.json index 6881ce16..217c8c83 100644 --- a/src/php/devcontainer-template.json +++ b/src/php/devcontainer-template.json @@ -13,13 +13,13 @@ "proposals": [ "8.5-trixie", "8.5-bookworm", - "8.5-bullseye", - "8-bookworm", + "8.4-trixie", + "8.4-bookworm", + "8.3-trixie", "8.3-bookworm", - "8.4-bookworm", - "8-bullseye", - "8.3-bullseye", - "8.4-bullseye" + "8.2-trixie", + "8.2-bookworm", + "8-bookworm" ], "default": "8.5-trixie" } diff --git a/src/postgres/.devcontainer/Dockerfile b/src/postgres/.devcontainer/Dockerfile index 917fce58..44c4605a 100644 --- a/src/postgres/.devcontainer/Dockerfile +++ b/src/postgres/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/python:1-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/python:3-${templateOption:imageVariant} ENV PYTHONUNBUFFERED 1 diff --git a/src/postgres/devcontainer-template.json b/src/postgres/devcontainer-template.json index b24554f8..3f9b0d6f 100644 --- a/src/postgres/devcontainer-template.json +++ b/src/postgres/devcontainer-template.json @@ -11,20 +11,20 @@ "type": "string", "description": "Python version (use -bookworm, or -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "3-trixie", + "3.14-trixie", + "3.13-trixie", + "3.12-trixie", + "3.11-trixie", + "3.10-trixie", "3-bookworm", + "3.14-bookworm", + "3.13-bookworm", + "3.12-bookworm", "3.11-bookworm", - "3.10-bookworm", - "3.9-bookworm", - "3-bullseye", - "3.11-bullseye", - "3.10-bullseye", - "3.9-bullseye", - "3-buster", - "3.11-buster", - "3.10-buster", - "3.9-buster" + "3.10-bookworm" ], - "default": "3.11-bullseye" + "default": "3.11-bookworm" } }, "platforms": ["Python"], diff --git a/src/python/.devcontainer/devcontainer.json b/src/python/.devcontainer/devcontainer.json index 7bc38796..f18df52f 100644 --- a/src/python/.devcontainer/devcontainer.json +++ b/src/python/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Python 3", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/python:2-${templateOption:imageVariant}" + "image": "mcr.microsoft.com/devcontainers/python:3-${templateOption:imageVariant}" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/src/python/devcontainer-template.json b/src/python/devcontainer-template.json index 8496b57f..606cb855 100644 --- a/src/python/devcontainer-template.json +++ b/src/python/devcontainer-template.json @@ -17,21 +17,12 @@ "3.12-trixie", "3.11-trixie", "3.10-trixie", - "3.9-trixie", "3-bookworm", "3.14-bookworm", "3.13-bookworm", "3.12-bookworm", "3.11-bookworm", - "3.10-bookworm", - "3.9-bookworm", - "3-bullseye", - "3.14-bullseye", - "3.13-bullseye", - "3.12-bullseye", - "3.11-bullseye", - "3.10-bullseye", - "3.9-bullseye" + "3.10-bookworm" ], "default": "3.14-trixie" } diff --git a/src/ruby-rails-postgres/.devcontainer/Dockerfile b/src/ruby-rails-postgres/.devcontainer/Dockerfile index 47767878..dd84a119 100644 --- a/src/ruby-rails-postgres/.devcontainer/Dockerfile +++ b/src/ruby-rails-postgres/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/ruby:2-${templateOption:imageVariant} +FROM mcr.microsoft.com/devcontainers/ruby:3-${templateOption:imageVariant} # Install Rails RUN su vscode -c "gem install rails webdrivers" diff --git a/src/ruby-rails-postgres/devcontainer-template.json b/src/ruby-rails-postgres/devcontainer-template.json index e277e7ef..e666f548 100644 --- a/src/ruby-rails-postgres/devcontainer-template.json +++ b/src/ruby-rails-postgres/devcontainer-template.json @@ -11,17 +11,17 @@ "type": "string", "description": "Ruby version (use -bookworm, -bullseye variants on local arm64/Apple Silicon):", "proposals": [ - "3-trixie", + "4-trixie", + "4.0-trixie", + "4-bookworm", + "4.0-bookworm", "3.4-trixie", - "3.3-trixie", - "3.2-trixie", - "3-bookworm", "3.4-bookworm", + "3.3-trixie", "3.3-bookworm", - "3.2-bookworm", - "3-bullseye", - "3.4-bullseye", "3.3-bullseye", + "3.2-trixie", + "3.2-bookworm", "3.2-bullseye" ], "default": "3.4-trixie" diff --git a/src/ruby/.devcontainer/devcontainer.json b/src/ruby/.devcontainer/devcontainer.json index eead7386..3f642645 100644 --- a/src/ruby/.devcontainer/devcontainer.json +++ b/src/ruby/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Ruby", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/ruby:2-${templateOption:imageVariant}" + "image": "mcr.microsoft.com/devcontainers/ruby:3-${templateOption:imageVariant}" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/src/ruby/devcontainer-template.json b/src/ruby/devcontainer-template.json index d3ae4051..43822eae 100644 --- a/src/ruby/devcontainer-template.json +++ b/src/ruby/devcontainer-template.json @@ -11,17 +11,17 @@ "type": "string", "description": "Ruby version (use -trixie, -bookworm, -bullseye variants on local arm64/Apple Silicon):", "proposals": [ - "3-trixie", - "3.4-trixie", + "4-trixie", + "4.0-trixie", + "4-bookworm", + "4.0-bookworm", + "3.4-trixie", + "3.4-bookworm", "3.3-trixie", - "3.2-trixie", - "3-bookworm", - "3.4-bookworm", "3.3-bookworm", - "3.2-bookworm", - "3-bullseye", - "3.4-bullseye", "3.3-bullseye", + "3.2-trixie", + "3.2-bookworm", "3.2-bullseye" ], "default": "3.4-trixie" diff --git a/src/typescript-node/.devcontainer/devcontainer.json b/src/typescript-node/.devcontainer/devcontainer.json index 310dbae9..c83df255 100644 --- a/src/typescript-node/.devcontainer/devcontainer.json +++ b/src/typescript-node/.devcontainer/devcontainer.json @@ -3,7 +3,7 @@ { "name": "Node.js & TypeScript", // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/typescript-node:1-${templateOption:imageVariant}" + "image": "mcr.microsoft.com/devcontainers/typescript-node:4-${templateOption:imageVariant}" // Features to add to the dev container. More info: https://containers.dev/features. // "features": {}, diff --git a/src/typescript-node/devcontainer-template.json b/src/typescript-node/devcontainer-template.json index 8e86084a..46d71276 100644 --- a/src/typescript-node/devcontainer-template.json +++ b/src/typescript-node/devcontainer-template.json @@ -11,14 +11,15 @@ "type": "string", "description": "Node.js version (use -bookworm, -bullseye variants on local arm64/Apple Silicon):", "proposals": [ + "24-trixie", "24-bookworm", "24-bullseye", + "22-trixie", "22-bookworm", "22-bullseye", + "20-trixie", "20-bookworm", - "18-bookworm", - "20-bullseye", - "18-bullseye" + "20-bullseye" ], "default": "24-bookworm" } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..901e1c63 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "types": ["node"], + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": ["build/*.ts"] +}