Duke Yin's Technology database

GitHub Action: 自动发布WordPress主题插件新版本

主要功能

  • 当主题或插件修改提交commit 并 push到Github时,自动打包主题插件发布一个Realease
  • 判断当前版本号,如果与之前版本号相同则不发布
  • .releaseignore文件设置忽略的文件或文件夹,不打包进release

主题

必须按照WordPress主题开发规范,在style.css顶部注释版本号(Version:)

文件位置:

.github/workflows/release-on-version-change.yml

内容:

name: Release on version change

on:
  push:
    branches:
      - main
      - master
      
permissions:
  contents: write
  packages: write

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Get previous commit hash
        id: prev
        run: |
          echo "prev_commit=$(git rev-parse HEAD^)" >> $GITHUB_ENV

      - name: Extract current version from style.css
        id: current_version
        run: |
          version=$(grep -E '^(Version:|版本:)' style.css | sed 's/.*[::] *//')
          if [ -z "$version" ]; then
            echo "❌ 未能在当前 style.css 中找到版本号"
            exit 1
          fi
          echo "current_version=$version" >> $GITHUB_ENV
          echo "当前版本: $version"

      - name: Extract previous version from last commit
        id: prev_version
        run: |
          git show ${{ env.prev_commit }}:style.css > old_style.css || true
          version=$(grep -E '^(Version:|版本:)' old_style.css | sed 's/.*[::] *//')
          echo "prev_version=$version" >> $GITHUB_ENV
          echo "上一个版本: $version"

      - name: Compare versions
        id: compare
        run: |
          if [ "${{ env.current_version }}" != "${{ env.prev_version }}" ]; then
            echo "version_changed=true" >> $GITHUB_ENV
            echo "🔄 版本变化: ${{ env.prev_version }} → ${{ env.current_version }}"
          else
            echo "version_changed=false" >> $GITHUB_ENV
            echo "ℹ️ 版本未变化,无需发布"
          fi

      - name: Stop if version not changed
        if: env.version_changed == 'false'
        run: exit 0

      - name: Check if tag already exists
        id: tag_check
        run: |
          if git rev-parse "v${{ env.current_version }}" >/dev/null 2>&1; then
            echo "tag_exists=true" >> $GITHUB_ENV
            echo "⚠️ Tag v${{ env.current_version }} 已存在,跳过发布"
          else
            echo "tag_exists=false" >> $GITHUB_ENV
          fi

      - name: Stop if tag already exists
        if: env.tag_exists == 'true'
        run: exit 0

      - name: Create Git tag
        if: env.tag_exists == 'false'
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
          git tag -a "v${{ env.current_version }}" -m "Release v${{ env.current_version }}"
          git push origin "v${{ env.current_version }}"

      - name: Create ZIP package (with ignore list)
        run: |
          ZIP_FILE="${{ github.event.repository.name }}-${{ env.current_version }}.zip"
          EXCLUDE_ARGS="-x '*.git*' '.github/*'"
          if [ -f ".releaseignore" ]; then
            echo "🧾 使用 .releaseignore 过滤以下内容:"
            while IFS= read -r line; do
              if [ -n "$line" ] && [[ ! "$line" =~ ^# ]]; then
                echo "  - $line"
                EXCLUDE_ARGS="$EXCLUDE_ARGS '$line'"
              fi
            done < .releaseignore
          else
            echo "⚠️ 未找到 .releaseignore,使用默认排除规则。"
          fi
          eval zip -r "$ZIP_FILE" . $EXCLUDE_ARGS
          echo "✅ 打包完成:$ZIP_FILE"

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ env.current_version }}
          name: "Release v${{ env.current_version }}"
          body: |
            🎉 自动发布版本 v${{ env.current_version }}
            🔖 来自 commit: ${{ github.sha }}
          files: ${{ github.event.repository.name }}-${{ env.current_version }}.zip
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

文件位置:

.releaseignore

内容:

# 忽略开发工具配置
.vscode/
.idea/
.gitattributes
.gitignore
.releaseignore

# 忽略文档和演示
README.md
screenshot.png
docs/
examples/

# 忽略 CI/CD 相关文件
.github/
.gitlab-ci.yml

# 忽略测试文件
tests/
*.log

# 忽略 Mac/Windows 系统文件
.DS_Store
Thumbs.db

# 忽略源代码文件
assets\main.scss
webpack.config.js

