getreadystack commited on
Commit
b0c5b00
·
verified ·
1 Parent(s): 7e94e85

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +75 -18
index.html CHANGED
@@ -1,19 +1,76 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html><html lang="en"><meta charset="utf-8">
2
+ <meta name="viewport" content="width=device-width,initial-scale=1">
3
+ <title>Base Image EOL Lint - Dockerfile and CI end-of-life check</title>
4
+ <meta name="description" content="Marks every base image in your Dockerfiles, compose files and CI workflows whose security patches have already stopped - or stop before 13 November 2026 - and prints the tag that replaces it.">
5
+ <script defer data-auto-init src="https://cdn.jsdelivr.net/npm/@polar-sh/checkout@latest/dist/embed.global.js"></script>
6
+ <style>
7
+ :root{color-scheme:light dark}
8
+ body{margin:0;font:16px/1.6 system-ui,-apple-system,"Segoe UI",sans-serif;
9
+ background:#fbfbfa;color:#16161d}
10
+ @media(prefers-color-scheme:dark){body{background:#14141a;color:#e8e8ea}}
11
+ .wrap{max-width:880px;margin:0 auto;padding:28px 20px 64px}
12
+ h1{font-size:1.7rem;line-height:1.25;margin:.2em 0 .3em}
13
+ p.sub{margin:0 0 1.4em;opacity:.8}
14
+ textarea{width:100%;min-height:230px;font:13px/1.5 ui-monospace,Menlo,Consolas,monospace;
15
+ padding:12px;border:1px solid #c9c9d1;border-radius:10px;background:transparent;color:inherit;
16
+ box-sizing:border-box}
17
+ button{font:600 15px/1 inherit;padding:12px 22px;border:0;border-radius:10px;
18
+ background:#1d4ed8;color:#fff;cursor:pointer;margin:12px 0}
19
+ button:hover{background:#1a43bd}
20
+ table{border-collapse:collapse;width:100%;margin-top:14px;font-size:14px}
21
+ th,td{border-bottom:1px solid #d8d8e0;padding:8px 6px;text-align:left;vertical-align:top}
22
+ th{font-weight:600;opacity:.75}
23
+ td.n{width:64px;font:13px ui-monospace,monospace;opacity:.7}
24
+ .ok{padding:14px;border-radius:10px;background:#e8f5ec;color:#14532d;margin-top:14px}
25
+ @media(prefers-color-scheme:dark){.ok{background:#15321f;color:#bbf7d0}}
26
+ .next{margin-top:30px;padding:18px;border:1px solid #d8d8e0;border-radius:12px}
27
+ .next h2{font-size:1.05rem;margin:0 0 .5em}
28
+ .next ul{margin:.3em 0 1em 1.1em;padding:0}
29
+ </style>
30
+ <div class="wrap">
31
+ <h1>Base Image EOL Lint - Dockerfile and CI end-of-life check</h1>
32
+ <p class="sub">Marks every base image in your Dockerfiles, compose files and CI workflows whose security patches have already stopped - or stop before 13 November 2026 - and prints the tag that replaces it.</p>
33
+ <textarea id="src" placeholder="Paste a Dockerfile, docker-compose.yml or CI workflow here"># web/Dockerfile
34
+ FROM node:20-alpine
35
+ # api/Dockerfile
36
+ FROM python:3.10-slim
37
+ # .github/workflows/ci.yml
38
+ runs-on: ubuntu-20.04
39
+ # docker-compose.yml
40
+ image: postgres:14
41
+ # services/report/Dockerfile
42
+ FROM mcr.microsoft.com/dotnet/aspnet:8.0
43
+ </textarea>
44
+ <button id="go">Check these images</button>
45
+ <div id="out"></div>
46
+ <div class="next"><h2>In the full version</h2><ul><li>Every Dockerfile, compose file and workflow in the repository</li><li>A dated CSV, JSON or HTML report</li><li>JSON output that fails the build</li><li><a href="https://buy.polar.sh/polar_cl_brZKgBkvnYrEIMElB5Ynt5gGEnqmTjvx9r9ZX3ljztR" data-polar-checkout data-polar-checkout-theme="light">Get the full version - $29</a></li></ul></div>
47
+ </div>
48
+ <script>
49
+ var RULES=[{"pattern": "\\bnode:20\\b", "flags": "i", "sev": "error", "message": "node:20 - Node.js 20 reached end-of-life on 30 April 2026. No security release has shipped for it since. Replace with node:24-trixie (Active LTS to 30 April 2028).", "fix": "FROM node:24-trixie"}, {"pattern": "\\bnode:18\\b", "flags": "i", "sev": "error", "message": "node:18 - Node.js 18 reached end-of-life on 30 April 2025. Replace with node:24-trixie (Active LTS to 30 April 2028).", "fix": "FROM node:24-trixie"}, {"pattern": "\\bnode:(?:14|16)\\b", "flags": "i", "sev": "error", "message": "Node.js 14 (end-of-life 30 April 2023) and Node.js 16 (11 September 2023) have been unpatched for over two years. Replace with node:24-trixie.", "fix": "FROM node:24-trixie"}, {"pattern": "\\bpython:3\\.(?:7|8|9)\\b", "flags": "i", "sev": "error", "message": "Python 3.9 reached end-of-life on 31 October 2025 (3.8 on 7 October 2024, 3.7 on 27 June 2023). 3.9.25 was the final security release. Replace with python:3.13-trixie.", "fix": "FROM python:3.13-trixie"}, {"pattern": "\\bpython:3\\.10\\b", "flags": "i", "sev": "warn", "message": "python:3.10 - Python 3.10 reaches end-of-life on 31 October 2026. After that date the PSF ships no further security patches. Replace with python:3.13-trixie.", "fix": "FROM python:3.13-trixie"}, {"pattern": "\\b(?:debian:11|bullseye)\\b", "flags": "i", "sev": "error", "message": "Debian 11 bullseye LTS ended on 31 August 2026 - no security updates from September 2026 onward. Replace with debian:trixie, or bookworm if you need LTS to 30 June 2028.", "fix": "FROM debian:trixie"}, {"pattern": "\\b(?:debian:(?:8|9|10)|buster|stretch|jessie)\\b", "flags": "i", "sev": "error", "message": "Debian 10 buster LTS ended on 30 June 2024; stretch and jessie are older still. Replace with debian:trixie.", "fix": "FROM debian:trixie"}, {"pattern": "\\b(?:ubuntu:20\\.04|ubuntu-20\\.04|ubuntu:focal|:focal\\b)", "flags": "i", "sev": "error", "message": "Ubuntu 20.04 focal left standard support on 31 May 2025. Patches now require a paid Ubuntu Pro (ESM) subscription. Replace with ubuntu:24.04, supported to April 2029.", "fix": "FROM ubuntu:24.04"}, {"pattern": "\\b(?:ubuntu:1[68]\\.04|ubuntu-1[68]\\.04|bionic|xenial)\\b", "flags": "i", "sev": "error", "message": "Ubuntu 18.04 bionic and 16.04 xenial left standard support in 2023 and 2021. Replace with ubuntu:24.04.", "fix": "FROM ubuntu:24.04"}, {"pattern": "\\balpine:3\\.(?:[0-9]|1[0-9]|20)\\b", "flags": "i", "sev": "error", "message": "This Alpine branch is out of support: 3.20 ended 1 April 2026, 3.19 on 1 November 2025, and everything older before that. Replace with alpine:3.23 (supported to 1 November 2027).", "fix": "FROM alpine:3.23"}, {"pattern": "\\balpine:3\\.21\\b", "flags": "i", "sev": "warn", "message": "alpine:3.21 - Alpine keeps a branch for two years, so 3.21 reaches end of support on 1 November 2026. Replace with alpine:3.23 (to 1 November 2027).", "fix": "FROM alpine:3.23"}, {"pattern": "\\bdotnet/(?:aspnet|sdk|runtime|samples):(?:6|7)\\.0\\b", "flags": "i", "sev": "error", "message": ".NET 6 reached end of support on 12 November 2024 and .NET 7 on 14 May 2024. Replace with mcr.microsoft.com/dotnet/aspnet:10.0 (LTS to 14 November 2028).", "fix": "FROM mcr.microsoft.com/dotnet/aspnet:10.0"}, {"pattern": "\\bdotnet/(?:aspnet|sdk|runtime|samples):(?:8|9)\\.0\\b", "flags": "i", "sev": "warn", "message": ".NET 8 (LTS) and .NET 9 (STS) both reach end of support on 10 November 2026 - the LTS release dies on the same day as the STS one. Replace with dotnet/aspnet:10.0, LTS to 14 November 2028.", "fix": "FROM mcr.microsoft.com/dotnet/aspnet:10.0"}, {"pattern": "\\bpostgres(?:ql)?:(?:9\\.[0-9]|1[0-3])\\b", "flags": "i", "sev": "error", "message": "PostgreSQL 13 reached end of life on 13 November 2025; 12 and older are further behind. The community ships no security patches for them. Replace with postgres:17.", "fix": "image: postgres:17"}, {"pattern": "\\bpostgres(?:ql)?:14\\b", "flags": "i", "sev": "warn", "message": "postgres:14 - PostgreSQL supports a major version for five years, so 14 reaches end of life on 12 November 2026. Replace with postgres:17.", "fix": "image: postgres:17"}, {"pattern": "\\bmysql:5\\.[0-9]\\b", "flags": "i", "sev": "error", "message": "MySQL 5.7 reached end of life on 31 October 2023 and 5.6 in February 2021. Replace with mysql:8.4, the current LTS.", "fix": "image: mysql:8.4"}, {"pattern": "\\bphp:(?:7\\.[0-9]|8\\.[01])\\b", "flags": "i", "sev": "error", "message": "PHP 8.1 security support ended on 31 December 2025; 8.0 and every 7.x are older. Replace with php:8.4-trixie.", "fix": "FROM php:8.4-trixie"}, {"pattern": "\\bphp:8\\.2\\b", "flags": "i", "sev": "warn", "message": "php:8.2 - PHP 8.2 reaches end of life on 31 December 2026, after which the PHP project ships no patches for it. Replace with php:8.4-trixie.", "fix": "FROM php:8.4-trixie"}, {"pattern": "\\bcentos:(?:6|7|8|stream8)\\b", "flags": "i", "sev": "error", "message": "CentOS 7 reached end of life on 30 June 2024 and CentOS 8 on 31 December 2021. The distribution line is finished. Replace with a maintained base such as debian:trixie.", "fix": "FROM debian:trixie"}, {"pattern": "\\bopenjdk:", "flags": "i", "sev": "warn", "message": "The openjdk Docker Official Image is deprecated and no longer updated. Replace with eclipse-temurin:21-jre-noble.", "fix": "FROM eclipse-temurin:21-jre-noble"}, {"pattern": "\\b[\\w./-]+:latest\\b", "flags": "i", "sev": "info", "message": "A :latest tag floats. The image you build today is not the image you built last month, so no end-of-life check - this one included - can tell you what is actually in the layer. Pin a dated tag.", "fix": "pin an explicit tag, e.g. FROM debian:trixie"}];
50
+ function scan(t){var L=String(t).split(/\r?\n/),h=[],i,r,re;
51
+ for(i=0;i<L.length;i++){for(var k=0;k<RULES.length;k++){r=RULES[k];
52
+ try{re=new RegExp(r.pattern,r.flags||'')}catch(e){continue}
53
+ if(re.test(L[i]))h.push({line:i+1,msg:r.message})}}
54
+ return h}
55
+ document.getElementById('go').onclick=function(){
56
+ var t=document.getElementById('src').value,o=document.getElementById('out');
57
+ if(!t.trim()){o.innerHTML='';return}
58
+ var h=scan(t);
59
+ if(!h.length){o.innerHTML='<div class="ok">No end-of-life base images in this file</div>';return}
60
+ var s='<table><tr><th>Line</th><th>Finding</th></tr>';
61
+ for(var i=0;i<h.length;i++){s+='<tr><td class="n">'+h[i].line+'</td><td>'+
62
+ String(h[i].msg).replace(/&/g,'&amp;').replace(/</g,'&lt;')+'</td></tr>'}
63
+ o.innerHTML=s+'</table>'};
64
+ document.getElementById('go').click();
65
+ </script>
66
  </html>
67
+
68
+
69
+ <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://marketplace.visualstudio.com/items?itemName=ReadyStack.base-image-eol-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">VS Code Marketplace</a><a href="https://open-vsx.org/extension/readystack/base-image-eol-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/base-image-eol-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://www.npmjs.com/package/@readystack/base-image-eol-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">MCP server (npx)</a><a href="https://hub.docker.com/r/getreadystack/base-image-eol-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">ext install ReadyStack.base-image-eol-lint
70
+ npx @readystack/base-image-eol-lint &lt;file&gt;
71
+ npx @readystack/base-image-eol-lint --mcp</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://buy.polar.sh/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
72
+ <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get one email when this rule changes</b><div style="opacity:.78;margin:.35rem 0 .8rem">We watch the regulation and vendor sources behind Base Image EOL Lint - Dockerfile and CI end-of-life check every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Notify me</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">You're on the list. One email when it changes.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"base-image-eol-lint",lang:"en",source:"rule_alert"})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script></section>
73
+
74
+ <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Marks every base image in your Dockerfiles, compose files and CI workflows whose security patches have already stopped - or stop before 13 November 2026 - and prints the tag that replaces it</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">Snyk's Team tier is $25 per contributing developer per month.</p><a href="https://buy.polar.sh/polar_cl_brZKgBkvnYrEIMElB5Ynt5gGEnqmTjvx9r9ZX3ljztR" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
75
+ <section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does Base Image EOL Lint actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads the image references written in your repository - Dockerfile FROM lines, docker-compose image keys, GitHub Actions runner labels and container images - and marks every one whose vendor has stopped shipping security patches, or stops soon, with the exact tag that replaces it and the date behind the finding.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is it for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Platform, DevOps and backend engineers who own the Dockerfiles and CI workflows in a repository: the person who answers when an auditor asks which base images are still supported, and the person who has to do the upgrade. If you maintain a multi-stage Dockerfile or a compose file, this reads your files.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why will a free image scanner not do this?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free scanners test an image that has already been built and pushed, and they report the vulnerable packages inside it. They cannot open the Dockerfile on your screen and tell you that FROM python:3.10-slim names a runtime whose final security release lands on 31 October 2026. Nothing that needs a built image can.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a licence?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free covers one whole file: open a Dockerfile, run the check, and all 21 rules report every finding with its severity and its replacement tag. Nothing is watermarked, timed or locked after N runs. The licence changes the scope only - every file in the repository at once, a dated exported report, and JSON for CI.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost otherwise?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Snyk&#x27;s Team tier is $25 per contributing developer per month, and it still starts from a built image rather than the file you are editing. Auditing FROM lines by hand means grepping every repository each time a vendor retires a branch, which happens several times a year. This is $29 once.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does Base Image EOL Lint actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads the image references written in your repository - Dockerfile FROM lines, docker-compose image keys, GitHub Actions runner labels and container images - and marks every one whose vendor has stopped shipping security patches, or stops soon, with the exact tag that replaces it and the date behind the finding."}}, {"@type": "Question", "name": "Who is it for?", "acceptedAnswer": {"@type": "Answer", "text": "Platform, DevOps and backend engineers who own the Dockerfiles and CI workflows in a repository: the person who answers when an auditor asks which base images are still supported, and the person who has to do the upgrade. If you maintain a multi-stage Dockerfile or a compose file, this reads your files."}}, {"@type": "Question", "name": "Why will a free image scanner not do this?", "acceptedAnswer": {"@type": "Answer", "text": "Free scanners test an image that has already been built and pushed, and they report the vulnerable packages inside it. They cannot open the Dockerfile on your screen and tell you that FROM python:3.10-slim names a runtime whose final security release lands on 31 October 2026. Nothing that needs a built image can."}}, {"@type": "Question", "name": "What is free and what needs a licence?", "acceptedAnswer": {"@type": "Answer", "text": "Free covers one whole file: open a Dockerfile, run the check, and all 21 rules report every finding with its severity and its replacement tag. Nothing is watermarked, timed or locked after N runs. The licence changes the scope only - every file in the repository at once, a dated exported report, and JSON for CI."}}, {"@type": "Question", "name": "What would this cost otherwise?", "acceptedAnswer": {"@type": "Answer", "text": "Snyk's Team tier is $25 per contributing developer per month, and it still starts from a built image rather than the file you are editing. Auditing FROM lines by hand means grepping every repository each time a vendor retires a branch, which happens several times a year. This is $29 once."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:0,slug:"base-image-eol-lint",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence, 7-day refund.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/docker-image-for-development"><span class="yj-rel-t">Docker Image for Development — Node.js 22 + TypeScript Dev Container with Post</span><span class="yj-rel-p">$19</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/runtime-eol-deploy-block-audit"><span class="yj-rel-t">Runtime EOL and Deploy-Block Audit for Docker, CI and AWS Lambda</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/data-science-docker-image"><span class="yj-rel-t">Data Science Docker Image — JupyterLab 4 + Python 3.12 Analytics Stack (non-ro</span><span class="yj-rel-p">$19</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/docker-image-for-data-science"><span class="yj-rel-t">Docker Image for Data Science — Reproducible JupyterLab + MLflow Stack (Python</span><span class="yj-rel-p">$19</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/webflow-restaurant-template"><span class="yj-rel-t">Webflow Restaurant Template — delivered as self-contained HTML you own: 26 pag</span><span class="yj-rel-p">$49</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/actions-deprecation-lint-2026"><span class="yj-rel-t">GitHub Actions Deprecation Lint: the 2026 runner and action EOL dates</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section><!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>
76
+ <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||'')})}).catch(function(){});}catch(e){}})();</script>