getreadystack commited on
Commit
def6e12
·
verified ·
1 Parent(s): fdfc09c

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +219 -17
index.html CHANGED
@@ -1,19 +1,221 @@
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>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>Forgejo Gitea Migration — check your compose file free</title>
7
+ <meta name="description" content="This free tool flags Gitea and Forgejo tags and runner settings in Docker Compose files that need migration.">
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 defer data-auto-init src="https://cdn.jsdelivr.net/npm/@polar-sh/checkout@latest/dist/embed.global.js"></script>
19
+ <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>
20
+ <!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/forgejo-migration-check"><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>
21
+ </head>
22
+ <body>
23
+ <div class="wrap">
24
+ <h1>Forgejo Gitea Migration — check your compose file free</h1>
25
+ <p class="lede">Forgejo migration lint for docker-compose files: flags Gitea tags past 1.22 (no transparent upgrade), a first hop that skips Forgejo v10.0, end-of-life Forgejo tags and Gitea act_runner. Runs entirely in your browser — nothing is uploaded.</p>
26
+ <textarea id="src" spellcheck="false"># acme-git staging: Gitea -&gt; Forgejo switch rehearsal
27
+ services:
28
+ git:
29
+ image: codeberg.org/forgejo/forgejo:11
30
+ restart: always
31
+ volumes:
32
+ - ./gitea:/data
33
+ ports:
34
+ - "3000:3000"
35
+ - "2222:22"
36
+ git-next:
37
+ image: codeberg.org/forgejo/forgejo:16
38
+ volumes:
39
+ - ./forgejo-canary:/data
40
+ legacy:
41
+ image: gitea/gitea:1.23.8
42
+ volumes:
43
+ - ./gitea-legacy:/data
44
+ mirror:
45
+ image: gitea/gitea:latest-rootless
46
+ runner:
47
+ image: gitea/act_runner:0.2.11
48
+ environment:
49
+ - GITEA_INSTANCE_URL=http://git:3000</textarea>
50
+ <div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
51
+ <div id="out" aria-live="polite"></div>
52
+ <div id="paid"><strong>Free here:</strong> every rule on the compose file you paste, every finding and its fix. <strong>Full version:</strong> export the dated two-hop migration report (Markdown + JSON) for the change ticket, one file per compose file in the workspace. $29 once · one licence key per person or team seat. Gitea Enterprise lists $19 per user per month ($9.50 on a 1-year commitment). <a href="https://getreadystack.com/api/buy/cl/polar_cl_1qyxPLso98eYI1iIvuEtSmbl4VeFu6MnCMqQA2onMBc" data-polar-checkout data-polar-checkout-theme="light">Get the full version — $29</a></div>
53
+ <p class="note">Same engine as the VS Code extension, byte for byte.</p>
54
+ </div>
55
+ <script>var FJ_RULES = [
56
+ {"id": "gitea-past-1-22", "sev": "error", "title": "Gitea tag past 1.22",
57
+ "msg": "Gitea {tag} is past 1.22. Forgejo supports a transparent upgrade only from Gitea up to v1.22 included; from 1.23 on there is no supported path, only best effort with manual database edits.",
58
+ "fix": "Keep production on gitea/gitea:1.22.x and switch from a 1.22 backup, or migrate repo by repo through the Forgejo migration UI/API.",
59
+ "source": "forgejo.org/2024-12-gitea-compatibility (18 Dec 2024)", "last_transparent": "1.22"},
60
+ {"id": "gitea-floating-tag", "sev": "error", "title": "Gitea tag floats past 1.22",
61
+ "msg": "gitea/gitea:{tag} is not pinned to 1.22.x. The next pull resolves to a release past 1.22 and closes the transparent upgrade path to Forgejo.",
62
+ "fix": "Pin gitea/gitea:1.22.x (or 1.22.x-rootless) until the switch is done.",
63
+ "source": "forgejo.org/2024-12-gitea-compatibility (18 Dec 2024)"},
64
+ {"id": "forgejo-first-hop", "sev": "error", "title": "First hop from Gitea is not Forgejo v10.0",
65
+ "msg": "Forgejo {tag} on Gitea data. The documented path is two steps: Gitea up to v1.22.x -\u003e Forgejo v10.0.x, then v10.0.x -\u003e any later Forgejo.",
66
+ "fix": "Start the Gitea data on forgejo:10.0.x once, let it migrate, then change the tag to the current LTS.",
67
+ "source": "forgejo.org/docs/latest/admin/upgrade"},
68
+ {"id": "forgejo-eol", "sev": "error", "title": "Forgejo major past end of life",
69
+ "msg": "Forgejo {major}.0 reached end of life on {eol} and gets no security fixes after that date.",
70
+ "fix": "Move to Forgejo 15.0 LTS (supported until 2027-07-15) or the current stable major.",
71
+ "source": "forgejo.org/docs/latest/admin/release-schedule",
72
+ "eol": {"7": "2025-07-17", "8": "2024-10-16", "9": "2025-01-16", "10": "2025-04-16", "11": "2026-07-16", "12": "2025-10-16", "13": "2026-01-29", "14": "2026-04-30", "15": "2027-07-15", "16": "2026-10-29", "17": "2027-01-28", "18": "2027-04-29", "19": "2028-07-13", "20": "2027-10-28"},
73
+ "lts": ["7", "11", "15", "19"]},
74
+ {"id": "forgejo-eol-soon", "sev": "warning", "title": "Forgejo major ends within 45 days",
75
+ "msg": "Forgejo {major}.0 reaches end of life on {eol}, {days} days after {today}.",
76
+ "fix": "Plan the move to Forgejo 15.0 LTS (supported until 2027-07-15) or the next stable major before {eol}.",
77
+ "source": "forgejo.org/docs/latest/admin/release-schedule", "window_days": 45},
78
+ {"id": "forgejo-floating-tag", "sev": "warning", "title": "Forgejo tag not pinned to a major",
79
+ "msg": "forgejo:{tag} is not pinned to a major version. A pull can jump several majors at once, including past the v10.0 hop.",
80
+ "fix": "Pin the major, e.g. codeberg.org/forgejo/forgejo:15.",
81
+ "source": "forgejo.org/docs/latest/admin/upgrade"},
82
+ {"id": "gitea-act-runner", "sev": "warning", "title": "Gitea act_runner next to Forgejo",
83
+ "msg": "gitea/act_runner:{tag} is Gitea's runner. Forgejo Actions is documented and supported with the Forgejo runner.",
84
+ "fix": "Use code.forgejo.org/forgejo/runner and re-register it against the Forgejo instance.",
85
+ "source": "forgejo.org/docs/latest/admin/actions"},
86
+ {"id": "forgejo-gpl-build", "sev": "info", "title": "Custom Forgejo build is GPL v3+",
87
+ "msg": "This file builds its own image next to Forgejo. Forgejo is GPL v3+ from v9.0 (MIT up to and including v8.0); a modified build you hand to others carries GPL source obligations.",
88
+ "fix": "Keep the patch source published with the image, or use the stock image.",
89
+ "source": "Forgejo v9.0 release notes (16 Oct 2024)"}
90
+ ]
91
+ ;</script>
92
+ <script>// Forgejo migration check: compose YAML -> Gitea-to-Forgejo blockers. Same file runs in VS Code and the web page.
93
+ (function () {
94
+ const RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.FJ_RULES;
95
+ const R = {};
96
+ RULES.forEach(function (r) { R[r.id] = r; });
97
+
98
+ function fill(s, v) { return String(s).replace(/\{(\w+)\}/g, function (m, k) { return v[k] !== undefined ? v[k] : m; }); }
99
+
100
+ function parseToday(t) {
101
+ const s = String(t || '').slice(0, 10);
102
+ const d = new Date(s + 'T00:00:00Z');
103
+ return isNaN(d) ? new Date().toISOString().slice(0, 10) : s;
104
+ }
105
+ function daysBetween(a, b) { return Math.round((Date.parse(b + 'T00:00:00Z') - Date.parse(a + 'T00:00:00Z')) / 86400000); }
106
+
107
+ // image: [registry/]path[:tag][@digest]
108
+ function parseImage(line) {
109
+ const m = line.replace(/\s+#.*$/, '').match(/^\s*-?\s*image\s*:\s*["']?([^\s"']+)["']?/i);
110
+ if (!m) return null;
111
+ let ref = m[1].split('@')[0];
112
+ const slash = ref.lastIndexOf('/');
113
+ const colon = ref.lastIndexOf(':');
114
+ let path = ref, tag = '';
115
+ if (colon > slash) { path = ref.slice(0, colon); tag = ref.slice(colon + 1); }
116
+ path = path.toLowerCase();
117
+ let kind = null;
118
+ if (/(^|\/)gitea\/gitea$/.test(path)) kind = 'gitea';
119
+ else if (/(^|\/)gitea\/act_runner$/.test(path)) kind = 'act_runner';
120
+ else if (/(^|\/)forgejo\/forgejo$/.test(path)) kind = 'forgejo';
121
+ return kind ? { kind: kind, path: path, tag: tag } : null;
122
+ }
123
+
124
+ function check(text, opts) {
125
+ opts = opts || {};
126
+ const today = parseToday(opts.today);
127
+ const lines = String(text || '').split(/\r?\n/);
128
+ const findings = [];
129
+ function add(id, line, v) {
130
+ const r = R[id];
131
+ findings.push({ check: id, sev: r.sev, msg: fill(r.msg, v), fix: fill(r.fix, v), line: line, title: r.title });
132
+ }
133
+ const images = [];
134
+ let giteaContext = false, hasBuild = false, hasForgejo = false;
135
+ lines.forEach(function (ln, i) {
136
+ if (/^\s*#/.test(ln)) return;
137
+ const img = parseImage(ln);
138
+ if (img) { img.line = i + 1; images.push(img); if (img.kind === 'gitea') giteaContext = true; if (img.kind === 'forgejo') hasForgejo = true; }
139
+ // a volume whose host side is Gitea data, e.g. ./gitea:/data or gitea-data:/data
140
+ if (/^\s*-\s*["']?[^\s:"']*gitea[^\s:"']*:\/data/i.test(ln)) giteaContext = true;
141
+ if (/^\s*build\s*:/i.test(ln)) hasBuild = true;
142
+ });
143
+ const eol = R['forgejo-eol'].eol;
144
+ const soon = R['forgejo-eol-soon'].window_days;
145
+ let firstHopDone = false;
146
+ images.forEach(function (img) {
147
+ const bare = img.tag.replace(/-rootless$/i, '');
148
+ if (img.kind === 'gitea') {
149
+ const v = bare.match(/^(\d+)\.(\d+)/);
150
+ if (!v) add('gitea-floating-tag', img.line, { tag: img.tag || '(no tag)' });
151
+ else if (+v[1] > 1 || (+v[1] === 1 && +v[2] > 22)) add('gitea-past-1-22', img.line, { tag: img.tag });
152
+ } else if (img.kind === 'act_runner') {
153
+ add('gitea-act-runner', img.line, { tag: img.tag || '(no tag)' });
154
+ } else if (img.kind === 'forgejo') {
155
+ const v = bare.match(/^(\d+)(?:\.|$)/);
156
+ if (!v) { add('forgejo-floating-tag', img.line, { tag: img.tag || '(no tag)' }); return; }
157
+ const major = v[1];
158
+ const hop = giteaContext && !firstHopDone;
159
+ if (hop) { firstHopDone = true; if (major !== '10') add('forgejo-first-hop', img.line, { tag: img.tag }); else return; }
160
+ const end = eol[major];
161
+ if (!end) return;
162
+ const left = daysBetween(today, end);
163
+ if (left < 0) add('forgejo-eol', img.line, { major: major, eol: end });
164
+ else if (left <= soon) add('forgejo-eol-soon', img.line, { major: major, eol: end, days: left, today: today });
165
+ }
166
+ });
167
+ if (hasBuild && hasForgejo) {
168
+ const b = lines.findIndex(function (ln) { return /^\s*build\s*:/i.test(ln); });
169
+ add('forgejo-gpl-build', b + 1, {});
170
+ }
171
+ findings.sort(function (a, b) { return a.line - b.line; });
172
+ return { findings: findings, today: today, images: images.length };
173
+ }
174
+
175
+ const api = { engine: { check: check, parseImage: parseImage }, RULES: RULES, RULE_COUNT: RULES.length };
176
+ if (typeof module !== 'undefined' && module.exports) module.exports = api;
177
+ if (typeof window !== 'undefined') window.FJENGINE = api;
178
+ })();
179
+ </script>
180
+ <script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
181
+ 'use strict';
182
+ function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
183
+ function summaryLine(res) {
184
+ const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
185
+ return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
186
+ }
187
+ function toText(res, label) {
188
+ const f = (res && res.findings) || [];
189
+ const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
190
+ 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 || '')); });
191
+ return lines.join('\n');
192
+ }
193
+ function toHtml(res) {
194
+ const f = (res && res.findings) || [];
195
+ if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
196
+ 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('');
197
+ 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>';
198
+ }
199
+ var FJREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
200
+ if (typeof module !== 'undefined' && module.exports) module.exports = FJREPORT;
201
+ else window.FJREPORT = FJREPORT;
202
+ </script>
203
+ <script>
204
+ (function(){
205
+ var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
206
+ today.value=new Date().toISOString().slice(0,10);
207
+ function run(){ try { var res=window.FJENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.FJREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
208
+ go.onclick=run; if (src.value.trim()) run();
209
+ })();
210
+ </script>
211
+
212
+
213
+ <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.forgejo-migration-check" rel="noopener" data-yj-install-door="mp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'forgejo-migration-check',src:'mp',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">VS Code Marketplace</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">ext install ReadyStack.forgejo-migration-check</pre><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>
214
+ <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 Forgejo Migration Check — Gitea 1.22 cutoff 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:"forgejo-migration-check",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>
215
+
216
+ <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">Export the dated two-hop migration report (Markdown + JSON) for the change ticket, one file per compose file in the workspace.</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><p class="yj-cta-anchor" style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">Gitea Enterprise lists $19 per user per month ($9.50 on a 1-year commitment) at about.gitea.com/pricing</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_1qyxPLso98eYI1iIvuEtSmbl4VeFu6MnCMqQA2onMBc" 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>
217
+ <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 Forgejo Migration Check do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads the image lines of a docker-compose or compose.yaml file and flags what breaks a Gitea to Forgejo switch: a Gitea tag past 1.22, a first hop that is not Forgejo v10.0.x, Forgejo majors past end of life on the Forgejo release schedule, unpinned tags, Gitea&#x27;s act_runner and custom GPL builds. Each finding has a line number and the fix.</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 Forgejo Migration Check for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Self-hosting admins, homelab owners and DevOps teams that run Gitea with Docker or Podman compose and plan the move to Forgejo, plus agencies that maintain several client Git servers. It suits anyone who must know, before pulling a new image, whether the Gitea data can go to Forgejo without manual database edits.</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 read the free Forgejo docs?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">The Forgejo upgrade guide and release schedule are free and correct, but they do not read your compose file. Docker will pull forgejo:11 onto a Gitea data volume without a warning, and a floating gitea:latest tag moves past 1.22 on the next pull. The check compares every image line with those published rules and dates.</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 in Forgejo Migration Check and what is paid?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free: the VS Code extension and the web page check any compose file with all eight rules and show every finding with its fix, no key needed. Paid, $29 once for one licence key per person or team seat: export a dated two-hop migration report in Markdown and JSON for the change ticket, one file per compose file in the workspace.</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 paid Gitea support cost instead of moving to Forgejo?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Gitea Enterprise, the vendor&#x27;s paid support plan, lists $19 per user per month, or $9.50 per user per month with a one-year commitment, on about.gitea.com/pricing. Staying on Gitea is a valid choice; this check is for teams that have decided to move to Forgejo and want the upgrade path verified line by line before the switch.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does Forgejo Migration Check do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads the image lines of a docker-compose or compose.yaml file and flags what breaks a Gitea to Forgejo switch: a Gitea tag past 1.22, a first hop that is not Forgejo v10.0.x, Forgejo majors past end of life on the Forgejo release schedule, unpinned tags, Gitea's act_runner and custom GPL builds. Each finding has a line number and the fix."}}, {"@type": "Question", "name": "Who is Forgejo Migration Check for?", "acceptedAnswer": {"@type": "Answer", "text": "Self-hosting admins, homelab owners and DevOps teams that run Gitea with Docker or Podman compose and plan the move to Forgejo, plus agencies that maintain several client Git servers. It suits anyone who must know, before pulling a new image, whether the Gitea data can go to Forgejo without manual database edits."}}, {"@type": "Question", "name": "Why not just read the free Forgejo docs?", "acceptedAnswer": {"@type": "Answer", "text": "The Forgejo upgrade guide and release schedule are free and correct, but they do not read your compose file. Docker will pull forgejo:11 onto a Gitea data volume without a warning, and a floating gitea:latest tag moves past 1.22 on the next pull. The check compares every image line with those published rules and dates."}}, {"@type": "Question", "name": "What is free in Forgejo Migration Check and what is paid?", "acceptedAnswer": {"@type": "Answer", "text": "Free: the VS Code extension and the web page check any compose file with all eight rules and show every finding with its fix, no key needed. Paid, $29 once for one licence key per person or team seat: export a dated two-hop migration report in Markdown and JSON for the change ticket, one file per compose file in the workspace."}}, {"@type": "Question", "name": "What does paid Gitea support cost instead of moving to Forgejo?", "acceptedAnswer": {"@type": "Answer", "text": "Gitea Enterprise, the vendor's paid support plan, lists $19 per user per month, or $9.50 per user per month with a one-year commitment, on about.gitea.com/pricing. Staying on Gitea is a valid choice; this check is for teams that have decided to move to Forgejo and want the upgrade path verified line by line before the switch."}}]}</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:"forgejo-migration-check",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/mcp-2026-migration-lint"><span class="yj-rel-t">MCP 2026 Migration Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/podman-migration-check"><span class="yj-rel-t">Podman Migration Check — Docker Desktop ties</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/mssql-container-licence-lint"><span class="yj-rel-t">SQL Server Docker Licence Lint (MSSQL_PID)</span><span class="yj-rel-p">$29</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/aks-eks-support-cliff-lint"><span class="yj-rel-t">AKS LTS &amp; EKS Extended Support Lint for Terraform</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/almalinux-migration-lint"><span class="yj-rel-t">AlmaLinux Migration Lint — CentOS 7/8</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>
218
+ <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>
219
+
220
+ <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 {"&":"&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></body>
221
  </html>