256 lines
9 KiB
YAML
256 lines
9 KiB
YAML
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
name: Build and publish app release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
SHARE_DIR: /ci-share/appstore-publish/${{ github.run_id }}-${{ github.run_attempt }}
|
|
|
|
jobs:
|
|
versions:
|
|
runs-on: selfhosted
|
|
container:
|
|
options: -v tmp:/ci-share
|
|
outputs:
|
|
php-min: ${{ steps.versions.outputs.php-min }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Validate app version against tag
|
|
run: |
|
|
VERSION="$(sed -n 's/^[[:space:]]*<version>\(.*\)<\/version>[[:space:]]*$/\1/p' appinfo/info.xml)"
|
|
echo "tag=${GITHUB_REF_NAME}"
|
|
echo "version=${VERSION}"
|
|
[ -n "${VERSION}" ] && [ "${GITHUB_REF_NAME}" = "v${VERSION}" ]
|
|
|
|
- name: Get version matrix
|
|
id: versions
|
|
uses: https://github.com/icewind1991/nextcloud-version-matrix@8a7bac6300b2f0f3100088b297995a229558ddba # v1.3.2
|
|
|
|
- name: Recreate share directory
|
|
run: |
|
|
rm -rf "$SHARE_DIR"
|
|
mkdir -p "$SHARE_DIR"
|
|
|
|
build-frontend:
|
|
needs: [versions]
|
|
runs-on: selfhosted
|
|
container:
|
|
image: node:24-bookworm
|
|
options: -v tmp:/ci-share
|
|
outputs:
|
|
build-hash: ${{ steps.share.outputs.build-hash }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Cache node_modules
|
|
id: node-modules-cache
|
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: node_modules
|
|
key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-node_modules-
|
|
|
|
- name: Install dependencies
|
|
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
|
env:
|
|
CYPRESS_INSTALL_BINARY: 0
|
|
PUPPETEER_SKIP_DOWNLOAD: true
|
|
run: npm ci
|
|
|
|
- name: Build
|
|
run: npm run build
|
|
|
|
- name: Share frontend build
|
|
id: share
|
|
run: |
|
|
tar -czf "$SHARE_DIR/frontend.tar.gz" js css
|
|
sha256sum "$SHARE_DIR/frontend.tar.gz" | tee "$SHARE_DIR/frontend.sha256"
|
|
echo "build-hash=$(cut -d' ' -f1 "$SHARE_DIR/frontend.sha256")" >> "$GITHUB_OUTPUT"
|
|
|
|
build-vendor:
|
|
needs: [versions]
|
|
runs-on: selfhosted
|
|
container:
|
|
image: docker.io/setupphp/node:php-${{ needs.versions.outputs.php-min }}-bookworm
|
|
options: -v tmp:/ci-share
|
|
outputs:
|
|
build-hash: ${{ steps.share.outputs.build-hash }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
|
|
- name: Restore composer binary
|
|
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
id: composer-bin-cache
|
|
with:
|
|
path: .ci-bin/composer
|
|
key: composer-2-${{ runner.os }}-php-${{ needs.versions.outputs.php-min }}-bookworm
|
|
|
|
- name: Install composer
|
|
if: steps.composer-bin-cache.outputs.cache-hit != 'true'
|
|
run: |
|
|
mkdir -p .ci-bin
|
|
curl -sS https://getcomposer.org/installer | php -- --install-dir=.ci-bin --filename=composer
|
|
|
|
- name: Save composer binary
|
|
if: steps.composer-bin-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
with:
|
|
path: .ci-bin/composer
|
|
key: ${{ steps.composer-bin-cache.outputs.cache-primary-key }}
|
|
|
|
- name: Add composer to PATH
|
|
run: |
|
|
chmod +x .ci-bin/composer
|
|
echo "$GITHUB_WORKSPACE/.ci-bin" >> "$GITHUB_PATH"
|
|
|
|
- name: Install composer dependencies
|
|
run: composer install --no-dev --prefer-dist
|
|
|
|
- name: Share vendor
|
|
id: share
|
|
run: |
|
|
tar -czf "$SHARE_DIR/vendor.tar.gz" vendor
|
|
sha256sum "$SHARE_DIR/vendor.tar.gz" | tee "$SHARE_DIR/vendor.sha256"
|
|
echo "build-hash=$(cut -d' ' -f1 "$SHARE_DIR/vendor.sha256")" >> "$GITHUB_OUTPUT"
|
|
|
|
build_and_publish:
|
|
needs: [versions, build-frontend, build-vendor]
|
|
runs-on: selfhosted
|
|
container:
|
|
image: node:24-bookworm
|
|
options: -v tmp:/ci-share
|
|
# Must match <id> in appinfo/info.xml (repo name is nextcloud-shortcuts).
|
|
# Job-level env is reliable on Forgejo; GITHUB_ENV may not feed ${{ env.* }} in later steps.
|
|
env:
|
|
APP_NAME: shortcuts
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
path: ${{ env.APP_NAME }}
|
|
|
|
- name: Restore and verify frontend build
|
|
run: |
|
|
EXPECTED='${{ needs.build-frontend.outputs.build-hash }}'
|
|
STORED="$(cut -d' ' -f1 "$SHARE_DIR/frontend.sha256")"
|
|
ACTUAL="$(sha256sum "$SHARE_DIR/frontend.tar.gz" | cut -d' ' -f1)"
|
|
echo "expected=$EXPECTED"
|
|
echo "stored=$STORED"
|
|
echo "actual=$ACTUAL"
|
|
[ "$ACTUAL" = "$EXPECTED" ] && [ "$STORED" = "$EXPECTED" ]
|
|
tar -xzf "$SHARE_DIR/frontend.tar.gz" -C "${{ env.APP_NAME }}"
|
|
|
|
- name: Restore and verify vendor
|
|
run: |
|
|
EXPECTED='${{ needs.build-vendor.outputs.build-hash }}'
|
|
STORED="$(cut -d' ' -f1 "$SHARE_DIR/vendor.sha256")"
|
|
ACTUAL="$(sha256sum "$SHARE_DIR/vendor.tar.gz" | cut -d' ' -f1)"
|
|
echo "expected=$EXPECTED"
|
|
echo "stored=$STORED"
|
|
echo "actual=$ACTUAL"
|
|
[ "$ACTUAL" = "$EXPECTED" ] && [ "$STORED" = "$EXPECTED" ]
|
|
tar -xzf "$SHARE_DIR/vendor.tar.gz" -C "${{ env.APP_NAME }}"
|
|
|
|
- name: Package ${{ env.APP_NAME }} ${{ github.ref_name }}
|
|
run: |
|
|
cd ${{ env.APP_NAME }}
|
|
mkdir -p build/artifacts
|
|
tar -czf "build/artifacts/${{ env.APP_NAME }}.tar.gz" \
|
|
--exclude='./build' \
|
|
--exclude='./.git' \
|
|
--exclude='./.github' \
|
|
--exclude='./scripts' \
|
|
--exclude='./node_modules' \
|
|
--exclude='./src' \
|
|
--exclude='./tests' \
|
|
--exclude='./vendor-bin' \
|
|
--exclude='./.php-cs-fixer*' \
|
|
--exclude='./package.json' \
|
|
--exclude='./package-lock.json' \
|
|
--exclude='./tsconfig.json' \
|
|
--exclude='./vite.config.ts' \
|
|
--exclude='./eslint.config.js' \
|
|
--exclude='./stylelint.config.cjs' \
|
|
--exclude='./psalm.xml' \
|
|
--exclude='./rector.php' \
|
|
--exclude='./renovate.json' \
|
|
--transform "s,^\./,${{ env.APP_NAME }}/," \
|
|
.
|
|
|
|
# Stage under the public asset name; forgejo-release uploads filenames as-is.
|
|
- name: Stage release asset
|
|
run: |
|
|
mkdir -p release-assets
|
|
cp "${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz" \
|
|
"release-assets/${{ env.APP_NAME }}-${{ github.ref_name }}.tar.gz"
|
|
|
|
- name: Extract latest changelog notes
|
|
run: |
|
|
"${{ env.APP_NAME }}/scripts/extract-latest-changelog.sh" \
|
|
"${{ env.APP_NAME }}/CHANGELOG.md" > release-notes.md
|
|
|
|
- name: Create release and upload tarball
|
|
uses: https://code.forgejo.org/actions/forgejo-release@98265452477dafb3f0f27ba9c462c90b18cb44fd # v2.13.4
|
|
with:
|
|
direction: upload
|
|
url: ${{ github.server_url }}
|
|
repo: ${{ github.repository }}
|
|
tag: ${{ github.ref_name }}
|
|
sha: ${{ github.sha }}
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
release-dir: release-assets
|
|
release-notes-file: release-notes.md
|
|
|
|
- name: Expose download URL
|
|
id: attach_to_release
|
|
run: |
|
|
DOWNLOAD_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/${APP_NAME}-${GITHUB_REF_NAME}.tar.gz"
|
|
echo "browser_download_url=${DOWNLOAD_URL}" >> "$GITHUB_OUTPUT"
|
|
echo "Download URL: ${DOWNLOAD_URL}"
|
|
|
|
# The push action needs openssl (sign); this image does not ship it.
|
|
- name: Install appstore push tools
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y --no-install-recommends openssl
|
|
|
|
- name: Upload app to Nextcloud appstore
|
|
uses: https://github.com/nextcloud-releases/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 }}
|
|
|
|
cleanup:
|
|
needs: [build-frontend, build-vendor, build_and_publish]
|
|
if: always()
|
|
runs-on: selfhosted
|
|
container:
|
|
image: node:24-bookworm
|
|
options: -v tmp:/ci-share
|
|
steps:
|
|
- name: Remove shared build output
|
|
run: rm -rf "$SHARE_DIR"
|