[BUG] HACS Custom Repository Installation Issue #36
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: "PR Deployment" | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: "Pull Request Number" | |
| required: true | |
| type: number | |
| tag_name: | |
| description: "Tag/Version (z. B. v1.2.3-rc1)" | |
| required: true | |
| type: string | |
| release_name: | |
| description: "Release-Name" | |
| required: false | |
| default: "" | |
| type: string | |
| issue_comment: | |
| types: | |
| - "created" | |
| pull_request_review_comment: | |
| types: | |
| - "created" | |
| permissions: {} | |
| jobs: | |
| deploy: | |
| name: "Create pre-release from PR" | |
| if: > | |
| github.event_name == 'workflow_dispatch' || | |
| ( | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| startsWith(github.event.comment.body, '/deploy') | |
| ) || | |
| ( | |
| github.event_name == 'pull_request_review_comment' && | |
| startsWith(github.event.comment.body, '/deploy') | |
| ) | |
| runs-on: "ubuntu-latest" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - name: "Resolve deployment inputs" | |
| id: "resolve" | |
| shell: "bash" | |
| env: | |
| EVENT_NAME: "${{ github.event_name }}" | |
| INPUT_PR_NUMBER: "${{ inputs.pr_number }}" | |
| INPUT_TAG_NAME: "${{ inputs.tag_name }}" | |
| INPUT_RELEASE_NAME: "${{ inputs.release_name }}" | |
| COMMENT_BODY: "${{ github.event.comment.body }}" | |
| COMMENT_PR_NUMBER: "${{ github.event.issue.number }}" | |
| REVIEW_COMMENT_PR_NUMBER: "${{ github.event.pull_request.number }}" | |
| run: | | |
| if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then | |
| pr_number="${INPUT_PR_NUMBER}" | |
| tag_name="${INPUT_TAG_NAME}" | |
| release_name="${INPUT_RELEASE_NAME}" | |
| elif [[ "${EVENT_NAME}" == "pull_request_review_comment" ]]; then | |
| # Command format: /deploy [release name] | |
| tag_name="" | |
| release_name="${COMMENT_BODY#/deploy}" | |
| release_name="${release_name# }" | |
| pr_number="${REVIEW_COMMENT_PR_NUMBER}" | |
| else | |
| # Command format: /deploy [release name] | |
| tag_name="" | |
| release_name="${COMMENT_BODY#/deploy}" | |
| release_name="${release_name# }" | |
| pr_number="${COMMENT_PR_NUMBER}" | |
| fi | |
| echo "pr_number=${pr_number}" >> "$GITHUB_OUTPUT" | |
| echo "tag_name=${tag_name}" >> "$GITHUB_OUTPUT" | |
| echo "release_name=${release_name}" >> "$GITHUB_OUTPUT" | |
| # Authorization policy: | |
| # - Users who invoke this workflow (manual dispatch or /deploy comments) must have | |
| # at least write-level repository permission. | |
| # - Allowed levels are: write, maintain, admin. | |
| # - We prefer github.triggering_actor when available so workflow re-runs are checked | |
| # against the user who clicked re-run instead of the original actor. | |
| # This gate blocks all downstream checkout/tag/release steps when unauthorized. | |
| - name: "Authorize deployment actor" | |
| id: "authorize" | |
| uses: "actions/github-script@v7" | |
| env: | |
| REQUESTED_BY: "${{ github.triggering_actor != '' && github.triggering_actor || github.actor }}" | |
| with: | |
| script: | | |
| const allowedPermissions = new Set(['write', 'maintain', 'admin']); | |
| const requestedBy = process.env.REQUESTED_BY; | |
| const { data } = await github.rest.repos.getCollaboratorPermissionLevel({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| username: requestedBy, | |
| }); | |
| const permission = data.permission; | |
| core.info(`Deployment requested by '${requestedBy}' with '${permission}' permission.`); | |
| if (!allowedPermissions.has(permission)) { | |
| core.setFailed( | |
| `Deployment denied for @${requestedBy}: repository permission '${permission}' is below required level. ` + | |
| `Allowed permissions: ${Array.from(allowedPermissions).join(', ')}.` | |
| ); | |
| return; | |
| } | |
| core.info(`Authorization gate passed for @${requestedBy}.`); | |
| - name: "Checkout PR merge commit" | |
| uses: "actions/checkout@v4.1.0" | |
| with: | |
| ref: "refs/pull/${{ steps.resolve.outputs.pr_number }}/merge" | |
| fetch-depth: 0 | |
| - name: "Determine effective tag" | |
| id: "effective" | |
| shell: "bash" | |
| env: | |
| RESOLVED_TAG: "${{ steps.resolve.outputs.tag_name }}" | |
| PR_NUMBER: "${{ steps.resolve.outputs.pr_number }}" | |
| RUN_ID: "${{ github.run_id }}" | |
| run: | | |
| if [[ -n "${RESOLVED_TAG}" ]]; then | |
| tag_name="${RESOLVED_TAG}" | |
| else | |
| version="$(python -c 'import json; print(json.load(open("custom_components/samsung_soundbar/manifest.json"))["version"])')" | |
| tag_name="v${version}-pr${PR_NUMBER}-run${RUN_ID}" | |
| fi | |
| echo "tag_name=${tag_name}" >> "$GITHUB_OUTPUT" | |
| - name: "Validate tag format" | |
| shell: "bash" | |
| run: | | |
| if [[ ! "${{ steps.effective.outputs.tag_name }}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then | |
| echo "Tag '${{ steps.effective.outputs.tag_name }}' does not look like a semantic version." >&2 | |
| exit 1 | |
| fi | |
| - name: "Create pre-release" | |
| uses: "softprops/action-gh-release@v2" | |
| with: | |
| tag_name: "${{ steps.effective.outputs.tag_name }}" | |
| target_commitish: "${{ github.sha }}" | |
| prerelease: true | |
| generate_release_notes: true | |
| name: "${{ steps.resolve.outputs.release_name != '' && steps.resolve.outputs.release_name || steps.effective.outputs.tag_name }}" | |
| body: | | |
| Automated pre-release from PR #${{ steps.resolve.outputs.pr_number }}. | |
| - name: "Package integration" | |
| shell: "bash" | |
| run: | | |
| cd "${{ github.workspace }}/custom_components/samsung_soundbar" | |
| zip -r samsung_soundbar.zip ./ | |
| - name: "Attach integration package to pre-release" | |
| uses: "softprops/action-gh-release@v2" | |
| with: | |
| tag_name: "${{ steps.effective.outputs.tag_name }}" | |
| files: "${{ github.workspace }}/custom_components/samsung_soundbar/samsung_soundbar.zip" | |
| - name: "Comment on PR with release link" | |
| uses: "actions/github-script@v7" | |
| env: | |
| RELEASE_URL: "https://github.com/${{ github.repository }}/releases/tag/${{ steps.effective.outputs.tag_name }}" | |
| with: | |
| script: | | |
| const prNumber = Number('${{ steps.resolve.outputs.pr_number }}'); | |
| const releaseUrl = process.env.RELEASE_URL; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: `🚀 Pre-release erstellt: ${releaseUrl}`, | |
| }); |