diff --git a/.github/workflows/appstore-build-publish.yml b/.github/workflows/appstore-build-publish.yml new file mode 100644 index 0000000..378744b --- /dev/null +++ b/.github/workflows/appstore-build-publish.yml @@ -0,0 +1,206 @@ +# Based on the organization template repository, adapted for community apps +# (no nextcloud-releases owner check). +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2021-2026 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: Build and publish app release + +on: + release: + types: [published] + +permissions: + contents: write + +env: + # Must match appinfo/info.xml and the certificate folder name in + # nextcloud/app-certificate-requests (not necessarily the GitHub repo name). + APP_NAME: app_template + +jobs: + build_and_publish: + environment: release + runs-on: ubuntu-latest + + steps: + - name: Check actor permission + uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0 + with: + require: write + + - name: Set app env + run: 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: nextcloud-libraries/parse-package-engines-action@39fcc545a815c353dd0a3fd8fd2ef6e59fd02b92 # v0.2.0 + id: versions + # Continue if no package.json + continue-on-error: true + with: + path: ${{ env.APP_NAME }}/package.json + + - name: Set up node ${{ steps.versions.outputs.node-version }} + # Skip if no package.json + if: ${{ steps.versions.outcome == 'success' }} + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: ${{ steps.versions.outputs.node-version }} + package-manager-cache: false + + - name: Set up npm ${{ steps.versions.outputs.package-manager-version }} + # Skip if no package.json + if: ${{ steps.versions.outcome == 'success' }} + run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}' + + - 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@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # 2.40.0 + 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.outcome == 'success' }} + 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 }} + nightly: ${{ github.event.release.prerelease }} + + - name: Delete crt and key from local storage + if: always() + run: rm -f ${{ env.APP_NAME }}.key ${{ env.APP_NAME }}.crt diff --git a/.gitignore b/.gitignore index 6f41dd1..887506a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /node_modules/ /js/ /css/ +/build/ diff --git a/.nextcloudignore b/.nextcloudignore new file mode 100644 index 0000000..72e3fcf --- /dev/null +++ b/.nextcloudignore @@ -0,0 +1,27 @@ +.git +.github +.gitignore +.tx +.vscode +.php-cs-fixer.* +/.eslintrc.cjs +/.gitignore +/.nextcloudignore +/.nvmrc +/build +/CODE_OF_CONDUCT.md +/composer.* +/node_modules +/src +/tests +/krankerl.toml +/package-lock.json +/package.json +/psalm.xml +/rector.php +/stylelint.config.cjs +/tsconfig.json +/vite.config.ts +/vendor-bin +/vendor/bin +/*.md diff --git a/README.md b/README.md index 073c8a3..5d04cad 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,13 @@ A template to get started with Nextcloud app development. this repository. Afterwards adjust all the necessary constants like App ID, namespace, descriptions etc. Once your app is ready follow the [instructions](https://nextcloudappstore.readthedocs.io/en/latest/developer.html) to -upload it to the Appstore. +upload it to the Appstore, or use the release workflow below. + +## Releasing to the App Store automatically + +Publishing a GitHub release (tag `v` + the version in `appinfo/info.xml`, e.g. `v1.0.0`) runs +[`.github/workflows/appstore-build-publish.yml`](.github/workflows/appstore-build-publish.yml). +This will build the app and publish it to the App Store automatically after being setup. See the [release automation docs](https://docs.nextcloud.com/server/latest/developer_manual/app_publishing_maintenance/release_automation.html) for details. ## Resources diff --git a/krankerl.toml b/krankerl.toml new file mode 100644 index 0000000..77f1e61 --- /dev/null +++ b/krankerl.toml @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: AGPL-3.0-or-later +[package] +before_cmds = [ + "npm ci", + "npm run build", + "composer install --no-dev -a", +] diff --git a/vite.config.ts b/vite.config.ts index b235048..dc7e9a3 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,7 +3,7 @@ import { join, resolve } from 'path' export default createAppConfig( { - main: resolve(join('src', 'main.js')), + main: resolve(join('src', 'main.ts')), }, { createEmptyCSSEntryPoints: true,