gitlink-cli/workflows/03-project-init.sh

525 lines
15 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────
# Scenario 3: One-Click Project Initialization
# Flow: Input description → Create repo → Generate files (README/LICENSE/
# CONTRIBUTING/CI) → Push to repo → Milestones → Issues →
# Branch protection → Initial Release
#
# Commands chained:
# 1. repo +create -- create repository
# 2. git clone -- clone the empty repo locally
# 3. file generation -- README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml
# 4. git add/commit/push -- push scaffold files to repo
# 5. milestone +create -- create project milestones
# 6. issue +create -- create initial issues
# 7. branch +protect -- protect default branch
# 8. release +create -- create initial release
# ─────────────────────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib/common.sh"
usage() {
echo "Usage: $0 --owner OWNER --name REPO_NAME --description DESC [--lang LANG] [--private] [--dry-run]"
echo ""
echo " --owner OWNER Repository owner (org or user)"
echo " --name REPO_NAME Repository name"
echo " --description DESC Repository description"
echo " --lang LANG Primary language: go|python|node|java (default: go)"
echo " --private Make repository private"
echo " --dry-run Preview actions without executing"
exit 1
}
PROJ_LANG="go"
DRY_RUN=false
OWNER=""
REPO_NAME=""
DESCRIPTION=""
PRIVATE="false"
while [[ $# -gt 0 ]]; do
case "$1" in
--owner) OWNER="$2"; shift 2 ;;
--name) REPO_NAME="$2"; shift 2 ;;
--description) DESCRIPTION="$2"; shift 2 ;;
--lang) PROJ_LANG="$2"; shift 2 ;;
--private) PRIVATE="true"; shift ;;
--dry-run) DRY_RUN="true"; shift ;;
--help|-h) usage ;;
*) log_err "Unknown arg: $1"; usage ;;
esac
done
if [[ -z "$OWNER" || -z "$REPO_NAME" || -z "$DESCRIPTION" ]]; then
log_err "Missing required parameters: --owner, --name, --description"
usage
fi
check_auth
# ─────────────────────────────────────────────────────────────────────
log_title "Project Initialization: $OWNER/$REPO_NAME"
# ─────────────────────────────────────────────────────────────────────
echo " Owner: $OWNER"
echo " Name: $REPO_NAME"
echo " Description: $DESCRIPTION"
echo " Language: $PROJ_LANG"
echo " Private: $PRIVATE"
divider
# ── Step 1: Create Repository ────────────────────────────────────────
log_step "Step 1/8: Creating repository..."
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would create repository: $OWNER/$REPO_NAME"
else
REPO_RESULT=$(gl_check repo +create --owner "$OWNER" --name "$REPO_NAME" --description "$DESCRIPTION" --private "$PRIVATE")
REPO_ID=$(echo "$REPO_RESULT" | jq -r '.data.id // .data.project_id // empty')
log_ok "Repository created: $OWNER/$REPO_NAME (id: $REPO_ID)"
fi
# ── Step 2: Clone empty repo ─────────────────────────────────────────
log_step "Step 2/8: Cloning repository..."
# Build auth URL using token so clone/push don't prompt for password
if [[ -n "${GITLINK_TOKEN:-}" ]]; then
CLONE_URL="https://oauth2:${GITLINK_TOKEN}@gitlink.org.cn/$OWNER/$REPO_NAME.git"
else
CLONE_URL="https://gitlink.org.cn/$OWNER/$REPO_NAME.git"
fi
REPO_URL="https://gitlink.org.cn/$OWNER/$REPO_NAME.git"
WORK_DIR=$(mktemp -d /tmp/gitlink-init-XXXXXX)
cleanup() { rm -rf "$WORK_DIR"; }
trap cleanup EXIT
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would clone: $REPO_URL$WORK_DIR"
else
git clone "$CLONE_URL" "$WORK_DIR" 2>&1 | tail -1 || true
log_ok "Cloned to $WORK_DIR"
fi
# ── Step 3: Generate project files ───────────────────────────────────
log_step "Step 3/8: Generating project scaffold files..."
# --- README.md ---
gen_readme() {
local lang_section
case "$PROJ_LANG" in
go)
lang_section="### 环境要求
- Go 1.21+
- Git
### 安装
\`\`\`bash
git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git
cd $REPO_NAME
go mod download
go build ./...
\`\`\`
### 使用
\`\`\`bash
go run main.go
\`\`\`
### 测试
\`\`\`bash
go test ./...
\`\`\`"
;;
python)
lang_section="### 环境要求
- Python 3.9+
- pip
### 安装
\`\`\`bash
git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git
cd $REPO_NAME
pip install -r requirements.txt
\`\`\`
### 使用
\`\`\`bash
python main.py
\`\`\`
### 测试
\`\`\`bash
pytest
\`\`\`"
;;
node)
lang_section="### 环境要求
- Node.js 18+
- npm or yarn
### 安装
\`\`\`bash
git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git
cd $REPO_NAME
npm install
\`\`\`
### 使用
\`\`\`bash
npm start
\`\`\`
### 测试
\`\`\`bash
npm test
\`\`\`"
;;
java)
lang_section="### 环境要求
- JDK 17+
- Maven 3.8+
### 安装
\`\`\`bash
git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git
cd $REPO_NAME
mvn clean install
\`\`\`
### 使用
\`\`\`bash
mvn exec:java
\`\`\`
### 测试
\`\`\`bash
mvn test
\`\`\`"
;;
esac
cat <<READMEEOF
# $REPO_NAME
$DESCRIPTION
## 快速开始
$lang_section
## 贡献指南
详见 [CONTRIBUTING](./CONTRIBUTING.md)。
## 许可证
本项目基于 MIT 许可证开源 — 详见 [LICENSE](./LICENSE)。
READMEEOF
}
# --- LICENSE (MIT) ---
gen_license() {
local year
year=$(date +%Y)
cat <<LICENSEEOF
MIT License
Copyright (c) $year $OWNER
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.
LICENSEEOF
}
# --- CONTRIBUTING.md ---
gen_contributing() {
cat <<CONTRIBEOF
# Contributing to $REPO_NAME
Thank you for your interest in contributing!
## How to Contribute
1. Fork the repository
2. Create a feature branch: \`git checkout -b feature/my-feature\`
3. Make your changes
4. Run tests to ensure everything passes
5. Commit your changes: \`git commit -m 'feat: add my feature'\`
6. Push to your fork: \`git push origin feature/my-feature\`
7. Create a Pull Request
## Code Style
- Follow the existing code style
- Write meaningful commit messages following [Conventional Commits](https://www.conventionalcommits.org/)
- Add tests for new features
- Update documentation as needed
## Reporting Issues
- Use the [issue tracker](https://gitlink.org.cn/$OWNER/$REPO_NAME/issues)
- Include steps to reproduce
- Include environment details (OS, language version, etc.)
## Code of Conduct
Please be respectful and constructive in all interactions.
CONTRIBEOF
}
# --- .gitlink-ci.yml ---
gen_ci_config() {
case "$PROJ_LANG" in
go)
cat <<CIEOF
image: golang:1.21
stages:
- test
- build
test:
stage: test
script:
- go mod download
- go test ./... -v -cover
build:
stage: build
script:
- go build ./...
CIEOF
;;
python)
cat <<CIEOF
image: python:3.9
stages:
- test
- lint
test:
stage: test
script:
- pip install -r requirements.txt
- pytest -v --cov
lint:
stage: lint
script:
- pip install flake8
- flake8 .
CIEOF
;;
node)
cat <<CIEOF
image: node:18
stages:
- test
- build
test:
stage: test
script:
- npm ci
- npm test -- --coverage
build:
stage: build
script:
- npm ci
- npm run build
CIEOF
;;
java)
cat <<CIEOF
image: maven:3.8-openjdk-17
stages:
- test
- build
test:
stage: test
script:
- mvn test
build:
stage: build
script:
- mvn package -DskipTests
CIEOF
;;
esac
}
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would generate: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml"
else
gen_readme > "$WORK_DIR/README.md"
gen_license > "$WORK_DIR/LICENSE"
gen_contributing > "$WORK_DIR/CONTRIBUTING.md"
gen_ci_config > "$WORK_DIR/.gitlink-ci.yml"
log_ok "Generated: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml"
fi
# ── Step 4: Push files to repo ───────────────────────────────────────
log_step "Step 4/8: Pushing scaffold files to repository..."
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would git add/commit/push to $REPO_URL"
else
pushd "$WORK_DIR" > /dev/null
git add README.md LICENSE CONTRIBUTING.md .gitlink-ci.yml
git -c user.name="$OWNER" -c user.email="$OWNER@gitlink.org.cn" \
commit -m "chore: initialize project scaffold
- Add README.md with getting-started guide
- Add MIT LICENSE
- Add CONTRIBUTING.md with guidelines
- Add .gitlink-ci.yml CI pipeline configuration" 2>&1 | tail -1
git push -u origin master 2>&1 | tail -1
popd > /dev/null
log_ok "Scaffold files pushed to master"
fi
# ── Step 5: Create Milestone ─────────────────────────────────────────
log_step "Step 5/8: Creating initial milestone..."
MILESTONES=(
"v1.0.0 - First Release|First official release milestone"
)
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would create ${#MILESTONES[@]} milestone"
else
for entry in "${MILESTONES[@]}"; do
IFS='|' read -r ms_title ms_desc <<< "$entry"
MS_RESULT=$(gl_run milestone +create --owner "$OWNER" --repo "$REPO_NAME" \
--name "$ms_title" --description "$ms_desc" 2>&1) || true
if [[ "$(json_ok "$MS_RESULT")" == "true" ]]; then
log_ok "Milestone created: $ms_title"
else
log_warn "Milestone creation may have failed: $ms_title"
fi
done
fi
# ── Step 6: Create Welcome Issue ─────────────────────────────────────
log_step "Step 6/8: Creating welcome issue..."
ISSUES_TO_CREATE=(
"Welcome to $REPO_NAME|欢迎来到 **${REPO_NAME}** 的仓库这是本仓库的第一条issue|welcome"
)
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would create ${#ISSUES_TO_CREATE[@]} initial issues"
else
for entry in "${ISSUES_TO_CREATE[@]}"; do
IFS='|' read -r title body label <<< "$entry"
ISSUE_RESULT=$(gl_run issue +create --owner "$OWNER" --repo "$REPO_NAME" \
--title "$title" --body "$body" 2>&1) || true
ISSUE_NUM=$(echo "$ISSUE_RESULT" | jq -r '.data.id // .data.number // empty')
if [[ -n "$ISSUE_NUM" ]]; then
gl_run issue +label-add --owner "$OWNER" --repo "$REPO_NAME" --number "$ISSUE_NUM" --labels "$label" > /dev/null 2>&1 || true
log_ok "Issue created: #$ISSUE_NUM - $title"
else
log_warn "Issue creation may have failed: $title"
fi
done
fi
# ── Step 7: Protect Default Branch ───────────────────────────────────
log_step "Step 7/8: Protecting master branch..."
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would protect branch 'master'"
else
PROTECT_RESULT=$(gl_run branch +protect --owner "$OWNER" --repo "$REPO_NAME" --name master 2>&1) || true
if [[ "$(json_ok "$PROTECT_RESULT")" == "true" ]]; then
log_ok "Branch 'master' protected"
else
log_warn "Branch protection may have failed (may require admin permissions)"
fi
fi
# ── Step 8: Create Initial Release ───────────────────────────────────
log_step "Step 8/8: Creating initial release v0.1.0..."
RELEASE_BODY="# v0.1.0 - Initial Release
## What's New
- Project initialized with $PROJ_LANG template
- README, LICENSE, CONTRIBUTING guide in repository
- CI/CD pipeline configuration (.gitlink-ci.yml)
- ${#MILESTONES[@]} project milestone created
- ${#ISSUES_TO_CREATE[@]} initial issues filed
- Branch protection enabled
## Next Steps
- [ ] Setup CI/CD pipeline
- [ ] Write comprehensive tests
- [ ] Complete documentation
- [ ] First feature implementation
---
*Auto-initialized by gitlink-cli project-init workflow*"
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "[DRY RUN] Would create release v0.1.0"
else
RELEASE_RESULT=$(gl_run release +create --owner "$OWNER" --repo "$REPO_NAME" \
--tag "v0.1.0" --name "Initial Release" --body "$RELEASE_BODY" 2>&1) || true
if [[ "$(json_ok "$RELEASE_RESULT")" == "true" ]]; then
log_ok "Release v0.1.0 created"
else
log_warn "Release creation may have failed"
fi
fi
# ─────────────────────────────────────────────────────────────────────
log_title "Project Initialization Complete"
# ─────────────────────────────────────────────────────────────────────
echo -e "${GREEN}Created:${NC}"
echo " Repository: $OWNER/$REPO_NAME"
echo " Files: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml"
echo " Milestones: ${#MILESTONES[@]} milestone"
echo " Issues: ${#ISSUES_TO_CREATE[@]} initial issues"
echo " Branch: master (protected)"
echo " Release: v0.1.0"
echo ""
echo -e "${CYAN}Next steps:${NC}"
echo " 1. Clone: git clone $REPO_URL"
echo " 2. Start coding and close the first issue"
echo " 3. CI/CD will trigger on your first push"
echo ""