forked from Gitlink/gitlink-cli
272 lines
7.6 KiB
JavaScript
272 lines
7.6 KiB
JavaScript
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const dir = process.argv[2] || '_output';
|
||
const specPath = path.join(dir, 'project-spec.json');
|
||
|
||
if (!fs.existsSync(specPath)) {
|
||
console.error('[ERROR] 未找到 project-spec.json: ' + specPath);
|
||
process.exit(1);
|
||
}
|
||
|
||
const spec = JSON.parse(fs.readFileSync(specPath, 'utf8'));
|
||
const NAME = spec.name || 'my-project';
|
||
const DESC = spec.description || '';
|
||
const LANG = (spec.language || 'go').toLowerCase();
|
||
const LIC = (spec.license || 'MIT').toUpperCase();
|
||
const YEAR = new Date().getFullYear();
|
||
|
||
const skeletonDir = path.join(dir, 'skeleton');
|
||
fs.mkdirSync(path.join(skeletonDir, '.devops'), { recursive: true });
|
||
|
||
// ==== README.md ====
|
||
const readme = `# ${NAME}
|
||
|
||
> ${DESC}
|
||
|
||
## 简介
|
||
|
||
${DESC}。本仓库由 \`gitlink-project-bootstrap\` 自动初始化,开箱即用。
|
||
|
||
## 安装
|
||
|
||
请根据你的主语言(${LANG})选择对应安装方式:
|
||
|
||
\`\`\`bash
|
||
# 示例:克隆仓库
|
||
git clone https://gitlink.org.cn/<owner>/${NAME}.git
|
||
cd ${NAME}
|
||
\`\`\`
|
||
|
||
## 用法
|
||
|
||
\`\`\`bash
|
||
# TODO: 在此补充构建 / 运行命令
|
||
\`\`\`
|
||
|
||
## 贡献指南
|
||
|
||
欢迎提交 Issue 与 Pull Request。提交流程请参考 [CONTRIBUTING.md](./CONTRIBUTING.md)(待补)。
|
||
|
||
## 许可证
|
||
|
||
本项目基于 ${LIC} 许可证开源,详见 [LICENSE](./LICENSE)。
|
||
|
||
---
|
||
*由 gitlink-project-bootstrap 自动生成于 ${YEAR}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')}*
|
||
`;
|
||
|
||
// ==== LICENSE ====
|
||
let licenseText = '';
|
||
if (LIC.startsWith('APACHE')) {
|
||
licenseText = `Apache License
|
||
Version 2.0, January 2004
|
||
http://www.apache.org/licenses/
|
||
|
||
Copyright ${YEAR} [project author]
|
||
|
||
Licensed 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.
|
||
`;
|
||
} else if (LIC.startsWith('GPL')) {
|
||
licenseText = `${LIC} License
|
||
|
||
Copyright (c) ${YEAR} [project author]
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
`;
|
||
} else {
|
||
// MIT (default)
|
||
licenseText = `MIT License
|
||
|
||
Copyright (c) ${YEAR} [project author]
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
of this software and associated documentation files (the "Software"), to deal
|
||
in the Software without restriction, including without limitation the rights
|
||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
copies of the Software, and to permit persons to whom the Software is
|
||
furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all
|
||
copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
SOFTWARE.
|
||
`;
|
||
}
|
||
|
||
// ==== .gitignore ====
|
||
let gitignore = '';
|
||
if (LANG === 'go') {
|
||
gitignore = `# Go
|
||
bin/
|
||
*.exe
|
||
*.exe~
|
||
*.dll
|
||
*.so
|
||
*.dylib
|
||
*.test
|
||
*.out
|
||
vendor/
|
||
go.sum
|
||
|
||
# IDE
|
||
.idea/
|
||
.vscode/
|
||
*.swp
|
||
`;
|
||
} else if (LANG === 'node') {
|
||
gitignore = `# Node
|
||
node_modules/
|
||
npm-debug.log*
|
||
yarn-debug.log*
|
||
yarn-error.log*
|
||
dist/
|
||
build/
|
||
.env
|
||
.nyc_output/
|
||
coverage/
|
||
|
||
# IDE
|
||
.idea/
|
||
.vscode/
|
||
*.swp
|
||
`;
|
||
} else if (LANG === 'python') {
|
||
gitignore = `# Python
|
||
__pycache__/
|
||
*.py[cod]
|
||
*$py.class
|
||
*.so
|
||
.Python
|
||
env/
|
||
venv/
|
||
.venv/
|
||
*.egg-info/
|
||
.pytest_cache/
|
||
dist/
|
||
build/
|
||
|
||
# IDE
|
||
.idea/
|
||
.vscode/
|
||
*.swp
|
||
`;
|
||
} else {
|
||
gitignore = `# 通用
|
||
*.log
|
||
*.tmp
|
||
.idea/
|
||
.vscode/
|
||
.DS_Store
|
||
`;
|
||
}
|
||
|
||
// ==== CI yaml (最小可用 GitLink 构建流水线) ====
|
||
const ciYaml = `version: 2
|
||
name: ${NAME} 构建流水线
|
||
description: "${NAME} 自动构建与测试"
|
||
trigger:
|
||
webhook: gitlink@1.0.0
|
||
event:
|
||
- ref: push
|
||
ruleset-operator: AND
|
||
global:
|
||
concurrent: 1
|
||
workflow:
|
||
- ref: start
|
||
name: 开始
|
||
task: start
|
||
- ref: end
|
||
name: 结束
|
||
task: end
|
||
needs:
|
||
- start
|
||
`;
|
||
|
||
// ==== 写盘 ====
|
||
const produced = [];
|
||
fs.writeFileSync(path.join(skeletonDir, 'README.md'), readme, 'utf8'); produced.push('README.md');
|
||
fs.writeFileSync(path.join(skeletonDir, 'LICENSE'), licenseText, 'utf8'); produced.push('LICENSE');
|
||
fs.writeFileSync(path.join(skeletonDir, '.gitignore'), gitignore, 'utf8'); produced.push('.gitignore');
|
||
fs.writeFileSync(path.join(skeletonDir, '.devops', '构建流水线.yml'), ciYaml, 'utf8'); produced.push('.devops/构建流水线.yml');
|
||
|
||
// ==== init-report.md ====
|
||
const completionScore = 9; // 骨架完整:仓库(spec)/README/LICENSE/.gitignore/CI 已就绪;Issue/里程碑由 Phase 3 补
|
||
const now = new Date();
|
||
const dateStr = now.toISOString().slice(0, 10);
|
||
const timeStr = now.toISOString().slice(0, 19).replace('T', ' ');
|
||
|
||
const report = `# 🚀 项目初始化报告
|
||
|
||
**项目:** ${spec.owner || '<owner>'}/${NAME}
|
||
**生成日期:** ${dateStr}
|
||
**主语言:** ${LANG}
|
||
**许可证:** ${LIC}
|
||
**综合评分:** ${completionScore}/10 🟢 良好
|
||
|
||
## 一、本次初始化产物
|
||
|
||
| 类别 | 产物 | 状态 |
|
||
|------|------|------|
|
||
| 仓库规格 | project-spec.json | ✅ 已生成 |
|
||
| 项目说明 | README.md | ✅ 已生成 |
|
||
| 许可证 | LICENSE (${LIC}) | ✅ 已生成(含 \`[year] [project author]\` 占位,请替换) |
|
||
| 忽略规则 | .gitignore (${LANG}) | ✅ 已生成 |
|
||
| CI 配置 | .devops/构建流水线.yml | ✅ 已生成 |
|
||
| 里程碑 | v0.1.0 | ⏳ Phase 3 创建 |
|
||
| 起始标签 | good-first-issue / enhancement / bug | ⏳ Phase 3 创建 |
|
||
| 初始 Issue | 完善 README / 配置 CI / 贡献指南 | ⏳ Phase 3 创建 |
|
||
|
||
## 二、待人工确认事项
|
||
|
||
1. **LICENSE 占位**:将 \`${licenseText.split('\n')[0].includes('Copyright') ? licenseText.split('\n')[0] : 'Copyright (c) ' + YEAR + ' [project author]'}\` 中的 \`[project author]\` 替换为真实版权人
|
||
2. **README 用法**:在"用法"小节补充实际构建/运行命令
|
||
3. **CI 触发**:根据团队约定调整 \`.devops/构建流水线.yml\` 的 trigger 与构建步骤
|
||
4. **仓库可见性**:当前为 ${spec.private ? '私有' : '公开'},确认无误
|
||
|
||
## 三、推送到仓库
|
||
|
||
\`\`\`bash
|
||
# 优先 file +batch(单次 commit)
|
||
gitlink-cli file +batch --files '<JSON>' --message "chore: 初始化项目骨架" --branch master
|
||
# 或逐个 file +create
|
||
\`\`\`
|
||
|
||
---
|
||
*数据采集时间:${timeStr}*
|
||
*AI 生成,建议人工复核*
|
||
`;
|
||
|
||
fs.writeFileSync(path.join(dir, 'init-report.md'), report, 'utf8');
|
||
|
||
console.log('[skeleton-gen] 已生成产物:');
|
||
produced.forEach(f => console.log(' - ' + f));
|
||
console.log('[skeleton-gen] init-report.md 已生成');
|