diff --git a/.github/workflows/release-sync-manifest-version.yml b/.github/workflows/release-sync-manifest-version.yml deleted file mode 100644 index 90f647a..0000000 --- a/.github/workflows/release-sync-manifest-version.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Sync manifest version on release - -on: - release: - types: [published] - -permissions: - contents: write - -jobs: - update-manifest: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.repository.default_branch }} - - - name: Update manifest version - env: - MANIFEST_VERSION: ${{ github.event.release.tag_name }} - run: | - python3 << 'PY' - import json - import os - from pathlib import Path - - raw = os.environ["MANIFEST_VERSION"] - version = raw[1:] if raw.startswith("v") else raw - - path = Path("custom_components/android_management_api/manifest.json") - with path.open(encoding="utf-8") as f: - data = json.load(f) - data["version"] = version - text = json.dumps(data, indent=2, ensure_ascii=False) + "\n" - path.write_text(text, encoding="utf-8") - PY - - - name: Commit and push - env: - TAG_NAME: ${{ github.event.release.tag_name }} - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add custom_components/android_management_api/manifest.json - if git diff --staged --quiet; then - echo "Manifest version already matches release; nothing to commit." - exit 0 - fi - git commit -m "chore: sync manifest version to release ${TAG_NAME}" - git push diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..ee57f1d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,125 @@ +name: Create release + +on: + workflow_dispatch: + inputs: + version: + description: Semver (e.g. 0.2.0). A leading v is optional. + required: true + type: string + draft: + description: Create as draft release + required: false + type: boolean + default: false + prerelease: + description: Mark as prerelease + required: false + type: boolean + default: false + release_notes: + description: Release notes (optional). If empty, GitHub generates notes from commits. + required: false + type: string + default: "" + +permissions: + contents: write + pull-requests: write + +jobs: + normalize: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.meta.outputs.version }} + tag: ${{ steps.meta.outputs.tag }} + branch: ${{ steps.meta.outputs.branch }} + steps: + - id: meta + env: + RAW: ${{ github.event.inputs.version }} + run: | + set -euo pipefail + VERSION="${RAW#v}" + if [ -z "$VERSION" ]; then + echo "::error::version is empty" + exit 1 + fi + if [[ "$VERSION" == *"/"* ]]; then + echo "::error::version must not contain /" + exit 1 + fi + TAG="v${VERSION}" + BRANCH="release/${TAG}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "branch=${BRANCH}" >> "$GITHUB_OUTPUT" + + release: + needs: normalize + runs-on: ubuntu-latest + concurrency: + group: create-release-${{ github.repository }}-${{ needs.normalize.outputs.version }} + cancel-in-progress: false + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.repository.default_branch }} + fetch-depth: 0 + + - name: Bump manifest, push release branch, publish release, open PR + env: + GH_TOKEN: ${{ github.token }} + VERSION: ${{ needs.normalize.outputs.version }} + TAG: ${{ needs.normalize.outputs.tag }} + BRANCH: ${{ needs.normalize.outputs.branch }} + INPUT_DRAFT: ${{ github.event.inputs.draft }} + INPUT_PRERELEASE: ${{ github.event.inputs.prerelease }} + RELEASE_NOTES: ${{ github.event.inputs.release_notes }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + run: | + set -euo pipefail + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout -b "$BRANCH" + + export MANIFEST_VERSION="$VERSION" + python3 << 'PY' + import json + import os + from pathlib import Path + + version = os.environ["MANIFEST_VERSION"] + path = Path("custom_components/android_management_api/manifest.json") + with path.open(encoding="utf-8") as f: + data = json.load(f) + data["version"] = version + text = json.dumps(data, indent=2, ensure_ascii=False) + "\n" + path.write_text(text, encoding="utf-8") + PY + + git add custom_components/android_management_api/manifest.json + if git diff --staged --quiet; then + echo "::error::Manifest already at ${VERSION}; nothing to commit." + exit 1 + fi + git commit -m "chore: bump manifest to ${VERSION} for ${TAG}" + git push -u origin "$BRANCH" + + EXTRA=( ) + if [ "$INPUT_DRAFT" = "true" ]; then EXTRA+=(--draft); fi + if [ "$INPUT_PRERELEASE" = "true" ]; then EXTRA+=(--prerelease); fi + + if [ -n "$RELEASE_NOTES" ]; then + printf '%s\n' "$RELEASE_NOTES" > /tmp/release-notes.md + gh release create "$TAG" --target "$BRANCH" --title "$TAG" -F /tmp/release-notes.md "${EXTRA[@]}" + else + gh release create "$TAG" --target "$BRANCH" --title "$TAG" --generate-notes "${EXTRA[@]}" + fi + + gh pr create \ + --base "$DEFAULT_BRANCH" \ + --head "$BRANCH" \ + --title "Merge ${TAG} manifest bump" \ + --body "Automated manifest bump for [${TAG}](https://github.com/${{ github.repository }}/releases/tag/${TAG}). Merge after checks pass so \`${DEFAULT_BRANCH}\` matches the release."