diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml new file mode 100644 index 0000000..20b23cd --- /dev/null +++ b/.github/workflows/test-deploy.yml @@ -0,0 +1,134 @@ +# SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT +name: Test Deploy + +on: + pull_request: + branches: [main] + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: tests-deploy-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + nc-host-app-docker: + runs-on: ubuntu-22.04 + name: NC In Host + + services: + postgres: + image: ghcr.io/nextcloud/continuous-integration-postgres-14:latest + ports: + - 4444:5432/tcp + env: + POSTGRES_USER: root + POSTGRES_PASSWORD: rootpassword + POSTGRES_DB: nextcloud + options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5 + + steps: + - name: Set app env + run: echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV + + - name: Checkout server + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + submodules: true + repository: nextcloud/server + ref: master + + - name: Checkout Test Deploy + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + path: apps/${{ env.APP_NAME }} + + - name: Set up php + uses: shivammathur/setup-php@4bd44f22a98a19e0950cbad5f31095157cc9621b # v2 + with: + php-version: '8.3' + extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, pgsql, pdo_pgsql + coverage: none + ini-file: development + ini-values: + apc.enabled=on, apc.enable_cli=on, disable_functions= + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Nextcloud + env: + DB_PORT: 4444 + run: | + mkdir data + ./occ maintenance:install --verbose --database=pgsql --database-name=nextcloud --database-host=127.0.0.1 \ + --database-port=$DB_PORT --database-user=root --database-pass=rootpassword \ + --admin-user admin --admin-pass admin + ./occ config:system:set loglevel --value=0 --type=integer + ./occ config:system:set debug --value=true --type=boolean + ./occ app:enable --force app_api + + - name: Test deploy + run: | + PHP_CLI_SERVER_WORKERS=2 php -S 127.0.0.1:8080 & + ./occ app_api:daemon:register docker_local_sock Docker docker-install http /var/run/docker.sock http://127.0.0.1:8080/index.php + ./occ app_api:app:register ${{ env.APP_NAME }} docker_local_sock \ + --info-xml apps/${{ env.APP_NAME }}/appinfo/info.xml + ./occ app_api:app:enable ${{ env.APP_NAME }} + ./occ app_api:app:disable ${{ env.APP_NAME }} + + - name: Save container info & logs + if: always() + run: | + docker inspect nc_app_${{ env.APP_NAME }} | json_pp > container.json + docker logs nc_app_${{ env.APP_NAME }} > container.log 2>&1 + + - name: Check logs + run: | + grep -q 'Started' container.log || error + grep -q 'Connect to Nextcloud was successful' container.log || error + grep -q 'enabled_handler: enabled=True' container.log || error + grep -q 'enabled_handler: enabled=False' container.log || error + grep -q 'Running on CPU' container.log || error + + - name: Unregister App & Daemon + run: | + ./occ app_api:app:unregister ${{ env.APP_NAME }} + ./occ app_api:daemon:unregister docker_local_sock + + - name: Upload Container info + if: always() + uses: actions/upload-artifact@v4 + with: + name: nc_host_app_docker_container.json + path: container.json + if-no-files-found: warn + + - name: Upload Container logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: nc_host_app_docker_container.log + path: container.log + if-no-files-found: warn + + - name: Upload NC logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: nc_host_app_docker_nextcloud.log + path: data/nextcloud.log + if-no-files-found: warn + + tests-deploy-success: + permissions: + contents: none + runs-on: ubuntu-22.04 + needs: [nc-host-app-docker] + name: Tests-Deploy-OK + steps: + - run: echo "Tests-Deploy passed successfully" diff --git a/Dockerfile b/Dockerfile index 8647fef..c3bac56 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM python:3.11-slim-bookworm -RUN apt-get update && apt-get install -y curl iputils-ping && \ +RUN apt-get update && apt-get install -y curl procps iputils-ping netcat-traditional && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* @@ -14,6 +14,23 @@ ADD /ex_app/l10[n] /ex_app/l10n ADD /ex_app/li[b] /ex_app/lib COPY --chmod=775 healthcheck.sh / +COPY --chmod=775 start.sh / + +# Download and install FRP client +RUN set -ex; \ + ARCH=$(uname -m); \ + if [ "$ARCH" = "aarch64" ]; then \ + FRP_URL="https://raw.githubusercontent.com/cloud-py-api/HaRP/main/exapps_dev/frp_0.61.1_linux_arm64.tar.gz"; \ + else \ + FRP_URL="https://raw.githubusercontent.com/cloud-py-api/HaRP/main/exapps_dev/frp_0.61.1_linux_amd64.tar.gz"; \ + fi; \ + echo "Downloading FRP client from $FRP_URL"; \ + curl -L "$FRP_URL" -o /tmp/frp.tar.gz; \ + tar -C /tmp -xzf /tmp/frp.tar.gz; \ + mv /tmp/frp_0.61.1_linux_* /tmp/frp; \ + cp /tmp/frp/frpc /usr/local/bin/frpc; \ + chmod +x /usr/local/bin/frpc; \ + rm -rf /tmp/frp /tmp/frp.tar.gz # Installing PyTorch based on BUILD_TYPE RUN ARCH=$(uname -m) && \ @@ -32,5 +49,5 @@ RUN \ python3 -m pip install -r requirements.txt && rm -rf ~/.cache && rm requirements.txt WORKDIR /ex_app/lib -ENTRYPOINT ["python3", "main.py"] +ENTRYPOINT ["/start.sh"] HEALTHCHECK --interval=2s --timeout=2s --retries=300 CMD /healthcheck.sh diff --git a/appinfo/info-latest.xml b/appinfo/info-latest.xml index 7beea8f..b323255 100644 --- a/appinfo/info-latest.xml +++ b/appinfo/info-latest.xml @@ -6,7 +6,7 @@ - 1.1.0 + 2.0.0 MIT Andrey Borysenko Alexander Piskun @@ -17,7 +17,7 @@ https://github.com/nextcloud/app_api/issues https://github.com/nextcloud/test-deploy - + @@ -25,8 +25,5 @@ nextcloud/test-deploy latest - - - false diff --git a/healthcheck.sh b/healthcheck.sh index 8c3cbfc..d6319ea 100644 --- a/healthcheck.sh +++ b/healthcheck.sh @@ -1,3 +1,9 @@ #!/bin/bash -exit 0 +if [ -f /frpc.toml ] && [ -n "$HP_SHARED_KEY" ]; then + if pgrep -x "frpc" > /dev/null; then + exit 0 + else + exit 1 + fi +fi diff --git a/requirements.txt b/requirements.txt index 2858b33..1d9028d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -nc_py_api[app]>=0.18.2 +nc_py_api[app]>=0.19.0 diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..e80ec05 --- /dev/null +++ b/start.sh @@ -0,0 +1,58 @@ +#!/bin/bash +set -e + +# Only create a config file if HP_SHARED_KEY is set. +if [ -n "$HP_SHARED_KEY" ]; then + echo "HP_SHARED_KEY is set, creating /frpc.toml configuration file..." + if [ -d "/certs/frp" ]; then + echo "Found /certs/frp directory. Creating configuration with TLS certificates." + cat < /frpc.toml +serverAddr = "$HP_FRP_ADDRESS" +serverPort = $HP_FRP_PORT + +transport.tls.enable = true +transport.tls.certFile = "/certs/frp/client.crt" +transport.tls.keyFile = "/certs/frp/client.key" +transport.tls.trustedCaFile = "/certs/frp/ca.crt" +transport.tls.serverName = "harp.nc" + +metadatas.token = "$HP_SHARED_KEY" + +[[proxies]] +name = "$APP_ID" +type = "tcp" +localIP = "127.0.0.1" +localPort = $APP_PORT +remotePort = $APP_PORT +EOF + else + echo "Directory /certs/frp not found. Creating configuration without TLS certificates." + cat < /frpc.toml +serverAddr = "$HP_FRP_ADDRESS" +serverPort = $HP_FRP_PORT + +transport.tls.enable = false + +metadatas.token = "$HP_SHARED_KEY" + +[[proxies]] +name = "$APP_ID" +type = "tcp" +localIP = "127.0.0.1" +localPort = $APP_PORT +remotePort = $APP_PORT +EOF + fi +else + echo "HP_SHARED_KEY is not set. Skipping FRP configuration." +fi + +# If we have a configuration file and the shared key is present, start the FRP client +if [ -f /frpc.toml ] && [ -n "$HP_SHARED_KEY" ]; then + echo "Starting frpc in the background..." + frpc -c /frpc.toml & +fi + +# Start the main Python application +echo "Starting main application..." +exec python3 main.py