ci: add GitHub Actions build workflow #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - master | |
| workflow_dispatch: | |
| jobs: | |
| build-and-release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Build project | |
| run: npm run build | |
| - name: Get version & extension name from extension.json | |
| id: meta | |
| run: | | |
| echo "VERSION=$(jq -r .version extension.json)" >> $GITHUB_ENV | |
| echo "EEXTNAME=$(jq -r .name extension.json)" >> $GITHUB_ENV | |
| - name: Check and create tag | |
| id: check_tag | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| TAG="v${VERSION}" | |
| echo "🔎 检查 tag $TAG 是否存在..." | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "⚠️ Tag $TAG 已存在,跳过发布。" | |
| echo "SKIP_RELEASE=true" >> $GITHUB_ENV | |
| else | |
| echo "✅ Tag $TAG 不存在,创建并推送。" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag -a "$TAG" -m "Release $TAG" | |
| git push origin "$TAG" | |
| echo "SKIP_RELEASE=false" >> $GITHUB_ENV | |
| fi | |
| - name: Extract changelog for version | |
| if: env.SKIP_RELEASE == 'false' | |
| id: changelog | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| EEXTNAME=${{ env.EEXTNAME }} | |
| echo "🔎 Extracting changelog for version $VERSION from CHANGELOG.md" | |
| ESCAPED_VERSION=$(echo "$VERSION" | sed 's/\./\\./g') | |
| if [ -f "CHANGELOG.md" ]; then | |
| # 支持多种 CHANGELOG 格式(兼容大小写 V): | |
| # - # v1.5.3 或 # V1.5.3 或 # 1.5.3 | |
| # - ## v1.5.3 或 ## V1.5.3 或 ## 1.5.3 | |
| # - ## [1.5.3] - 2024-01-01 或 ## [v1.5.3] | |
| NOTES=$(awk ' | |
| BEGIN { found=0 } | |
| # 匹配版本行(兼容大小写 v/V) | |
| /^(#|##) \[?[vV]?'"$ESCAPED_VERSION"'\]?([[:space:]-]|$)/ { | |
| if (found) exit | |
| found=1 | |
| next | |
| } | |
| # 遇到下一个版本标题时停止 | |
| /^(#|##) \[?[vV]?[0-9]+\.[0-9]+\.[0-9]+\]?([[:space:]-]|$)/ { | |
| if (found) exit | |
| } | |
| # 遇到一级标题(如"更新日志"、"Changelog"、"修改记录")时停止 | |
| /^# [^[\-0-9]/ { | |
| if (found) exit | |
| } | |
| found { print } | |
| ' CHANGELOG.md) | |
| # 清理空行 | |
| NOTES=$(echo "$NOTES" | sed '/^[[:space:]]*$/d' | sed '1{/^$/d}') | |
| if [ -z "$NOTES" ]; then | |
| echo "⚠️ CHANGELOG.md 中未找到版本 $VERSION 的记录,使用默认说明" | |
| NOTES="Release v${VERSION}" | |
| else | |
| echo "✅ 已从 CHANGELOG.md 中提取版本 $VERSION 的更新日志" | |
| fi | |
| else | |
| echo "⚠️ 未找到 CHANGELOG.md 文件,使用默认说明" | |
| NOTES="Release v${VERSION}" | |
| fi | |
| # 添加页脚 | |
| NOTES="${NOTES} | |
| --- | |
| 由GitHub Actions自动构建并发布 | |
| Built and released automatically by GitHub Actions | |
| 也可前往[嘉立创EDA扩展广场](https://jlc-ext.com/item/oshwhub/${EEXTNAME})下载 | |
| Also available at [JLCEDA Extension Plaza](https://jlcext.com/item/oshwlab/${EEXTNAME})" | |
| # 使用 EOF 分隔符设置多行环境变量 | |
| echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV | |
| echo "$NOTES" >> $GITHUB_ENV | |
| echo "EOF" >> $GITHUB_ENV | |
| echo "------ Release Notes ------" | |
| echo "$NOTES" | |
| echo "---------------------------" | |
| - name: Build zh-cn package | |
| if: env.SKIP_RELEASE == 'false' | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| EEXTNAME=${{ env.EEXTNAME }} | |
| DIST_DIR="build/dist" | |
| ZH_FILE="${DIST_DIR}/${EEXTNAME}_v${VERSION}_zh-cn.eext" | |
| echo "📦 构建中文版包..." | |
| # 查找中文 README 文件 | |
| # 优先级:README_zh.md > README_zh-*.md > README.zh.md > README.zh-*.md > README.md | |
| ZH_README="" | |
| if [ -f "README_zh.md" ]; then | |
| ZH_README="README_zh.md" | |
| elif [ -f "README.zh.md" ]; then | |
| ZH_README="README.zh.md" | |
| else | |
| # 查找 README_zh-xx.md 或 README.zh-xx.md 格式 | |
| ZH_README=$(ls README_zh-*.md README.zh-*.md 2>/dev/null | head -1) | |
| fi | |
| # 如果没有中文 README,使用默认 README.md | |
| if [ -z "$ZH_README" ]; then | |
| echo "⚠️ 未找到中文 README,使用默认 README.md" | |
| ZH_README="README.md" | |
| else | |
| echo "✅ 使用中文 README: $ZH_README" | |
| fi | |
| # 创建临时目录 | |
| TEMP_DIR=$(mktemp -d) | |
| cp -r . "$TEMP_DIR/source" | |
| # 替换 README.md | |
| if [ "$ZH_README" != "README.md" ] && [ -f "$ZH_README" ]; then | |
| cp "$ZH_README" "$TEMP_DIR/source/README.md" | |
| fi | |
| # 打包 | |
| cd "$TEMP_DIR/source" | |
| zip -r "$OLDPWD/$ZH_FILE" . -x ".git/*" ".husky/*" ".vscode/*" ".claude/*" "build/*" "config/*" "coverage/*" "node_modules/*" "src/*" ".editorconfig" ".gitattributes" ".gitignore" ".npmrc" "eslint.config.mjs" "package-lock.json" "package.json" "tsconfig.json" ".eslintcache" "debug.log" "*.md" "!README.md" "CHANGELOG.md" | |
| echo "✅ 中文版包构建完成: $ZH_FILE" | |
| ls -lh "$OLDPWD/$ZH_FILE" | |
| # 清理 | |
| rm -rf "$TEMP_DIR" | |
| - name: Build global package | |
| if: env.SKIP_RELEASE == 'false' | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| EEXTNAME=${{ env.EEXTNAME }} | |
| DIST_DIR="build/dist" | |
| GLOBAL_FILE="${DIST_DIR}/${EEXTNAME}_v${VERSION}_global.eext" | |
| echo "📦 构建国际版包..." | |
| # 查找英文 README 文件 | |
| # 优先级:README_en.md > README_en-*.md > README.en.md > README.en-*.md > README.md | |
| EN_README="" | |
| if [ -f "README_en.md" ]; then | |
| EN_README="README_en.md" | |
| elif [ -f "README.en.md" ]; then | |
| EN_README="README.en.md" | |
| else | |
| # 查找 README_en-xx.md 或 README.en-xx.md 格式 | |
| EN_README=$(ls README_en-*.md README.en-*.md 2>/dev/null | head -1) | |
| fi | |
| # 如果没有英文 README,使用默认 README.md | |
| if [ -z "$EN_README" ]; then | |
| echo "⚠️ 未找到英文 README,使用默认 README.md" | |
| EN_README="README.md" | |
| else | |
| echo "✅ 使用英文 README: $EN_README" | |
| fi | |
| # 创建临时目录 | |
| TEMP_DIR=$(mktemp -d) | |
| cp -r . "$TEMP_DIR/source" | |
| # 替换 README.md | |
| if [ "$EN_README" != "README.md" ] && [ -f "$EN_README" ]; then | |
| cp "$EN_README" "$TEMP_DIR/source/README.md" | |
| fi | |
| # 打包 | |
| cd "$TEMP_DIR/source" | |
| zip -r "$OLDPWD/$GLOBAL_FILE" . -x ".git/*" ".husky/*" ".vscode/*" ".claude/*" "build/*" "config/*" "coverage/*" "node_modules/*" "src/*" ".editorconfig" ".gitattributes" ".gitignore" ".npmrc" "eslint.config.mjs" "package-lock.json" "package.json" "tsconfig.json" ".eslintcache" "debug.log" "*.md" "!README.md" "CHANGELOG.md" | |
| echo "✅ 国际版包构建完成: $GLOBAL_FILE" | |
| ls -lh "$OLDPWD/$GLOBAL_FILE" | |
| # 清理 | |
| rm -rf "$TEMP_DIR" | |
| - name: Debug check artifacts | |
| if: env.SKIP_RELEASE == 'false' | |
| run: | | |
| VERSION=${{ env.VERSION }} | |
| EEXTNAME=${{ env.EEXTNAME }} | |
| DIST_DIR="build/dist" | |
| ZH_FILE="${DIST_DIR}/${EEXTNAME}_v${VERSION}_zh-cn.eext" | |
| GLOBAL_FILE="${DIST_DIR}/${EEXTNAME}_v${VERSION}_global.eext" | |
| echo "🔍 检查构建产物..." | |
| if [ -f "$ZH_FILE" ]; then | |
| echo "✅ 中文版产物存在: $ZH_FILE" | |
| else | |
| echo "❌ 中文版产物不存在: $ZH_FILE" | |
| ls -R build || true | |
| exit 1 | |
| fi | |
| if [ -f "$GLOBAL_FILE" ]; then | |
| echo "✅ 国际版产物存在: $GLOBAL_FILE" | |
| else | |
| echo "❌ 国际版产物不存在: $GLOBAL_FILE" | |
| ls -R build || true | |
| exit 1 | |
| fi | |
| - name: Upload Release | |
| if: env.SKIP_RELEASE == 'false' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ env.VERSION }} | |
| name: Release v${{ env.VERSION }} | |
| body: ${{ env.RELEASE_NOTES }} | |
| files: | | |
| build/dist/${{ env.EEXTNAME }}_v${{ env.VERSION }}_zh-cn.eext | |
| build/dist/${{ env.EEXTNAME }}_v${{ env.VERSION }}_global.eext | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |