# Publish a date-based release every time master moves. # # Versioning is date-based: vYYYY.MM.DD. Priority rule — an unreleased `version` # declared in custom_components/nvidia_shield/manifest.json wins (bump the # manifest to force a specific release, e.g. after a meaningful change); otherwise # the version is today's date (UTC), so a plain push to master publishes the # day's release. Repeated pushes on the same day are deduped by tag existence. # # The Gitea release carries a nvidia_shield.zip asset (custom_components/ # nvidia_shield/) so the integration is installable manually from any release. # # No hand-made secrets are required: Gitea mints a token for every job and # exposes it as secrets.GITEA_TOKEN. name: Release on: push: branches: [master] # Manual runs, for the first release (no tags yet) or to re-publish after a # partial failure. workflow_dispatch: # One release at a time. Two pushes in quick succession would otherwise race to # tag the same commit; a later run dedupes safely instead of interleaving. concurrency: group: release-master cancel-in-progress: false permissions: # The job token pushes the tag and creates the release. contents: write env: ZIP_NAME: nvidia_shield.zip jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: # Tags drive versioning decisions, so the clone must carry them. fetch-depth: 0 ref: master token: ${{ secrets.GITEA_TOKEN }} - name: Determine release version id: version run: | set -euo pipefail MANIFEST_VERSION="$(jq -r .version custom_components/nvidia_shield/manifest.json)" DATE_VERSION="$(date -u +%Y.%m.%d)" # An unreleased manifest version wins over today's date. if git rev-parse -q --verify "refs/tags/v${MANIFEST_VERSION}" >/dev/null; then VERSION="${DATE_VERSION}" else VERSION="${MANIFEST_VERSION}" fi echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" if git rev-parse -q --verify "refs/tags/v${VERSION}" >/dev/null; then echo "v${VERSION} is already tagged — nothing to release" echo "exists=yes" >> "$GITHUB_OUTPUT" else echo "releasing v${VERSION}" echo "exists=no" >> "$GITHUB_OUTPUT" fi - name: Create tag if: steps.version.outputs.exists == 'no' run: | set -euo pipefail git config user.name "gitea-actions" git config user.email "actions@notexpectedyet.com" git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}" git push origin "refs/tags/${{ steps.version.outputs.tag }}" - name: Build the release zip if: steps.version.outputs.exists == 'no' run: | set -euo pipefail cd custom_components zip -r "../${ZIP_NAME}" nvidia_shield - name: Publish the release if: steps.version.outputs.exists == 'no' env: VERSION: ${{ steps.version.outputs.version }} TAG: ${{ steps.version.outputs.tag }} SERVER: ${{ github.server_url }} REPO: ${{ github.repository }} TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail # Notes: subject lines of the commits in the released range. PREV="$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)" if [ -n "$PREV" ]; then RANGE="${PREV}..${TAG}" else RANGE="${TAG}" fi { echo "Release ${TAG}" echo git log --pretty=format:'- %s' "$RANGE" } > /tmp/notes.md # The body is built by an encoder rather than by string interpolation: # release notes are multi-line markdown and quoting them into JSON by # hand is a reliable way to publish a malformed release. python3 - <<'PY' > /tmp/release.json import json, os with open('/tmp/notes.md', encoding='utf-8') as handle: body = handle.read() print(json.dumps({ 'tag_name': 'v' + os.environ['VERSION'], 'name': 'v' + os.environ['VERSION'], 'body': body, 'draft': False, 'prerelease': False, })) PY status="$(curl -sS -o /tmp/release-response.json -w '%{http_code}' \ -X POST "${SERVER}/api/v1/repos/${REPO}/releases" \ -H "Authorization: token ${TOKEN}" \ -H 'Content-Type: application/json' \ --data-binary @/tmp/release.json)" RELEASE_ID="$(jq -r '.id // empty' /tmp/release-response.json)" # 409 is "a release for this tag already exists": resolve the existing # release instead of failing, so the zip still gets attached. if [ -z "$RELEASE_ID" ]; then RELEASE_ID="$(curl -sS "${SERVER}/api/v1/repos/${REPO}/releases/tags/${TAG}" \ -H "Authorization: token ${TOKEN}" | jq -r '.id')" else if [ "$status" != "201" ] && [ "$status" != "200" ]; then echo "release creation failed (HTTP ${status})" >&2 cat /tmp/release-response.json >&2 exit 1 fi fi case "$RELEASE_ID" in ''|*[!0-9]*) echo "could not resolve a release id for ${TAG} (HTTP ${status})" >&2 cat /tmp/release-response.json >&2 exit 1 ;; esac echo "release id: ${RELEASE_ID}" curl -sS -o /tmp/asset-response.json \ -X POST "${SERVER}/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \ -H "Authorization: token ${TOKEN}" \ -F "attachment=@${ZIP_NAME}" echo "published ${TAG} with ${ZIP_NAME}"