插件

必须按照WordPress插件开发规范,根目录存在插件名称php,并在顶部注释版本号(Version:)

文件位置:

.github/workflows/release-on-version-change.yml

内容:

name: Release on Plugin Version Change

on:
  push:
    branches:
      - main
      - master

permissions:
  contents: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Get plugin main file
        id: find_plugin_file
        run: |
          # 查找插件主文件(假设插件主文件在仓库根目录下且带有 Plugin Name)
          PLUGIN_FILE=$(grep -rl "Plugin Name:" . | head -n 1)
          if [ -z "$PLUGIN_FILE" ]; then
            echo "❌ 未找到插件主文件(包含 Plugin Name: 的PHP文件)。"
            exit 1
          fi
          echo "plugin_file=$PLUGIN_FILE" >> $GITHUB_OUTPUT
          echo "✅ 找到插件文件: $PLUGIN_FILE"

      - name: Get current version from plugin header
        id: get_version
        run: |
          FILE="${{ steps.find_plugin_file.outputs.plugin_file }}"

          # 使用兼容 WordPress 格式的正则提取 Version 字段
          VERSION=$(grep -Eim1 "^[[:space:]]*(\*|#|//)?[[:space:]]*Version:[[:space:]]*[0-9]+\.[0-9]+(\.[0-9]+)?" "$FILE" | sed -E 's/.*Version:[[:space:]]*([0-9.]+).*/\1/')

          if [ -z "$VERSION" ]; then
            echo "❌ 未能从插件文件中提取版本号。"
            echo "文件内容示例:"
            head -n 20 "$FILE"
            exit 1
          fi

          echo "current_version=$VERSION" >> $GITHUB_OUTPUT
          echo "✅ 当前版本号:$VERSION"

      - name: Check if version already released
        id: check_release
        run: |
          VERSION=${{ steps.get_version.outputs.current_version }}
          EXISTING=$(gh release list --limit 100 | grep -F "v$VERSION" || true)
          if [ -n "$EXISTING" ]; then
            echo "⚠️ 版本 v$VERSION 已存在,跳过发布。"
            echo "skip_release=true" >> $GITHUB_OUTPUT
          else
            echo "skip_release=false" >> $GITHUB_OUTPUT
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create ZIP package (with .releaseignore)
        if: steps.check_release.outputs.skip_release == 'false'
        run: |
          VERSION=${{ steps.get_version.outputs.current_version }}
          ZIP_FILE="${{ github.event.repository.name }}-${VERSION}.zip"
          EXCLUDE_ARGS="-x '*.git*' '.github/*'"

          if [ -f ".releaseignore" ]; then
            echo "🧾 使用 .releaseignore 过滤以下内容:"
            while IFS= read -r line; do
              if [ -n "$line" ] && [[ ! "$line" =~ ^# ]]; then
                echo "  - $line"
                EXCLUDE_ARGS="$EXCLUDE_ARGS '$line'"
              fi
            done < .releaseignore
          fi

          eval zip -r "$ZIP_FILE" . $EXCLUDE_ARGS
          echo "✅ 打包完成:$ZIP_FILE"

      - name: Create GitHub Release
        if: steps.check_release.outputs.skip_release == 'false'
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ steps.get_version.outputs.current_version }}
          name: "v${{ steps.get_version.outputs.current_version }}"
          body: "🔖 自动发布插件版本 v${{ steps.get_version.outputs.current_version }}"
          files: |
            ${{ github.event.repository.name }}-${{ steps.get_version.outputs.current_version }}.zip
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

文件位置:

.releaseignore

内容:

# 开发文件
.vscode/
.idea/
node_modules/

# 文档
README.md
screenshot.png
docs/
tests/

# GitHub Actions
.github/
.gitlab-ci.yml

# 系统文件
.DS_Store
Thumbs.db
*.log

注意

主题插件的文件命名、文件结构应符合WordPress规范,例如:

主题目录根目录应包含 style.css,开头注释应包含 “Version” 字段

插件名称为“My Good Plugin”,主插件文件应为 my-good-plugin.php,此文件头部应包含Version注释。

当任意提交push时,会首先检查版本号,如果与之前相同则不发布新版,不相同则自动打包发布,打包内容忽略.releaseignore内的所有文件或文件夹。

发布评论

评论

标注 * 的为必填项。