diff --git a/actions/nextcloud-appstore-publish/action.yml b/actions/nextcloud-appstore-publish/action.yml index 70c3add..c37fa13 100644 --- a/actions/nextcloud-appstore-publish/action.yml +++ b/actions/nextcloud-appstore-publish/action.yml @@ -41,10 +41,19 @@ runs: using: composite steps: - name: Check actor permission - uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0 - with: - require: write - token: ${{ inputs.github-token }} + shell: bash + env: + GH_TOKEN: ${{ inputs.github-token }} + run: | + set -euo pipefail + permission="$(gh api "repos/${GITHUB_REPOSITORY}/collaborators/${GITHUB_ACTOR}/permission" --jq '.permission')" + case "${permission}" in + admin|maintain|write) ;; + *) + echo "::error::${GITHUB_ACTOR} has ${permission} permission; write is required." + exit 1 + ;; + esac - name: Validate boolean inputs shell: bash @@ -77,26 +86,57 @@ runs: - name: Validate release identity id: release_identity - uses: LibreCodeCoop/release-tool/actions/release-identity@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/release-identity@5524b80559174b15be15afd33da2fbca2980a53c with: tag: ${{ inputs.release-tag }} working-directory: ${{ inputs.app-name }} require-tag-exists: 'true' - - name: Get appinfo data + - name: Read appinfo compatibility id: appinfo - uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # v1.0.0 - with: - filename: ${{ inputs.app-name }}/appinfo/info.xml - expression: "//info//dependencies//nextcloud/@min-version" + shell: bash + env: + APP_NAME: ${{ inputs.app-name }} + run: | + set -euo pipefail + result="$(python3 - "${APP_NAME}/appinfo/info.xml" <<'PY' + import json + import sys + import xml.etree.ElementTree as ET + + root = ET.parse(sys.argv[1]).getroot() + nextcloud = root.find("./dependencies/nextcloud") + if nextcloud is None: + raise SystemExit("appinfo/info.xml has no dependencies/nextcloud element") + minimum = nextcloud.get("min-version") + if not minimum: + raise SystemExit("appinfo/info.xml has no Nextcloud min-version") + print(json.dumps({"nextcloud": {"min-version": minimum}}, separators=(",", ":"))) + PY + )" + printf 'result=%s\n' "${result}" >> "${GITHUB_OUTPUT}" - name: Read package engines id: versions - continue-on-error: true - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - with: - path: ${{ inputs.app-name }} - fallbackNode: '^24' + shell: bash + env: + APP_NAME: ${{ inputs.app-name }} + run: | + set -euo pipefail + node_version="$(python3 - "${APP_NAME}/package.json" <<'PY' + import json + import pathlib + import sys + + path = pathlib.Path(sys.argv[1]) + if not path.is_file(): + print("^24") + raise SystemExit(0) + package = json.loads(path.read_text()) + print(package.get("engines", {}).get("node") or "^24") + PY + )" + printf 'nodeVersion=%s\n' "${node_version}" >> "${GITHUB_OUTPUT" - name: Set up node if: ${{ steps.versions.outputs.nodeVersion }} @@ -271,7 +311,7 @@ runs: GITHUB_TOKEN: ${{ inputs.github-token }} - name: Validate release artifact - uses: LibreCodeCoop/release-tool/actions/artifact-validate@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/artifact-validate@5524b80559174b15be15afd33da2fbca2980a53c with: artifact: ${{ inputs.app-name }}/build/artifacts/${{ inputs.app-name }}.tar.gz app-name: ${{ inputs.app-name }} @@ -300,7 +340,7 @@ runs: app_private_key: ${{ inputs.app-private-key }} - name: Verify App Store publication - uses: LibreCodeCoop/release-tool/actions/appstore-publication-wait@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/appstore-publication-wait@5524b80559174b15be15afd33da2fbca2980a53c with: app-name: ${{ inputs.app-name }} version: ${{ steps.release_identity.outputs.version }} diff --git a/tests/test_release_tool_pins.py b/tests/test_release_tool_pins.py index 2cdd1c7..8a13fbd 100644 --- a/tests/test_release_tool_pins.py +++ b/tests/test_release_tool_pins.py @@ -7,7 +7,7 @@ ROOT = Path(__file__).resolve().parents[1] -RELEASE_TOOL_RELEASE_SHA = "9b33a67a7b1e37a45b0a3c252370899effcdfdc2" +RELEASE_TOOL_RELEASE_SHA = "5524b80559174b15be15afd33da2fbca2980a53c" SURFACES = ( ROOT / "workflow-templates/prepare-release.yml", ROOT / "workflow-templates/nightly-release.yml", diff --git a/workflow-templates/nightly-release.yml b/workflow-templates/nightly-release.yml index 3194647..039c8ad 100644 --- a/workflow-templates/nightly-release.yml +++ b/workflow-templates/nightly-release.yml @@ -4,14 +4,8 @@ name: Nightly release on: - push: - branches: - - 'stable*' - paths: - - '**' - - '!**.md' - - '!.github/**' - - '.github/workflows/nightly-release.yml' + schedule: + - cron: '17 3 * * *' workflow_dispatch: permissions: @@ -19,12 +13,12 @@ permissions: pull-requests: read concurrency: - group: nightly-release-${{ github.repository }}-${{ github.ref_name }} + group: nightly-release-${{ github.repository }} cancel-in-progress: true jobs: - check-latest-stable: - name: Check latest stable + resolve-latest-stable: + name: Resolve latest stable runs-on: ubuntu-latest outputs: is-latest: ${{ steps.stable.outputs.is-latest }} @@ -35,63 +29,84 @@ jobs: steps: - id: stable name: Resolve stable release line - uses: LibreCodeCoop/release-tool/actions/stable-select@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/stable-select@5524b80559174b15be15afd33da2fbca2980a53c with: github-token: ${{ github.token }} nightly-release: name: Build and publish nightly - needs: check-latest-stable - if: needs.check-latest-stable.outputs.is-latest == 'true' + needs: resolve-latest-stable runs-on: ubuntu-latest timeout-minutes: 30 steps: - - name: Check actor permission - uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0 - with: - require: write - - name: Set app environment shell: bash run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> "${GITHUB_ENV}" - - name: Checkout + - name: Checkout latest stable uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false fetch-depth: 0 submodules: true + ref: ${{ needs.resolve-latest-stable.outputs.latest-branch }} path: ${{ env.APP_NAME }} - - name: Get app version number - id: app-version - uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # v1.0.0 - with: - filename: ${{ env.APP_NAME }}/appinfo/info.xml - expression: "//info//version/text()" + - name: Resolve checked out commit + id: source + working-directory: ${{ env.APP_NAME }} + shell: bash + run: echo "sha=$(git rev-parse HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Read app metadata + id: appinfo + shell: bash + env: + APP_NAME: ${{ env.APP_NAME }} + run: | + set -euo pipefail + python3 - "${APP_NAME}/appinfo/info.xml" "${GITHUB_OUTPUT}" <<'PY' + import sys + import xml.etree.ElementTree as ET + + root = ET.parse(sys.argv[1]).getroot() + version = root.findtext("version") + nextcloud = root.find("./dependencies/nextcloud") + minimum = None if nextcloud is None else nextcloud.get("min-version") + if not version or not minimum: + raise SystemExit("appinfo/info.xml is missing version or Nextcloud min-version") + with open(sys.argv[2], "a", encoding="utf-8") as output: + output.write(f"version={version}\n") + output.write(f"nextcloud_min={minimum}\n") + PY - name: Set app version shell: bash env: - APP_VERSION: ${{ fromJSON(steps.app-version.outputs.result).version }} + APP_VERSION: ${{ steps.appinfo.outputs.version }} run: echo "APP_VERSION=${APP_VERSION}" >> "${GITHUB_ENV}" - - name: Get appinfo data - id: appinfo - uses: skjnldsv/xpath-action@f5b036e9d973f42c86324833fd00be90665fbf77 # v1.0.0 - with: - filename: ${{ env.APP_NAME }}/appinfo/info.xml - expression: "//info//dependencies//nextcloud/@min-version" - - name: Read package.json node and npm engines version id: versions - uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 - continue-on-error: true - with: - path: ${{ env.APP_NAME }} - fallbackNode: '^24' - fallbackNpm: '^11.3' + shell: bash + env: + APP_NAME: ${{ env.APP_NAME }} + run: | + set -euo pipefail + python3 - "${APP_NAME}/package.json" "${GITHUB_OUTPUT}" <<'PY' + import json + import pathlib + import sys + + path = pathlib.Path(sys.argv[1]) + engines = {} + if path.is_file(): + engines = json.loads(path.read_text()).get("engines", {}) + with open(sys.argv[2], "a", encoding="utf-8") as output: + output.write(f"nodeVersion={engines.get('node') or '^24'}\n") + output.write(f"npmVersion={engines.get('npm') or '^11.3'}\n") + PY - name: Set up node ${{ steps.versions.outputs.nodeVersion }} if: steps.versions.outputs.nodeVersion @@ -168,7 +183,7 @@ jobs: continue-on-error: true shell: bash env: - NEXTCLOUD_VERSION: ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }} + NEXTCLOUD_VERSION: ${{ steps.appinfo.outputs.nextcloud_min }} run: | download_url="$(curl -fsSL "https://updates.nextcloud.com/updater_server/latest?channel=beta&version=${NEXTCLOUD_VERSION}" | jq -r '.downloads.zip[0]')" test -n "${download_url}" && test "${download_url}" != "null" @@ -215,7 +230,7 @@ jobs: tar -zcf "${APP_NAME}.tar.gz" "${APP_NAME}" - name: Validate release artifact - uses: LibreCodeCoop/release-tool/actions/artifact-validate@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/artifact-validate@5524b80559174b15be15afd33da2fbca2980a53c with: artifact: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz app-name: ${{ env.APP_NAME }} @@ -226,7 +241,7 @@ jobs: shell: bash run: | echo "tag=nightly" >> "${GITHUB_OUTPUT}" - echo "branch=${{ needs.check-latest-stable.outputs.current-branch }}" >> "${GITHUB_OUTPUT}" + echo "branch=${{ needs.resolve-latest-stable.outputs.latest-branch }}" >> "${GITHUB_OUTPUT}" - name: Move nightly tag to this commit shell: bash @@ -234,14 +249,14 @@ jobs: GH_TOKEN: ${{ github.token }} run: | if gh api "repos/${GITHUB_REPOSITORY}/git/ref/tags/nightly" >/dev/null 2>&1; then - gh api --method PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/nightly" -f sha="${GITHUB_SHA}" -F force=true >/dev/null + gh api --method PATCH "repos/${GITHUB_REPOSITORY}/git/refs/tags/nightly" -f sha="${{ steps.source.outputs.sha }}" -F force=true >/dev/null else - gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" -f ref='refs/tags/nightly' -f sha="${GITHUB_SHA}" >/dev/null + gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" -f ref='refs/tags/nightly' -f sha="${{ steps.source.outputs.sha }}" >/dev/null fi - name: Build nightly change list id: release-note-changes - uses: LibreCodeCoop/release-tool/actions/release-notes@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/release-notes@5524b80559174b15be15afd33da2fbca2980a53c with: repository: ${{ github.repository }} branch: ${{ steps.nightly.outputs.branch }} @@ -267,7 +282,8 @@ jobs: cat "${CHANGES_FILE}" echo echo "---" - printf 'Generated from commit `%s`.\n' "${GITHUB_SHA:0:7}" + source_sha='${{ steps.source.outputs.sha }}' + printf 'Generated from commit `%s`.\n' "${source_sha:0:7}" } > release-notes.md - name: Create or update GitHub release diff --git a/workflow-templates/prepare-release.yml b/workflow-templates/prepare-release.yml index da96674..6594171 100644 --- a/workflow-templates/prepare-release.yml +++ b/workflow-templates/prepare-release.yml @@ -45,6 +45,8 @@ on: type: boolean pull_request_target: types: [closed] + paths-ignore: + - 'docs/changelogs/**' release: types: [published] @@ -87,7 +89,7 @@ jobs: git fetch --quiet origin "+refs/heads/main:refs/remotes/origin/main" - name: Prepare release - uses: LibreCodeCoop/release-tool/actions/prepare@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/prepare@5524b80559174b15be15afd33da2fbca2980a53c with: branch: ${{ inputs.branch }} ref: ${{ inputs.ref }} @@ -132,7 +134,7 @@ jobs: git fetch --quiet --unshallow --prune origin "+refs/heads/${RELEASE_BRANCH}:refs/remotes/origin/${RELEASE_BRANCH}" "+refs/tags/*:refs/tags/*" - name: Finalize merged release - uses: LibreCodeCoop/release-tool/actions/post-merge@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/post-merge@5524b80559174b15be15afd33da2fbca2980a53c with: pull-request-number: ${{ github.event.pull_request.number }} merger: ${{ github.event.pull_request.merged_by.login }} @@ -158,7 +160,7 @@ jobs: ref: ${{ github.event.release.tag_name }} - name: Verify publication - uses: LibreCodeCoop/release-tool/actions/publication@9b33a67a7b1e37a45b0a3c252370899effcdfdc2 + uses: LibreCodeCoop/release-tool/actions/publication@5524b80559174b15be15afd33da2fbca2980a53c with: github-release-id: ${{ github.event.release.id }} config-path: .nextcloud-release.yml