feat(apisix): add Cloudron package

- Implements Apache APISIX packaging for Cloudron platform.
- Includes Dockerfile, CloudronManifest.json, and start.sh.
- Configured to use Cloudron's etcd addon.

🤖 Generated with Gemini CLI
Co-Authored-By: Gemini <noreply@google.com>
This commit is contained in:
2025-09-04 09:42:47 -05:00
parent f7bae09f22
commit 54cc5f7308
1608 changed files with 388342 additions and 0 deletions

View File

@@ -0,0 +1,238 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { execSync } from 'child_process';
import { readFileSync } from 'fs';
import { join } from 'path';
// Types
interface Version {
tag: string;
ref: string;
}
interface PR {
number: number;
title: string;
commit: string;
}
// Configuration
const IGNORE_TYPES = [
'docs',
'chore',
'test',
'ci'
];
const IGNORE_PRS = [
// 3.9.0
10655, 10857, 10858, 10887, 10959, 11029, 11041, 11053, 11055, 11061, 10976, 10984, 11025,
// 3.10.0
11105, 11128, 11169, 11171, 11280, 11333, 11081, 11202, 11469,
// 3.11.0
11463, 11570,
// 3.12.0
11769, 11816, 11881, 11905, 11924, 11926, 11973, 11991, 11992, 11829,
// 3.13.0
9945, 11420, 11765, 12036, 12048, 12057, 12076, 12122, 12123, 12168, 12199, 12218, 12225, 12272, 12277, 12300, 12306, 12329, 12353, 12364, 12375, 12358
];
function getGitRef(version: string): string {
try {
execSync(`git rev-parse ${version}`, { stdio: 'ignore' });
return version;
} catch {
return 'HEAD';
}
}
function extractVersionsFromChangelog(): Version[] {
const changelogPath = join(process.cwd(), '..', 'CHANGELOG.md');
const content = readFileSync(changelogPath, 'utf-8');
const versionRegex = /^## ([0-9]+\.[0-9]+\.[0-9]+)/gm;
const versions: Version[] = [];
let match;
while ((match = versionRegex.exec(content)) !== null) {
const tag = match[1];
versions.push({
tag,
ref: getGitRef(tag)
});
}
return versions;
}
function extractPRsFromChangelog(startTag: string, endTag: string): number[] {
const changelogPath = join(process.cwd(), '..', 'CHANGELOG.md');
const content = readFileSync(changelogPath, 'utf-8');
const lines = content.split('\n');
let inRange = false;
const prs: number[] = [];
for (const line of lines) {
if (line.startsWith(`## ${startTag}`)) {
inRange = true;
continue;
}
if (inRange && line.startsWith(`## ${endTag}`)) {
break;
}
if (inRange) {
const match = line.match(/#(\d+)/);
if (match) {
prs.push(parseInt(match[1], 10));
}
}
}
return prs.sort((a, b) => a - b);
}
function shouldIgnoreCommitMessage(message: string): boolean {
// Extract the commit message part (remove the commit hash)
const messagePart = message.split(' ').slice(1).join(' ');
// Check if the message starts with any of the ignored types
for (const type of IGNORE_TYPES) {
// Check simple format: "type: message"
if (messagePart.startsWith(`${type}:`)) {
return true;
}
// Check format with scope: "type(scope): message"
if (messagePart.startsWith(`${type}(`)) {
const closingBracketIndex = messagePart.indexOf('):');
if (closingBracketIndex !== -1) {
return true;
}
}
}
return false;
}
function extractPRsFromGitLog(oldRef: string, newRef: string): PR[] {
const log = execSync(`git log ${oldRef}..${newRef} --oneline`, { encoding: 'utf-8' });
const prs: PR[] = [];
for (const line of log.split('\n')) {
if (!line.trim()) continue;
// Check if this commit should be ignored
if (shouldIgnoreCommitMessage(line)) continue;
// Find PR number
const prMatch = line.match(/#(\d+)/);
if (prMatch) {
const prNumber = parseInt(prMatch[1], 10);
if (!IGNORE_PRS.includes(prNumber)) {
prs.push({
number: prNumber,
title: line,
commit: line.split(' ')[0]
});
}
}
}
return prs.sort((a, b) => a.number - b.number);
}
function findMissingPRs(changelogPRs: number[], gitPRs: PR[]): PR[] {
const changelogPRSet = new Set(changelogPRs);
return gitPRs.filter(pr => !changelogPRSet.has(pr.number));
}
function versionGreaterThan(v1: string, v2: string): boolean {
// Remove 'v' prefix if present
const cleanV1 = v1.replace(/^v/, '');
const cleanV2 = v2.replace(/^v/, '');
// Split version strings into arrays of numbers
const v1Parts = cleanV1.split('.').map(Number);
const v2Parts = cleanV2.split('.').map(Number);
// Compare each part
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
const v1Part = v1Parts[i] || 0;
const v2Part = v2Parts[i] || 0;
if (v1Part > v2Part) return true;
if (v1Part < v2Part) return false;
}
// If all parts are equal, return false
return false;
}
// Main function
async function main() {
try {
const versions = extractVersionsFromChangelog();
let hasErrors = false;
for (let i = 0; i < versions.length - 1; i++) {
const newVersion = versions[i];
const oldVersion = versions[i + 1];
// Skip if new version is less than or equal to 3.8.0
if (!versionGreaterThan(newVersion.tag, '3.8.0')) {
continue;
}
console.log(`\n=== Checking changes between ${newVersion.tag} (${newVersion.ref}) and ${oldVersion.tag} (${oldVersion.ref}) ===`);
const changelogPRs = extractPRsFromChangelog(newVersion.tag, oldVersion.tag);
const gitPRs = extractPRsFromGitLog(oldVersion.ref, newVersion.ref);
const missingPRs = findMissingPRs(changelogPRs, gitPRs);
console.log(`\n=== PR Comparison Results for ${newVersion.tag} ===`);
if (missingPRs.length === 0) {
console.log(`\n✅ All PRs are included in CHANGELOG.md for version ${newVersion.tag}`);
} else {
console.log(`\n❌ Missing PRs in CHANGELOG.md for version ${newVersion.tag} (sorted):`);
missingPRs.forEach(pr => {
console.log(` #${pr.number}`);
});
console.log(`\nDetailed information about missing PRs for version ${newVersion.tag}:`);
missingPRs.forEach(pr => {
console.log(`\nPR #${pr.number}:`);
console.log(` - ${pr.title}`);
console.log(` - PR URL: https://github.com/apache/apisix/pull/${pr.number}`);
});
console.log('Note: If you confirm that a PR should not appear in the changelog, please add its number to the IGNORE_PRS array in this script.');
hasErrors = true;
}
}
if (hasErrors) {
process.exit(1);
}
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
(async () => {
await main();
})();