Add native Home Assistant (HACS) integration #19
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: Validate Integration | |
| on: | |
| push: | |
| branches: ["main", "develop"] | |
| pull_request: | |
| schedule: | |
| - cron: "0 6 * * *" | |
| permissions: {} | |
| jobs: | |
| hacs: | |
| name: HACS validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: HACS Action | |
| uses: hacs/action@main | |
| with: | |
| category: integration | |
| # `brands` (home-assistant/brands icon) and `topics` (GitHub repo | |
| # topics) are repo-admin/external prerequisites tracked separately; | |
| # ignore them so this job reflects the integration's own validity. | |
| # Add topics (home-assistant, hacs, marstek, energy) + the brands PR | |
| # before submitting to the HACS default store. | |
| ignore: brands topics | |
| hassfest: | |
| name: Hassfest validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| - name: Vendor the astrameter package into the integration | |
| run: python3 scripts/assemble_integration.py --vendor-only | |
| - name: Hassfest | |
| uses: home-assistant/actions/hassfest@master | |
| package: | |
| name: Build installable artifact | |
| runs-on: ubuntu-latest | |
| # Needed to post/update the install-links comment on pull requests. | |
| permissions: | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.13" | |
| # Assemble the integration the same way a release does, but stamp an | |
| # identifiable pre-release version (the patch bump + this run number) so a | |
| # manually installed PR build is distinguishable from a real release. | |
| - name: Assemble astrameter.zip | |
| id: assemble | |
| run: | | |
| VERSION="$(python scripts/assemble_integration.py --print-beta-version "${{ github.run_number }}")" | |
| python scripts/assemble_integration.py --version "$VERSION" --output dist/astrameter.zip | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Built astrameter $VERSION" | |
| # The folder artifact extracts straight into config/custom_components/astrameter/. | |
| - name: Upload custom_components/astrameter (drop into your HA config) | |
| id: upload_folder | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: astrameter-custom-component | |
| path: dist/astrameter/ | |
| if-no-files-found: error | |
| # The zip artifact is the exact asset HACS installs (zip-of-zip on download). | |
| - name: Upload astrameter.zip (HACS-shaped release asset) | |
| id: upload_zip | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: astrameter-zip | |
| path: dist/astrameter.zip | |
| if-no-files-found: error | |
| # Post a single sticky comment with the download links and refresh it on | |
| # every rebuild (found by the hidden marker) instead of spamming the PR. | |
| # Skipped for fork PRs, whose GITHUB_TOKEN is read-only. | |
| - name: Comment install links on the PR | |
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const marker = '<!-- astrameter-build-artifact -->'; | |
| const version = ${{ toJSON(steps.assemble.outputs.version) }}; | |
| const folderUrl = ${{ toJSON(steps.upload_folder.outputs['artifact-url']) }}; | |
| const zipUrl = ${{ toJSON(steps.upload_zip.outputs['artifact-url']) }}; | |
| const sha = context.payload.pull_request.head.sha.slice(0, 7); | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const body = [ | |
| marker, | |
| `### 📦 Installable build for this PR`, | |
| ``, | |
| `Built **astrameter \`${version}\`** from \`${sha}\` ([run](${runUrl})). ` + | |
| `Install this branch manually — no release needed:`, | |
| ``, | |
| `- **[\`astrameter-custom-component\`](${folderUrl})** — unzip into ` + | |
| `\`config/custom_components/astrameter/\` (HA Container/Core), then restart HA.`, | |
| `- **[\`astrameter-zip\`](${zipUrl})** — the HACS-shaped release asset ` + | |
| `(GitHub wraps it, so it downloads as a zip-of-zip).`, | |
| ``, | |
| `<sub>Downloading a workflow artifact requires being signed in to GitHub. ` + | |
| `Artifacts expire after 90 days. This comment updates on every push.</sub>`, | |
| ].join('\n'); | |
| const { owner, repo } = context.repo; | |
| const issue_number = context.issue.number; | |
| const comments = await github.paginate(github.rest.issues.listComments, { | |
| owner, repo, issue_number, | |
| }); | |
| const existing = comments.find((c) => c.body && c.body.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner, repo, comment_id: existing.id, body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ owner, repo, issue_number, body }); | |
| } |