|
1 | 1 | name: Release |
2 | 2 |
|
3 | 3 | on: |
| 4 | + pull_request: |
| 5 | + types: [closed] |
| 6 | + branches: [main] |
4 | 7 | workflow_dispatch: |
| 8 | + inputs: |
| 9 | + bump: |
| 10 | + description: "Version part to bump" |
| 11 | + required: true |
| 12 | + type: choice |
| 13 | + options: [patch, minor, major] |
| 14 | + default: patch |
5 | 15 |
|
6 | 16 | env: |
7 | | - COMPONENT_NAME: solis_modbus |
| 17 | + COMPONENT_NAME: solisconnect |
8 | 18 |
|
9 | 19 | jobs: |
10 | 20 | release: |
11 | 21 | name: Prepare release |
| 22 | + # Only release for: a manual run, or a merged (not just closed) PR from patch/dev into main. |
| 23 | + if: | |
| 24 | + github.event_name == 'workflow_dispatch' || |
| 25 | + (github.event.pull_request.merged == true && |
| 26 | + contains(fromJson('["patch", "dev"]'), github.event.pull_request.head.ref)) |
12 | 27 | runs-on: ubuntu-latest |
13 | 28 | permissions: |
14 | 29 | contents: write |
15 | | - id-token: write |
16 | 30 | steps: |
17 | 31 | - uses: actions/checkout@v4 |
18 | 32 | with: |
| 33 | + ref: main |
19 | 34 | fetch-depth: 0 |
| 35 | + # A PAT (not the default GITHUB_TOKEN) is required: main is protected and only an |
| 36 | + # admin's own credentials can push directly to it, and only a PAT-authenticated push |
| 37 | + # will trigger the branch's required status-check workflows on the bump commit. |
| 38 | + token: ${{ secrets.PAT }} |
20 | 39 |
|
21 | | - - name: Install jq |
22 | | - run: sudo apt-get install jq |
23 | | - |
24 | | - - name: Install Python semver |
25 | | - run: pip install semver |
26 | | - |
27 | | - - name: Get latest tag or fail |
28 | | - id: get-latest-tag |
29 | | - run: | |
30 | | - latest_tag=$(git for-each-ref --sort=version:refname --format '%(refname)' refs/tags/ | grep -v 'latest' | tail -1 | sed 's/^refs\/tags\///; s/^v//') |
31 | | - if [ -z "$latest_tag" ]; then |
32 | | - echo "No tags found for the commit." |
33 | | - exit 1 |
34 | | - fi |
35 | | - echo "latest_tag=$latest_tag" >> $GITHUB_ENV |
36 | | -
|
37 | | - - name: Get current version from manifest.json |
38 | | - id: get-version |
| 40 | + - name: Install jq and semver |
39 | 41 | run: | |
40 | | - current_version=$(cat "${{ github.workspace }}/custom_components/${{ env.COMPONENT_NAME }}/manifest.json" | jq -r '.version') |
41 | | - echo "version=$current_version" >> $GITHUB_ENV |
42 | | -
|
43 | | - - name: Check if version is higher and bump if needed |
44 | | - id: check-version |
| 42 | + sudo apt-get install -y jq |
| 43 | + pip install semver |
| 44 | +
|
| 45 | + - name: Determine bump type |
| 46 | + # Values are passed via env, not interpolated into the script, so an attacker-controlled |
| 47 | + # branch name (e.g. a fork PR's head ref) can't inject shell commands here. |
| 48 | + env: |
| 49 | + EVENT_NAME: ${{ github.event_name }} |
| 50 | + HEAD_REF: ${{ github.event.pull_request.head.ref }} |
| 51 | + BUMP_INPUT: ${{ inputs.bump }} |
45 | 52 | run: | |
46 | | - latest="${{ env.latest_tag }}" |
47 | | - current="${{ env.version }}" |
48 | | -
|
49 | | - echo "Current version: $current" |
50 | | - echo "Latest tag: $latest" |
51 | | -
|
52 | | - # Check if latest tag is a valid SemVer string |
53 | | - if ! python -c "import semver; semver.VersionInfo.parse('$latest')" > /dev/null 2>&1; then |
54 | | - echo "Latest tag '$latest' is not a valid SemVer version, treating it as the current version." |
55 | | - latest=$current # Treat invalid tag as current version |
56 | | - fi |
57 | | -
|
58 | | - # Check if current version is higher than the latest tag (which is now set to current if invalid) |
59 | | - is_higher=$(python -c "import semver; print(semver.compare('$current', '$latest') > 0)") |
60 | | -
|
61 | | - if [ "$is_higher" != "True" ]; then |
62 | | - echo "The version is not higher. Bumping patch version..." |
63 | | - bumped=$(python -c "import semver; print(semver.bump_patch('$latest'))") |
64 | | - echo "New version: $bumped" |
65 | | - jq ".version = \"$bumped\"" "${{ github.workspace }}/custom_components/${{ env.COMPONENT_NAME }}/manifest.json" > package.tmp.json && mv package.tmp.json "${{ github.workspace }}/custom_components/${{ env.COMPONENT_NAME }}/manifest.json" |
66 | | - echo "version=$bumped" >> $GITHUB_ENV |
| 53 | + if [ "$EVENT_NAME" = "workflow_dispatch" ]; then |
| 54 | + bump="$BUMP_INPUT" |
| 55 | + elif [ "$HEAD_REF" = "dev" ]; then |
| 56 | + bump="minor" |
67 | 57 | else |
68 | | - echo "version=$current" >> $GITHUB_ENV |
| 58 | + bump="patch" |
69 | 59 | fi |
| 60 | + echo "Bump type: $bump" |
| 61 | + echo "bump=$bump" >> "$GITHUB_ENV" |
70 | 62 |
|
71 | | - echo "is_higher_version=true" >> $GITHUB_ENV |
| 63 | + - name: Bump version in manifest.json |
| 64 | + run: | |
| 65 | + manifest="custom_components/${{ env.COMPONENT_NAME }}/manifest.json" |
| 66 | + current=$(jq -r '.version' "$manifest") |
| 67 | + new=$(python -c "import semver; print(semver.bump_${{ env.bump }}('$current'))") |
| 68 | + echo "Bumping $current -> $new (${{ env.bump }})" |
| 69 | + jq ".version = \"$new\"" "$manifest" > package.tmp.json && mv package.tmp.json "$manifest" |
| 70 | + echo "version=$new" >> "$GITHUB_ENV" |
72 | 71 |
|
73 | 72 | - name: Commit and push version bump |
74 | | - if: env.is_higher_version == 'true' |
75 | 73 | run: | |
76 | | - git config user.name "github-actions" |
77 | | - git config user.email "github-actions@github.com" |
78 | | - git add custom_components/${{ env.COMPONENT_NAME }}/manifest.json |
79 | | - git diff --exit-code || (git commit -m "chore: bump version to v${{ env.version }}" && git push) |
| 74 | + git config user.name "github-actions[bot]" |
| 75 | + git config user.email "github-actions[bot]@users.noreply.github.com" |
| 76 | + git add "custom_components/${{ env.COMPONENT_NAME }}/manifest.json" |
| 77 | + git commit -m "chore: release v${{ env.version }}" |
| 78 | + git push origin HEAD:main |
80 | 79 |
|
81 | 80 | - name: Zip ${{ env.COMPONENT_NAME }} dir |
82 | 81 | run: | |
83 | | - cd "${{ github.workspace }}/custom_components/${{ env.COMPONENT_NAME }}" |
84 | | - zip ${{ env.COMPONENT_NAME }}.zip -r ./ |
| 82 | + cd "custom_components/${{ env.COMPONENT_NAME }}" |
| 83 | + zip "${{ env.COMPONENT_NAME }}.zip" -r ./ |
85 | 84 |
|
86 | 85 | - name: Upload zip to release |
87 | | - if: env.is_higher_version == 'true' |
88 | 86 | uses: softprops/action-gh-release@v2 |
89 | 87 | with: |
90 | | - files: ${{ github.workspace }}/custom_components/${{ env.COMPONENT_NAME }}/${{ env.COMPONENT_NAME }}.zip |
| 88 | + files: custom_components/${{ env.COMPONENT_NAME }}/${{ env.COMPONENT_NAME }}.zip |
91 | 89 | tag_name: v${{ env.version }} |
92 | 90 | name: v${{ env.version }} |
93 | 91 | token: ${{ secrets.PAT }} |
94 | 92 | generate_release_notes: true |
95 | 93 |
|
96 | 94 | - name: 🏷️ Update latest tag |
97 | | - if: env.is_higher_version == 'true' |
98 | 95 | uses: EndBug/latest-tag@latest |
| 96 | + with: |
| 97 | + github-token: ${{ secrets.PAT }} |
0 commit comments