Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 231 additions & 50 deletions patches/nextcloud/appstore-build-publish.yml.patch
Original file line number Diff line number Diff line change
@@ -1,60 +1,241 @@
--- upstream/vendor/nextcloud/appstore-build-publish.yml
+++ workflow-templates/appstore-build-publish.yml
@@ -1,6 +1,6 @@
# This workflow is provided via the organization template repository
#
+# https://github.com/LibreCodeCoop/.github
@@ -1,202 +1,36 @@
-# This workflow is provided via the organization template repository
-#
-# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
@@ -19,9 +19,6 @@
build_and_publish:
runs-on: ubuntu-latest

-# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
-#
-# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
-# SPDX-License-Identifier: MIT
-
-name: Build and publish app release
-
-on:
- release:
- types: [published]
-
-permissions:
- contents: write
-
-jobs:
- build_and_publish:
- runs-on: ubuntu-latest
-
- # Only allowed to be run on nextcloud-releases repositories
- if: ${{ github.repository_owner == 'nextcloud-releases' }}
-
steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0
@@ -143,6 +140,14 @@
cd ${{ env.APP_NAME }}
make appstore

+ - name: Verify app store package
+ if: steps.krankerl.outputs.files_exists != 'true'
+ working-directory: ${{ env.APP_NAME }}
+ run: |
+ if make -qp 2>/dev/null | grep -q '^verify-appstore-package:'; then
+ make verify-appstore-package
+ fi
- steps:
- - name: Check actor permission
- uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0
- with:
- require: write
-
- - name: Set app env
- run: |
- # Split and keep last
- echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
- echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
-
- - name: Checkout
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- with:
- persist-credentials: false
- 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: Validate app version against tag
- run: |
- [ "${{ env.APP_VERSION }}" = "v${{ fromJSON(steps.app-version.outputs.result).version }}" ]
-
- - 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
- uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
- id: versions
- # Continue if no package.json
- continue-on-error: true
- with:
- path: ${{ env.APP_NAME }}
- fallbackNode: '^24'
- fallbackNpm: '^11.3'
-
- - name: Set up node ${{ steps.versions.outputs.nodeVersion }}
- # Skip if no package.json
- if: ${{ steps.versions.outputs.nodeVersion }}
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
- with:
- node-version: ${{ steps.versions.outputs.nodeVersion }}
- package-manager-cache: false
-
- - name: Set up npm ${{ steps.versions.outputs.npmVersion }}
- # Skip if no package.json
- if: ${{ steps.versions.outputs.npmVersion }}
- run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
-
- - name: Get php version
- id: php-versions
- uses: nextcloud-libraries/nextcloud-version-matrix@cd0211ffcef1065e2020cd579e4843b8746e7a58 # v1.3.3
- with:
- filename: ${{ env.APP_NAME }}/appinfo/info.xml
-
- - name: Set up php ${{ steps.php-versions.outputs.php-min }}
- uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
- with:
- php-version: ${{ steps.php-versions.outputs.php-min }}
- coverage: none
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Check composer.json
- id: check_composer
- uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0
- with:
- files: "${{ env.APP_NAME }}/composer.json"
-
- - name: Install composer dependencies
- if: steps.check_composer.outputs.files_exists == 'true'
- uses: ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda # 4.0.0
- with:
- composer-options: '--no-dev'
- working-directory: ${{ env.APP_NAME }}
- ignore-cache: 'yes'
-
- - name: Build ${{ env.APP_NAME }}
- # Skip if no package.json
- if: ${{ steps.versions.outputs.nodeVersion }}
- env:
- CYPRESS_INSTALL_BINARY: 0
- run: |
- cd ${{ env.APP_NAME }}
- npm ci
- npm run build --if-present
-
- - name: Check Krankerl config
- id: krankerl
- uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0
- with:
- files: ${{ env.APP_NAME }}/krankerl.toml
-
- - name: Install Krankerl
- if: steps.krankerl.outputs.files_exists == 'true'
- run: |
- wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
- sudo dpkg -i krankerl_0.14.0_amd64.deb
-
- - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl
- if: steps.krankerl.outputs.files_exists == 'true'
- run: |
- cd ${{ env.APP_NAME }}
- krankerl package
-
- - name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile
- if: steps.krankerl.outputs.files_exists != 'true'
- run: |
- cd ${{ env.APP_NAME }}
- make appstore
-
- - name: Check server download link for ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
- run: |
- NCVERSION='${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}'
- DOWNLOAD_URL=$(curl -s "https://updates.nextcloud.com/updater_server/latest?channel=beta&version=$NCVERSION" | jq -r '.downloads.zip[0]')
- echo "DOWNLOAD_URL=$DOWNLOAD_URL" >> $GITHUB_ENV
-
- - name: Download server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
- continue-on-error: true
- id: server-download
- if: ${{ env.DOWNLOAD_URL != 'null' }}
- run: |
- echo "Downloading release tarball from $DOWNLOAD_URL"
- wget $DOWNLOAD_URL -O nextcloud.zip
- unzip nextcloud.zip
-
- - name: Checkout server master fallback
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- if: ${{ steps.server-download.outcome != 'success' }}
- with:
- persist-credentials: false
- submodules: true
- repository: nextcloud/server
- path: nextcloud
-
-
- - name: Sign app
- run: |
- # Extracting release
- cd ${{ env.APP_NAME }}/build/artifacts
- tar -xvf ${{ env.APP_NAME }}.tar.gz
- cd ../../../
- # Setting up keys
- echo '${{ secrets.APP_PRIVATE_KEY }}' > ${{ env.APP_NAME }}.key
- wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt"
- # Signing
- php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}
- # Rebuilding archive
- cd ${{ env.APP_NAME }}/build/artifacts
- tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
-
- - name: Attach tarball to github release
- uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # 2.11.5
- id: attach_to_release
- with:
- repo_token: ${{ secrets.GITHUB_TOKEN }}
- file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
- asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz
- tag: ${{ github.ref }}
- overwrite: true
-
- - name: Upload app to Nextcloud appstore
- uses: nextcloud-libraries/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1.0.3
- with:
- app_name: ${{ env.APP_NAME }}
- appstore_token: ${{ secrets.APPSTORE_TOKEN }}
- download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
- app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
+# This workflow is provided via the organization template repository
+#
+# https://github.com/LibreCodeCoop/.github
+# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
+#
+# SPDX-FileCopyrightText: 2021-2026 Nextcloud GmbH, LibreCode coop and contributors
+# SPDX-License-Identifier: MIT
+
- name: Check server download link for ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
run: |
NCVERSION='${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}'
@@ -183,6 +188,13 @@
cd ${{ env.APP_NAME }}/build/artifacts
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}

