feat(WanDirector): Ctrl+V clipboard-image paste (LTX parity) — port t… #142
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: Version Bump | |
| on: | |
| push: | |
| branches: [main, master] | |
| workflow_dispatch: | |
| inputs: | |
| bump: | |
| description: "Force a specific bump (auto|patch|minor|major|none)" | |
| required: false | |
| default: "auto" | |
| type: choice | |
| options: [auto, patch, minor, major, none] | |
| concurrency: | |
| group: version-bump-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| env: | |
| # Opt into Node.js 24 for actions to silence the Node 20 deprecation warning. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| jobs: | |
| bump: | |
| name: Bump version & tag | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event_name == 'workflow_dispatch' || | |
| !startsWith(github.event.head_commit.message, 'chore(release):') | |
| outputs: | |
| new_version: ${{ steps.bump.outputs.new_version }} | |
| bumped: ${{ steps.bump.outputs.bumped }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Determine bump type | |
| id: classify | |
| shell: bash | |
| # NOTE: intentionally NOT using `set -e`. The grep pipelines below are | |
| # expected to return non-zero when no match is found, which is normal | |
| # control flow — letting `-e` kill the step caused historical false | |
| # failures. Errors that matter are reported explicitly. | |
| run: | | |
| set +e | |
| # ---------------------------------------------------------------- | |
| # Resolve commit range since the last semver tag (or full history). | |
| # ---------------------------------------------------------------- | |
| last_tag="$(git describe --tags --abbrev=0 2>/dev/null || true)" | |
| if [ -n "$last_tag" ]; then | |
| range="${last_tag}..HEAD" | |
| else | |
| range="HEAD" | |
| fi | |
| msgs="$(git log --pretty=%s "$range" 2>/dev/null || true)" | |
| # ---------------------------------------------------------------- | |
| # Honour an explicit input from workflow_dispatch. | |
| # ---------------------------------------------------------------- | |
| forced="${{ github.event.inputs.bump }}" | |
| if [ -n "$forced" ] && [ "$forced" != "auto" ]; then | |
| echo "bump=$forced" >> "$GITHUB_OUTPUT" | |
| echo "explicit_version=" >> "$GITHUB_OUTPUT" | |
| echo "Forced bump: $forced" | |
| exit 0 | |
| fi | |
| # ---------------------------------------------------------------- | |
| # Look for an explicit "v1.2.3"-style tag in any commit message so | |
| # manual releases still get tagged. | |
| # ---------------------------------------------------------------- | |
| explicit="$(printf '%s\n' "$msgs" | grep -oiE '\bv[0-9]+\.[0-9]+\.[0-9]+\b' | head -n1 | sed 's/^[vV]//' || true)" | |
| # ---------------------------------------------------------------- | |
| # Conventional Commits classification. | |
| # ---------------------------------------------------------------- | |
| bump=none | |
| if [ -n "$msgs" ]; then | |
| while IFS= read -r m; do | |
| [ -z "$m" ] && continue | |
| if printf '%s' "$m" | grep -qiE '^(feat|fix|refactor|perf)(\(.+\))?!:|BREAKING CHANGE'; then | |
| bump=major | |
| break | |
| elif printf '%s' "$m" | grep -qiE '^feat(\(.+\))?:'; then | |
| bump=minor | |
| elif [ "$bump" != "minor" ] && printf '%s' "$m" | grep -qiE '^fix(\(.+\))?:'; then | |
| bump=patch | |
| fi | |
| done <<< "$msgs" | |
| fi | |
| # ---------------------------------------------------------------- | |
| # Loose-keyword fallback for repos that don't use Conventional Commits. | |
| # ---------------------------------------------------------------- | |
| if [ "$bump" = "none" ]; then | |
| if printf '%s' "$msgs" | grep -qiE 'feature|added|implement'; then | |
| bump=minor | |
| elif printf '%s' "$msgs" | grep -qiE 'fix|bug|error|crash'; then | |
| bump=patch | |
| elif [ -n "$explicit" ]; then | |
| bump=patch | |
| elif printf '%s' "$msgs" | grep -qiE '\b(bump|release|publish|version)\b'; then | |
| bump=patch | |
| fi | |
| fi | |
| echo "bump=$bump" >> "$GITHUB_OUTPUT" | |
| echo "explicit_version=$explicit" >> "$GITHUB_OUTPUT" | |
| echo "Detected bump: $bump (explicit: ${explicit:-none})" | |
| exit 0 | |
| - name: Bump pyproject version | |
| id: bump | |
| if: steps.classify.outputs.bump != 'none' || steps.classify.outputs.explicit_version != '' | |
| shell: bash | |
| run: | | |
| set -e | |
| python - <<'PY' >> "$GITHUB_OUTPUT" | |
| import re, pathlib, sys | |
| bump = "${{ steps.classify.outputs.bump }}" | |
| explicit = "${{ steps.classify.outputs.explicit_version }}" | |
| p = pathlib.Path("pyproject.toml") | |
| if not p.exists(): | |
| print("bumped=false") | |
| sys.exit(0) | |
| txt = p.read_text(encoding="utf-8") | |
| m = re.search(r'(?m)^version\s*=\s*"([^"]+)"', txt) | |
| if not m: | |
| print("bumped=false") | |
| sys.exit(0) | |
| current = m.group(1) | |
| if explicit: | |
| new = explicit | |
| else: | |
| try: | |
| maj, mn, pt = (int(x) for x in current.split(".")) | |
| except Exception: | |
| print("bumped=false") | |
| sys.exit(0) | |
| if bump == "major": maj, mn, pt = maj + 1, 0, 0 | |
| elif bump == "minor": mn, pt = mn + 1, 0 | |
| elif bump == "patch": pt = pt + 1 | |
| else: new = current; print(f"new_version={new}"); print("bumped=false"); sys.exit(0) | |
| new = f"{maj}.{mn}.{pt}" | |
| if new != current: | |
| p.write_text( | |
| re.sub(r'(?m)^version\s*=\s*"[^"]+"', f'version = "{new}"', txt), | |
| encoding="utf-8", | |
| ) | |
| print(f"new_version={new}") | |
| print("bumped=true") | |
| else: | |
| print(f"new_version={new}") | |
| print("bumped=false") | |
| PY | |
| - name: Commit, tag, push | |
| if: steps.bump.outputs.bumped == 'true' | |
| env: | |
| NEW: ${{ steps.bump.outputs.new_version }} | |
| shell: bash | |
| run: | | |
| set -e | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| # Skip entirely if the tag already exists (manual tag or prior run). | |
| if git rev-parse "v${NEW}" >/dev/null 2>&1 || \ | |
| git ls-remote --exit-code --tags origin "refs/tags/v${NEW}" >/dev/null 2>&1; then | |
| echo "Tag v${NEW} already exists; nothing to do." | |
| exit 0 | |
| fi | |
| git add pyproject.toml | |
| if ! git diff --cached --quiet; then | |
| git commit -m "chore(release): v${NEW}" | |
| fi | |
| git tag -a "v${NEW}" -m "Release v${NEW}" | |
| git push origin HEAD --follow-tags |