Upload index.html with huggingface_hub
Browse files- index.html +331 -17
index.html
CHANGED
|
@@ -1,19 +1,333 @@
|
|
| 1 |
<!doctype html>
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
<!doctype html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="utf-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
| 6 |
+
<title>Helm Kubernetes compatibility — check your chart before release</title>
|
| 7 |
+
<meta name="description" content="This free browser tool checks Chart.yaml fields, Kubernetes version ranges, and CI files pinned to Helm 3.">
|
| 8 |
+
<style>
|
| 9 |
+
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
|
| 10 |
+
.wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
|
| 11 |
+
textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
|
| 12 |
+
.bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
|
| 13 |
+
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
|
| 14 |
+
table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
|
| 15 |
+
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
|
| 16 |
+
.note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
|
| 17 |
+
</style>
|
| 18 |
+
<script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
|
| 19 |
+
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/chart-yaml-release-gate"><style data-yj-mfit="1">#out{max-width:100%}#out td,#out th{overflow-wrap:anywhere}#out pre,#out code{white-space:pre-wrap;overflow-wrap:anywhere}@media (max-width:640px){table{display:block;max-width:100%;overflow-x:auto}pre{max-width:100%;overflow-x:auto}code,a{overflow-wrap:anywhere}img,svg,video,canvas,iframe{max-width:100%}textarea,input,select{max-width:100%;box-sizing:border-box}.yj-lgbar{position:static!important;justify-content:flex-end;margin:0 0 10px}h1,h2,h3,h4,p,li,dd,dt,blockquote,figcaption,summary,label,.res,.lead{overflow-wrap:anywhere}label{max-width:100%;box-sizing:border-box}#out table:not(:has(tr>:nth-child(4))){display:table;table-layout:fixed;width:100%}#out table:has(tr>:nth-child(4)),#out table:has(tr>:nth-child(4)) tbody,#out table:has(tr>:nth-child(4)) tr,#out table:has(tr>:nth-child(4)) td{display:block;width:auto;overflow:visible}#out table:has(tr>:nth-child(4)) thead{display:none}#out table:has(tr>:nth-child(4)) tr{padding:10px 0;border-bottom:1px solid rgba(128,128,128,.28)}#out table:has(tr>:nth-child(4)) td{border:0;padding:1px 0}#out table:has(tr>:nth-child(4)) td:nth-child(-n+3){display:inline-block;margin-right:10px;font-size:12px;opacity:.78}}</style>
|
| 20 |
+
</head>
|
| 21 |
+
<body>
|
| 22 |
+
<div class="wrap">
|
| 23 |
+
<h1>Helm Kubernetes compatibility — check your chart before release</h1>
|
| 24 |
+
<p class="lede">Lint Chart.yaml before helm package: SemVer 2 version, apiVersion v2 fields, unquoted appVersion, kubeVersion ranges stuck on EOL Kubernetes, and CI files still pinned to Helm 3 (security fixes end 2026-11-11). Runs entirely in your browser — nothing is uploaded.</p>
|
| 25 |
+
<textarea id="src" spellcheck="false">apiVersion: v1
|
| 26 |
+
name: payments-api
|
| 27 |
+
description: Payments API service chart for the platform team.
|
| 28 |
+
version: v2.4
|
| 29 |
+
appVersion: 1.10
|
| 30 |
+
kubeVersion: ">=1.25.0 <1.35.0"
|
| 31 |
+
owner: platform-team
|
| 32 |
+
dependencies:
|
| 33 |
+
- name: postgresql
|
| 34 |
+
version: "15.5.0"
|
| 35 |
+
repository: oci://registry.example.com/charts
|
| 36 |
+
maintainers:
|
| 37 |
+
- name: Platform Team
|
| 38 |
+
email: platform@example.com</textarea>
|
| 39 |
+
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
|
| 40 |
+
<div id="out" aria-live="polite"></div>
|
| 41 |
+
<div id="paid"><strong>Free here:</strong> Lint every Chart.yaml and CI file in the workspace and show each broken line with the exact replacement line, no key needed.. <strong>In the editor:</strong> Team key: a dated Helm 4 readiness report (Markdown + JSON) covering every chart in the repo, plus a CI gate that fails the build on any finding. — that part asks for a licence key.</div>
|
| 42 |
+
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
|
| 43 |
+
</div>
|
| 44 |
+
<script>var CHARTGATE_RULES = [
|
| 45 |
+
{
|
| 46 |
+
"id": "api-missing",
|
| 47 |
+
"sev": "error",
|
| 48 |
+
"title": "apiVersion is missing",
|
| 49 |
+
"fix": "apiVersion: v2",
|
| 50 |
+
"source": "helm.sh/docs/topics/charts: apiVersion is required"
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"id": "api-v1",
|
| 54 |
+
"sev": "warning",
|
| 55 |
+
"title": "apiVersion v1 is the pre-Helm-3 chart format",
|
| 56 |
+
"fix": "apiVersion: v2",
|
| 57 |
+
"source": "helm.sh/docs/topics/charts: apiVersion should be v2 for charts that require at least Helm 3"
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"id": "api-unknown",
|
| 61 |
+
"sev": "error",
|
| 62 |
+
"title": "apiVersion is neither v1 nor v2",
|
| 63 |
+
"fix": "apiVersion: v2",
|
| 64 |
+
"source": "helm.sh/docs/topics/charts: The apiVersion Field"
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"id": "name-missing",
|
| 68 |
+
"sev": "error",
|
| 69 |
+
"title": "name is missing",
|
| 70 |
+
"fix": "name: \u003cchart-name\u003e",
|
| 71 |
+
"source": "helm.sh/docs/topics/charts: name is required"
|
| 72 |
+
},
|
| 73 |
+
{
|
| 74 |
+
"id": "version-missing",
|
| 75 |
+
"sev": "error",
|
| 76 |
+
"title": "version is missing",
|
| 77 |
+
"fix": "version: 0.1.0",
|
| 78 |
+
"source": "helm.sh/docs/topics/charts: Every chart must have a version number"
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"id": "version-not-semver",
|
| 82 |
+
"sev": "error",
|
| 83 |
+
"title": "version is not SemVer 2",
|
| 84 |
+
"fix": "version: MAJOR.MINOR.PATCH",
|
| 85 |
+
"source": "helm.sh/docs/topics/charts: non-SemVer names are explicitly disallowed"
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"id": "version-coerced",
|
| 89 |
+
"sev": "warning",
|
| 90 |
+
"title": "version gets coerced (leading v or fewer than 3 parts)",
|
| 91 |
+
"fix": "version: MAJOR.MINOR.PATCH",
|
| 92 |
+
"source": "helm.sh/docs/topics/charts: v1.2 is coerced to v1.2.0; the package name must match the Chart.yaml version"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"id": "v2-field-on-v1",
|
| 96 |
+
"sev": "error",
|
| 97 |
+
"title": "dependencies/type only exist in apiVersion v2",
|
| 98 |
+
"fix": "apiVersion: v2",
|
| 99 |
+
"source": "helm.sh/docs/topics/charts: v2 added dependencies (was requirements.yaml) and type"
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"id": "type-invalid",
|
| 103 |
+
"sev": "error",
|
| 104 |
+
"title": "type must be application or library",
|
| 105 |
+
"fix": "type: application",
|
| 106 |
+
"source": "helm.sh/docs/topics/charts: Chart Types"
|
| 107 |
+
},
|
| 108 |
+
{
|
| 109 |
+
"id": "dep-incomplete",
|
| 110 |
+
"sev": "error",
|
| 111 |
+
"title": "dependency lacks name or version",
|
| 112 |
+
"fix": "- name: \u003cchart\u003e\n version: \"1.2.3\"",
|
| 113 |
+
"source": "helm.sh/docs/topics/charts: dependencies[].name and version"
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"id": "appversion-unquoted",
|
| 117 |
+
"sev": "warning",
|
| 118 |
+
"title": "appVersion is unquoted and YAML reads it as a number",
|
| 119 |
+
"fix": "appVersion: \"\u003cvalue\u003e\"",
|
| 120 |
+
"source": "helm.sh/docs/topics/charts: YAML interprets 1.0 as a float and 1234e10 as scientific notation"
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"id": "kube-no-supported",
|
| 124 |
+
"sev": "error",
|
| 125 |
+
"title": "kubeVersion allows no Kubernetes minor still supported",
|
| 126 |
+
"fix": "kubeVersion: \"\u003e=1.33.0-0\" (no upper cap below the newest minor)",
|
| 127 |
+
"source": "helm.sh/docs/topics/charts: Helm fails the install if the cluster version is outside kubeVersion; EOL dates from kubernetes.io releases"
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"id": "kube-eol-soon",
|
| 131 |
+
"sev": "warning",
|
| 132 |
+
"title": "kubeVersion only allows Kubernetes minors reaching end of life within 90 days",
|
| 133 |
+
"fix": "kubeVersion: \"\u003e=1.33.0-0\" (no upper cap below the newest minor)",
|
| 134 |
+
"source": "helm.sh/docs/topics/charts: The kubeVersion Field; EOL dates from kubernetes.io releases"
|
| 135 |
+
},
|
| 136 |
+
{
|
| 137 |
+
"id": "unknown-field",
|
| 138 |
+
"sev": "error",
|
| 139 |
+
"title": "field is not part of Chart.yaml",
|
| 140 |
+
"fix": "annotations:\n \u003ckey\u003e: \"\u003cvalue\u003e\"",
|
| 141 |
+
"source": "helm.sh/docs/topics/charts: As of v3.3.2, additional fields are not allowed; use annotations"
|
| 142 |
+
},
|
| 143 |
+
{
|
| 144 |
+
"id": "deprecated-not-bool",
|
| 145 |
+
"sev": "warning",
|
| 146 |
+
"title": "deprecated must be true or false",
|
| 147 |
+
"fix": "deprecated: true",
|
| 148 |
+
"source": "helm.sh/docs/topics/charts: deprecated (optional, boolean)"
|
| 149 |
+
},
|
| 150 |
+
{
|
| 151 |
+
"id": "helm3-pin",
|
| 152 |
+
"sev": "warning",
|
| 153 |
+
"title": "CI or image pins Helm 3",
|
| 154 |
+
"fix": "version: v4.3.0",
|
| 155 |
+
"source": "helm.sh/blog/helm-4-released: Helm v3 bug fixes until 2026-07-08, security fixes until 2026-11-11"
|
| 156 |
+
}
|
| 157 |
+
];</script>
|
| 158 |
+
<script>/* Chart.yaml release gate: Helm chart spec checks + Helm 3 pin map. Same file runs in node and the browser. */
|
| 159 |
+
(function () {
|
| 160 |
+
var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.CHARTGATE_RULES;
|
| 161 |
+
var BY = {}; RULES.forEach(function (r) { BY[r.id] = r; });
|
| 162 |
+
var HELM3_SECURITY_END = '2026-11-11';
|
| 163 |
+
// Kubernetes minor -> end of life (kubernetes.io/releases, via endoflife.date, read 2026-09-30)
|
| 164 |
+
var KUBE_EOL = { 28: '2024-10-28', 29: '2025-02-28', 30: '2025-07-15', 31: '2025-11-11', 32: '2026-02-28',
|
| 165 |
+
33: '2026-06-28', 34: '2026-10-27', 35: '2027-02-28', 36: '2027-06-28', 37: '2027-10-28' };
|
| 166 |
+
var KNOWN = ['apiVersion', 'name', 'version', 'kubeVersion', 'description', 'type', 'keywords', 'home', 'sources',
|
| 167 |
+
'dependencies', 'maintainers', 'icon', 'appVersion', 'deprecated', 'annotations'];
|
| 168 |
+
|
| 169 |
+
function days(a, b) { return Math.round((Date.parse(b + 'T00:00:00Z') - Date.parse(a + 'T00:00:00Z')) / 864e5); }
|
| 170 |
+
function unq(v) { v = v.replace(/\s+#.*$/, '').trim(); var m = v.match(/^(["'])(.*)\1$/); return m ? m[2] : v; }
|
| 171 |
+
function isoDay(t) { var m = String(t || '').match(/(\d{4})-(\d{2})-(\d{2})/); return m && !isNaN(Date.parse(m[0])) ? m[0] : new Date().toISOString().slice(0, 10); }
|
| 172 |
+
|
| 173 |
+
// --- minimal semver constraint check (Masterminds syntax subset used in Chart.yaml) ---
|
| 174 |
+
function pv(s) {
|
| 175 |
+
var m = String(s).trim().replace(/^v/, '').replace(/[-+].*$/, '').split('.');
|
| 176 |
+
return m.map(function (x) { return /^[xX*]$/.test(x) ? null : parseInt(x, 10); });
|
| 177 |
+
}
|
| 178 |
+
function cmp(a, b) { for (var i = 0; i < 3; i++) { var d = (a[i] || 0) - (b[i] || 0); if (d) return d; } return 0; }
|
| 179 |
+
function term(op, raw, v) {
|
| 180 |
+
var p = pv(raw), n = p.filter(function (x) { return x !== null && !isNaN(x); }).length;
|
| 181 |
+
var lo = [p[0] || 0, n > 1 ? p[1] : 0, n > 2 ? p[2] : 0], hi;
|
| 182 |
+
if (n === 1) hi = [lo[0] + 1, 0, 0]; else if (n === 2) hi = [lo[0], lo[1] + 1, 0]; else hi = null;
|
| 183 |
+
if (op === '~') return cmp(v, lo) >= 0 && cmp(v, n === 1 ? [lo[0] + 1, 0, 0] : [lo[0], lo[1] + 1, 0]) < 0;
|
| 184 |
+
if (op === '^') return cmp(v, lo) >= 0 && cmp(v, lo[0] > 0 ? [lo[0] + 1, 0, 0] : [0, lo[1] + 1, 0]) < 0;
|
| 185 |
+
if (op === '' || op === '=') return hi ? (cmp(v, lo) >= 0 && cmp(v, hi) < 0) : cmp(v, lo) === 0;
|
| 186 |
+
if (op === '!=') return hi ? !(cmp(v, lo) >= 0 && cmp(v, hi) < 0) : cmp(v, lo) !== 0;
|
| 187 |
+
if (op === '>=') return cmp(v, lo) >= 0;
|
| 188 |
+
if (op === '>') return hi ? cmp(v, hi) >= 0 : cmp(v, lo) > 0;
|
| 189 |
+
if (op === '<') return cmp(v, lo) < 0;
|
| 190 |
+
if (op === '<=') return hi ? cmp(v, hi) < 0 : cmp(v, lo) <= 0;
|
| 191 |
+
return true;
|
| 192 |
+
}
|
| 193 |
+
function satisfies(range, v) {
|
| 194 |
+
return range.split('||').some(function (grp) {
|
| 195 |
+
grp = grp.trim().replace(/(\S+)\s+-\s+(\S+)/g, '>=$1 <=$2').replace(/([<>=!~^]+)\s+/g, '$1');
|
| 196 |
+
return grp.split(/[\s,]+/).filter(Boolean).every(function (t) {
|
| 197 |
+
var m = t.match(/^(>=|<=|!=|>|<|=|~>?|\^)?(.+)$/);
|
| 198 |
+
return term((m[1] || '').replace('~>', '~'), m[2], v);
|
| 199 |
+
});
|
| 200 |
+
});
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
function check(text, opts) {
|
| 204 |
+
opts = opts || {};
|
| 205 |
+
var today = isoDay(opts.today);
|
| 206 |
+
var lines = String(text || '').replace(/\r\n?/g, '\n').replace(/\t/g, ' ').split('\n');
|
| 207 |
+
var out = [];
|
| 208 |
+
function add(id, line, detail, fix) {
|
| 209 |
+
var r = BY[id];
|
| 210 |
+
out.push({ check: id, sev: r.sev, line: line, msg: r.title + (detail ? ' - ' + detail : '') + '. Fix: ' + (fix || r.fix).replace(/\n\s*/g, ' / ') });
|
| 211 |
+
}
|
| 212 |
+
var top = {}, order = [];
|
| 213 |
+
lines.forEach(function (l, i) {
|
| 214 |
+
var m = l.match(/^([A-Za-z_][\w.-]*)\s*:\s*(.*)$/);
|
| 215 |
+
if (m && !top[m[1]]) { top[m[1]] = { v: m[2], line: i + 1 }; order.push(m[1]); }
|
| 216 |
+
});
|
| 217 |
+
var isChart = !top.kind && !top.jobs && !top.on && !top.stages && (top.apiVersion || (top.name && top.version));
|
| 218 |
+
|
| 219 |
+
if (isChart) {
|
| 220 |
+
var api = top.apiVersion ? unq(top.apiVersion.v) : null;
|
| 221 |
+
if (!top.apiVersion) add('api-missing', 1);
|
| 222 |
+
else if (api === 'v1') add('api-v1', top.apiVersion.line, 'charts that require at least Helm 3 should say v2');
|
| 223 |
+
else if (api !== 'v2') add('api-unknown', top.apiVersion.line, 'found "' + api + '"');
|
| 224 |
+
if (!top.name || !unq(top.name.v)) add('name-missing', top.name ? top.name.line : 1);
|
| 225 |
+
if (!top.version || !unq(top.version.v)) add('version-missing', top.version ? top.version.line : 1);
|
| 226 |
+
else {
|
| 227 |
+
var ver = unq(top.version.v);
|
| 228 |
+
if (/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/.test(ver)) { /* ok */ }
|
| 229 |
+
else if (/^v?\d+(\.\d+){0,2}$/.test(ver)) {
|
| 230 |
+
var p = ver.replace(/^v/, '').split('.'); while (p.length < 3) p.push('0');
|
| 231 |
+
add('version-coerced', top.version.line, '"' + ver + '" becomes ' + p.join('.') + ', so the package is named <name>-' + p.join('.') + '.tgz', 'version: ' + p.join('.'));
|
| 232 |
+
} else add('version-not-semver', top.version.line, 'found "' + ver + '"');
|
| 233 |
+
}
|
| 234 |
+
if (api === 'v1') ['dependencies', 'type'].forEach(function (k) {
|
| 235 |
+
if (top[k]) add('v2-field-on-v1', top[k].line, k + ' was added in apiVersion v2 (v1 charts list dependencies in requirements.yaml)');
|
| 236 |
+
});
|
| 237 |
+
if (top.type && unq(top.type.v) && !/^(application|library)$/.test(unq(top.type.v))) add('type-invalid', top.type.line, 'found "' + unq(top.type.v) + '"');
|
| 238 |
+
if (top.appVersion) {
|
| 239 |
+
var av = top.appVersion.v.replace(/\s+#.*$/, '').trim();
|
| 240 |
+
if (/^[0-9][0-9.eE+-]*$/.test(av) && /^(\d+\.\d+|\d+[eE]\d+|\d+)$/.test(av)) {
|
| 241 |
+
add('appversion-unquoted', top.appVersion.line, av + ' is read as the number ' + String(Number(av)), 'appVersion: "' + av + '"');
|
| 242 |
+
}
|
| 243 |
+
}
|
| 244 |
+
if (top.deprecated) { var dv = unq(top.deprecated.v); if (dv && !/^(true|false)$/.test(dv)) add('deprecated-not-bool', top.deprecated.line, 'found "' + dv + '"'); }
|
| 245 |
+
order.forEach(function (k) { if (KNOWN.indexOf(k) < 0) add('unknown-field', top[k].line, '"' + k + '"', 'annotations: ' + k + ': "' + unq(top[k].v) + '"'); });
|
| 246 |
+
if (top.dependencies) {
|
| 247 |
+
var s = top.dependencies.line, items = [], cur = null;
|
| 248 |
+
for (var i = s; i < lines.length; i++) {
|
| 249 |
+
var l = lines[i]; if (/^\S/.test(l)) break;
|
| 250 |
+
var dm = l.match(/^\s*-\s+(\w[\w-]*)\s*:\s*(.*)$/), km = l.match(/^\s+(\w[\w-]*)\s*:\s*(.*)$/);
|
| 251 |
+
if (dm) { cur = { line: i + 1, f: {} }; items.push(cur); cur.f[dm[1]] = unq(dm[2]); }
|
| 252 |
+
else if (km && cur) cur.f[km[1]] = unq(km[2]);
|
| 253 |
+
}
|
| 254 |
+
items.forEach(function (d) {
|
| 255 |
+
var miss = ['name', 'version'].filter(function (k) { return !d.f[k]; });
|
| 256 |
+
if (miss.length) add('dep-incomplete', d.line, 'missing ' + miss.join(' and ') + (d.f.name ? ' on "' + d.f.name + '"' : ''));
|
| 257 |
+
});
|
| 258 |
+
}
|
| 259 |
+
if (top.kubeVersion && unq(top.kubeVersion.v)) {
|
| 260 |
+
var kr = unq(top.kubeVersion.v), live = [], ok = [];
|
| 261 |
+
Object.keys(KUBE_EOL).forEach(function (m) { if (KUBE_EOL[m] > today) live.push(+m); });
|
| 262 |
+
live.forEach(function (m) { if (satisfies(kr, [1, m, 0]) || satisfies(kr, [1, m, 20])) ok.push(m); });
|
| 263 |
+
if (!ok.length) add('kube-no-supported', top.kubeVersion.line, '"' + kr + '" matches none of ' + live.map(function (m) { return '1.' + m; }).join(', ') + ' (supported on ' + today + ')');
|
| 264 |
+
else {
|
| 265 |
+
var last = ok.map(function (m) { return KUBE_EOL[m]; }).sort().pop();
|
| 266 |
+
if (days(today, last) <= 90) add('kube-eol-soon', top.kubeVersion.line, '"' + kr + '" installs only on ' + ok.map(function (m) { return '1.' + m; }).join(', ') + ', end of life ' + last + ' (' + days(today, last) + ' days after ' + today + ')');
|
| 267 |
+
}
|
| 268 |
+
}
|
| 269 |
+
}
|
| 270 |
+
// Helm 3 pins in CI, Dockerfiles, Makefiles (any file)
|
| 271 |
+
var left = days(today, HELM3_SECURITY_END);
|
| 272 |
+
var when = left >= 0 ? 'Helm 3 security fixes end ' + HELM3_SECURITY_END + ', ' + left + ' days after ' + today : 'Helm 3 security fixes ended ' + HELM3_SECURITY_END;
|
| 273 |
+
lines.forEach(function (l, i) {
|
| 274 |
+
var hit = null;
|
| 275 |
+
if (/(alpine\/helm|dtzar\/helm-kubectl):v?3\.\d/.test(l)) hit = l.match(/(alpine\/helm|dtzar\/helm-kubectl):v?3[\d.]*/)[0];
|
| 276 |
+
else if (/HELM_VERSION\s*[:=]\s*["']?v?3\.\d/.test(l)) hit = l.trim();
|
| 277 |
+
else if (/get-helm-3\b/.test(l)) hit = 'get-helm-3 installer';
|
| 278 |
+
else if (/^\s*(helm-)?version\s*:\s*["']?v3\.\d/.test(l)) {
|
| 279 |
+
for (var j = i - 1; j >= Math.max(0, i - 6); j--) if (/setup-helm@/.test(lines[j])) { hit = 'azure/setup-helm ' + unq(l.split(':').slice(1).join(':')); break; }
|
| 280 |
+
}
|
| 281 |
+
if (hit) add('helm3-pin', i + 1, hit + ' - ' + when);
|
| 282 |
+
});
|
| 283 |
+
out.sort(function (a, b) { return a.line - b.line; });
|
| 284 |
+
return { findings: out };
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
var api = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length, satisfies: satisfies };
|
| 288 |
+
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
| 289 |
+
if (typeof window !== 'undefined') window.CHARTGATE = api;
|
| 290 |
+
})();
|
| 291 |
+
</script>
|
| 292 |
+
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
|
| 293 |
+
'use strict';
|
| 294 |
+
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }
|
| 295 |
+
function summaryLine(res) {
|
| 296 |
+
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
|
| 297 |
+
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
|
| 298 |
+
}
|
| 299 |
+
function toText(res, label) {
|
| 300 |
+
const f = (res && res.findings) || [];
|
| 301 |
+
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
|
| 302 |
+
f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
|
| 303 |
+
return lines.join('\n');
|
| 304 |
+
}
|
| 305 |
+
function toHtml(res) {
|
| 306 |
+
const f = (res && res.findings) || [];
|
| 307 |
+
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
|
| 308 |
+
const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
|
| 309 |
+
return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
|
| 310 |
+
}
|
| 311 |
+
var CHARTGATE_REPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
|
| 312 |
+
if (typeof module !== 'undefined' && module.exports) module.exports = CHARTGATE_REPORT;
|
| 313 |
+
else window.CHARTGATE_REPORT = CHARTGATE_REPORT;
|
| 314 |
+
</script>
|
| 315 |
+
<script>
|
| 316 |
+
(function(){
|
| 317 |
+
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
|
| 318 |
+
today.value=new Date().toISOString().slice(0,10);
|
| 319 |
+
function run(){ try { var res=window.CHARTGATE.engine.check(src.value,{today:today.value}); out.innerHTML=window.CHARTGATE_REPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
|
| 320 |
+
go.onclick=run; if (src.value.trim()) run();
|
| 321 |
+
})();
|
| 322 |
+
</script>
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
<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://open-vsx.org/extension/readystack/chart-yaml-release-gate" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'chart-yaml-release-gate',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" 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><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/team" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
|
| 326 |
+
<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 helm chart lint Chart.yaml - Helm 4 Release Gate 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:"chart-yaml-release-gate",lang:"en",source:"rule_alert"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).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><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);document.addEventListener("click",function(ev){var b=ev.target&&ev.target.closest?ev.target.closest("button,input[type=submit]"):null;if(b&&!b.closest("[data-yj],[data-yj-cta],[data-yj-install],[data-yj-alert],.yj-find,.yj-related,#yj-ask,.yjp"))mv(ev);},true);})();</script></section>
|
| 327 |
+
|
| 328 |
+
<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 full version <span class="yj-price">$29</span></h2><p class="yj-cta-paid" style="margin:.25rem 0 .6rem;color:#1f2a37">Team key: a dated Helm 4 readiness report (Markdown + JSON) covering every chart in the repo, plus a CI gate that fails the build on any finding.</p><p class="yj-cta-pay" style="margin:.25rem 0 1rem;color:#5b6b7c;font-size:.94rem">One payment, one licence key for this tool. The key is shown right after payment.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_kucFyBvi1rLLBezWKPG8aE3rMnxS18iNfQJOg0iedeD" 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>
|
| 329 |
+
<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 helm chart lint Chart.yaml - Helm 4 Release Gate actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads Chart.yaml and CI YAML files and flags lines Helm will reject or misread, each with its replacement line. On the bundled sample chart it reports 6 findings from 16 rules: apiVersion v1, version v2.4 coerced to 2.4.0, unquoted appVersion 1.10 read as 1.1, kubeVersion capped below 1.35, an owner field outside the spec, and dependencies on a v1 chart.</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 the Chart.yaml release gate for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Platform, DevOps and SRE engineers who publish Helm charts, run an internal chart repository, or call helm package in CI. It is aimed at teams moving pipelines from Helm 3 to Helm 4, because Helm 3 bug fixes ended on 2026-07-08 and Helm 3 security fixes end on 2026-11-11, according to the Helm project.</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 not just run helm lint on the chart?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">helm lint validates chart structure, but it carries no Kubernetes end-of-life calendar and no Helm 3 cut-off date, and it never reads your CI workflow files. This checker flags a kubeVersion range that only matches Kubernetes 1.34, which reaches end of life on 2026-10-27, and a setup-helm step still pinned to v3.x before 2026-11-11.</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 the team key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free, with no key: all 16 rules on every Chart.yaml and CI YAML file, in VS Code and on the web page, with the replacement line for each finding. The team key, $29 once, adds a dated Helm 4 readiness report in Markdown and JSON covering every chart in the repository, plus a CI gate that fails the build on findings.</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 does the alternative cost?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">The alternative is an engineer reading the Helm chart documentation, the Helm 4 release notes and the Kubernetes release calendar, then walking each Chart.yaml and pipeline file by hand. The free checker does the reading in one pass and prints the replacement line for each finding. The team report is $29 once, one licence key per person or team seat.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does helm chart lint Chart.yaml - Helm 4 Release Gate actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads Chart.yaml and CI YAML files and flags lines Helm will reject or misread, each with its replacement line. On the bundled sample chart it reports 6 findings from 16 rules: apiVersion v1, version v2.4 coerced to 2.4.0, unquoted appVersion 1.10 read as 1.1, kubeVersion capped below 1.35, an owner field outside the spec, and dependencies on a v1 chart."}}, {"@type": "Question", "name": "Who is the Chart.yaml release gate for?", "acceptedAnswer": {"@type": "Answer", "text": "Platform, DevOps and SRE engineers who publish Helm charts, run an internal chart repository, or call helm package in CI. It is aimed at teams moving pipelines from Helm 3 to Helm 4, because Helm 3 bug fixes ended on 2026-07-08 and Helm 3 security fixes end on 2026-11-11, according to the Helm project."}}, {"@type": "Question", "name": "Why not just run helm lint on the chart?", "acceptedAnswer": {"@type": "Answer", "text": "helm lint validates chart structure, but it carries no Kubernetes end-of-life calendar and no Helm 3 cut-off date, and it never reads your CI workflow files. This checker flags a kubeVersion range that only matches Kubernetes 1.34, which reaches end of life on 2026-10-27, and a setup-helm step still pinned to v3.x before 2026-11-11."}}, {"@type": "Question", "name": "What is free and what needs the team key?", "acceptedAnswer": {"@type": "Answer", "text": "Free, with no key: all 16 rules on every Chart.yaml and CI YAML file, in VS Code and on the web page, with the replacement line for each finding. The team key, $29 once, adds a dated Helm 4 readiness report in Markdown and JSON covering every chart in the repository, plus a CI gate that fails the build on findings."}}, {"@type": "Question", "name": "What does the alternative cost?", "acceptedAnswer": {"@type": "Answer", "text": "The alternative is an engineer reading the Helm chart documentation, the Helm 4 release notes and the Kubernetes release calendar, then walking each Chart.yaml and pipeline file by hand. The free checker does the reading in one pass and prints the replacement line for each finding. The team report is $29 once, one licence key per person or team seat."}}]}</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:"chart-yaml-release-gate",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.</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/package-json-release-gate"><span class="yj-rel-t">npm publish package.json gate: engines & SPDX</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/gomod-release-gate"><span class="yj-rel-t">go.mod Release Gate: /vN suffix and go line check</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/bitnami-image-catalog-gate"><span class="yj-rel-t">Bitnami Image Gate: Compose, Helm, Dockerfile</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/cargo-publish-gate"><span class="yj-rel-t">Cargo.toml Publish Gate - crates.io</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/firmware-release-gate"><span class="yj-rel-t">Firmware Release Gate for sdkconfig and prj.conf</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/maven-central-publish-gate"><span class="yj-rel-t">Maven Central Publish Gate</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>
|
| 330 |
+
<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||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
|
| 331 |
+
|
| 332 |
+
<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</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 {"&":"&","<":"<",">":">",'"':"""}[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></body>
|
| 333 |
</html>
|