+ - name: Validate release artifact
+ uses: LibreCodeCoop/release-tool/actions/artifact-validate@710c4c83fba47bf01713f46e9c4cb4cf63debfba
+ with:
+ artifact: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
+ app-name: ${{ env.APP_NAME }}
+ version: ${{ env.APP_VERSION }}
+name: Build and publish app release
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+ inputs:
+ release_tag:
+ description: Existing release tag to build and publish.
+ required: true
+ type: string
+
- name: Attach tarball to github release
uses: svenstaro/upload-release-action@29e53e917877a24fad85510ded594ab3c9ca12de # 2.11.5
id: attach_to_release
@@ -200,3 +212,10 @@
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
+permissions:
+ contents: write
+
+ - name: Verify App Store publication
+ uses: LibreCodeCoop/release-tool/actions/appstore-publication-wait@710c4c83fba47bf01713f46e9c4cb4cf63debfba
+jobs:
+ build_and_publish:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build and publish release
+ uses: LibreCodeCoop/.github/actions/nextcloud-appstore-publish@748b0416ea5b734292671dd0feec33aaf8ec6b82
+ with:
+ app-name: ${{ env.APP_NAME }}
+ version: ${{ env.APP_VERSION }}
+ platform: ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
+ app-name: ${{ github.event.repository.name }}
+ release-tag: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.event.release.tag_name }}
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ app-private-key: ${{ secrets.APP_PRIVATE_KEY }}
+ appstore-token: ${{ secrets.APPSTORE_TOKEN }}
+ manual-recovery: ${{ github.event_name == 'workflow_dispatch' }}
7 changes: 7 additions & 0 deletions tests/test_appstore_publication_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@

ROOT = Path(__file__).resolve().parents[1]
ACTION = ROOT / "actions/nextcloud-appstore-publish/action.yml"
TEMPLATE = ROOT / "workflow-templates/appstore-build-publish.yml"


class AppStorePublicationContractTest(unittest.TestCase):
def test_consumer_template_is_thin_wrapper(self) -> None:
content = TEMPLATE.read_text(encoding="utf-8")
self.assertIn("LibreCodeCoop/.github/actions/nextcloud-appstore-publish@748b0416ea5b734292671dd0feec33aaf8ec6b82", content)
self.assertNotIn("\n run: |", content)
self.assertLessEqual(len(content.splitlines()), 40)

def test_external_actions_are_immutable(self) -> None:
content = ACTION.read_text(encoding="utf-8")
revisions = re.findall(r"^\s*uses:\s*([^@\s]+)@([^\s#]+)", content, re.MULTILINE)
Expand Down
Loading
Loading