name: "Build and test LXD image" on: workflow_call: inputs: git_ref: required: true type: string arch: required: false type: string default: 'x86' outputs: lxd_artifact_name: value: "${{ jobs.build-current.outputs.artifact_name }}" lxd_artifact_file: value: "${{ jobs.build-current.outputs.artifact_file }}" lxc_artifact_name: value: "${{ jobs.convert-to-lxc-image.outputs.artifact_name }}" lxc_artifact_file: value: "${{ jobs.convert-to-lxc-image.outputs.artifact_file }}" push: branches: - "**" pull_request: branches: - master - devel - release/* jobs: determine-runner: env: LXD_ARCH: "${{ inputs.arch || 'x86' }}" runs-on: ubuntu-latest outputs: runner_label: ${{ steps.script.outputs.runner_label }} steps: - name: script id: script run: | if [[ "${LXD_ARCH}" == "arm64" ]] then RUNNER_LABEL="ubuntu-20.04-arm64" else RUNNER_LABEL="ubuntu-20.04" fi echo "runner_label=$RUNNER_LABEL" | tee -a $GITHUB_OUTPUT build-current: needs: - determine-runner runs-on: ${{ needs.determine-runner.outputs.runner_label }} outputs: artifact_name: "${{ env.ARTIFACT_NAME }}" artifact_file: "${{ steps.pack-lxd.outputs.artifact_file }}" env: VERSION: "${{ inputs.git_ref || github.head_ref || github.ref_name }}" ARTIFACT_NAME: "${{ github.run_id }}-lxd-${{ inputs.arch || 'x86' }}-image" LXD_ARCH: "${{ inputs.arch || 'x86' }}" steps: - name: Checkout code uses: actions/checkout@v3 with: ref: "${{ env.VERSION }}" - name: Cleanup lxd run: test -z "$(lxc profile device show default | grep eth0)" || lxc profile device remove default eth0 - uses: whywaita/setup-lxd@v1 continue-on-error: true with: lxd_version: latest/stable - name: Fix LXD run: | sudo iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT sudo iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - name: Build LXD image run: | ./build/build-LXD.sh - name: Pack LXD image id: pack-lxd run: | . ./build/buildlib.sh ARTIFACT_FILE="NextcloudPi_LXD_${LXD_ARCH:-x86}_${VERSION//\//_}" lxc image export -q ncp/"${version}" "output/${ARTIFACT_FILE}" echo "artifact_file=${ARTIFACT_FILE}.tar.gz" >> $GITHUB_OUTPUT - name: upload LXD image to artifact store uses: actions/upload-artifact@v3 with: name: "${{ env.ARTIFACT_NAME }}" path: "output/${{ steps.pack-lxd.outputs.artifact_file }}" if-no-files-found: error build-previous: runs-on: [ ubuntu-20.04 ] if: ${{ inputs.arch == 'x86' || inputs.arch == '' }} outputs: artifact_name: "${{ env.ARTIFACT_NAME }}" artifact_file: "${{ steps.pack-lxd.outputs.artifact_file }}" previous_version: "${{ steps.checkout_previous_version.outputs.previous_version }}" env: VERSION: "${{ inputs.git_ref || github.head_ref || github.ref_name }}" ARTIFACT_NAME: "${{ github.run_id }}-lxd-${{ inputs.arch || 'x86' }}-image-previous" LXD_ARCH: "${{ inputs.arch || 'x86' }}" steps: - name: Checkout code uses: actions/checkout@v3 with: ref: "${{ env.VERSION }}" fetch-depth: 0 - name: Checkout previous release id: checkout_previous_version shell: bash run: | set -e if [[ -n "${{ github.base_ref }}" ]] then version="${{ github.base_ref }}" elif [[ "${{ env.VERSION }}" == "refs/heads/devel" ]] then version="master" else if [[ "${{ github.ref_type }}" != "tag" ]] || ! git describe --tags > /dev/null then git fetch -fu --tags origin ${{ env.VERSION }}:${{ env.VERSION }} fi version="$(git describe --tags)" [[ "$version" =~ .*-.*-.* ]] || { git checkout HEAD~1 version="$(git describe --tags)" } version="${version%-*-*}" fi echo "Previous version is '$version'" git checkout "$version" echo "VERSION=$version" >> "$GITHUB_ENV" echo "previous_version=${version}" >> $GITHUB_OUTPUT - uses: whywaita/setup-lxd@v1 continue-on-error: true with: lxd_version: latest/stable - name: Fix LXD run: | sudo iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT sudo iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - name: Build LXD image run: | ./build/build-LXD.sh - name: Pack LXD image id: pack-lxd run: | . ./build/buildlib.sh ARTIFACT_FILE="NextcloudPi_LXD_${LXD_ARCH:-x86}_${VERSION//\//_}" lxc image export -q ncp/"${version}" "output/${ARTIFACT_FILE}" echo "artifact_file=${ARTIFACT_FILE}.tar.gz" >> $GITHUB_OUTPUT - name: upload LXD image to artifact store uses: actions/upload-artifact@v3 with: name: "${{ env.ARTIFACT_NAME }}" path: "output/${{ steps.pack-lxd.outputs.artifact_file }}" if-no-files-found: error test-update: needs: - build-previous runs-on: [ubuntu-20.04] outputs: artifact_name: "${{ env.ARTIFACT_NAME }}" artifact_file: "${{ steps.pack-lxd.outputs.artifact_file }}" env: VERSION: "${{ inputs.git_ref || github.ref }}" ARTIFACT_NAME: "${{ needs.build-previous.outputs.artifact_name }}" steps: - uses: whywaita/setup-lxd@v1 continue-on-error: true with: lxd_version: latest/stable - name: Fix LXD run: | sudo iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT sudo iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - name: Checkout code uses: actions/checkout@v3 with: ref: "${{ env.VERSION }}" - name: Setup Firefox continue-on-error: true id: setup-firefox-browser-action uses: browser-actions/setup-firefox@latest - name: Setup Firefox from packages if: ${{ steps.setup-firefox-browser-action.outcome == 'failure' }} run: | sudo apt-get install -y --no-install-recommends firefox - name: Setup GeckoDriver uses: ChlodAlejandro/setup-geckodriver@latest with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium run: pip install selenium - name: download LXD image from artifact store uses: actions/download-artifact@v3 with: name: ${{ needs.build-previous.outputs.artifact_name }} - name: Launch ncp container run: | set -x lxc delete -q -f ncp || true lxc image import -q "./${{ needs.build-previous.outputs.artifact_file }}" --alias "ncp/update" systemd-run --user --scope -p "Delegate=yes" lxc launch -q "ncp/update" ncp lxc exec ncp -- bash -c 'while [ "$(systemctl is-system-running 2>/dev/null)" != "running" ] && [ "$(systemctl is-system-running 2>/dev/null)" != "degraded" ]; do :; done' lxc exec ncp -- rm -f /opt/ncdata/data/nextcloud.log sleep 30 ip="$(lxc list -c n4 -f csv | grep '^ncp' | cut -d ',' -f2)" ip="${ip/% *}" echo "${ip} nextcloudpi.local" | sudo tee /etc/hosts - name: Activate and Test LXD Image working-directory: ./tests run: | lxc exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || { echo "Activation test failed!" echo "Geckodriver logs:" tail -n 20 geckodriver.log >&2 || true echo "================" echo "ncp.log: " lxc exec ncp -- "tail -n20 /var/log/ncp.log" exit 1 } python system_tests.py --non-interactive || { echo "System test failed!" exit 1 } python nextcloud_tests.py --no-gui "nextcloudpi.local" 443 4443 || { echo "Nextcloud test failed!" echo "Geckodriver logs:" tail -n 20 geckodriver.log >&2 || true echo "================" echo "ncp.log: " lxc exec ncp -- "tail -n20 /var/log/ncp.log" exit 1 } - name: Update ncp run: | set -ex BRANCH="${VERSION/refs\/heads\//}" BRANCH="${BRANCH/refs\/tags\//}" if [[ "$BRANCH" =~ "refs/pull/"* ]] then UPDATE_ARGS=("${{ github.base_ref }}" "$VERSION") else UPDATE_ARGS=("$BRANCH") fi echo "VERSION=${VERSION}" >> "$GITHUB_ENV" echo "Running update ${{ needs.build-previous.outputs.previous_version }} -> ${VERSION}" current_nc_version="$(lxc exec ncp -- ncc status | grep "version:" | awk '{ print $3 }')" latest_nc_version="$(cat etc/ncp.cfg | jq -r '.nextcloud_version')" lxc exec ncp -- bash -c "DBG=x ncp-update ${UPDATE_ARGS[*]}" lxc exec ncp -- /usr/local/bin/ncc status if [[ "$current_nc_version" =~ "$latest_nc_version".* ]] then echo "Nextcloud is up to date - skipping NC update test." else lxc exec ncp -- bash -c "DBG=x ncp-update-nc ${latest_nc_version?}" fi lxc exec ncp -- rm -f /opt/ncdata/data/nextcloud.log lxc stop ncp - name: Relaunch container run: | set -x systemd-run --user --scope -p "Delegate=yes" lxc start ncp lxc exec ncp -- bash -c 'while [ "$(systemctl is-system-running 2>/dev/null)" != "running" ] && [ "$(systemctl is-system-running 2>/dev/null)" != "degraded" ]; do :; done' sleep 30 ip="$(lxc list -c n4 -f csv | grep '^ncp' | cut -d ',' -f2)" ip="${ip/% *}" echo "${ip} nextcloudpi.local" | sudo tee /etc/hosts - name: Test LXD Image working-directory: ./tests run: | lxc exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & python system_tests.py --non-interactive || { echo "System test failed!" exit 1 } python nextcloud_tests.py --no-gui "nextcloudpi.local" 443 4443 || { echo "Nextcloud test failed!" echo "Geckodriver logs:" tail -n 20 geckodriver.log >&2 || true echo "================" echo "ncp.log: " lxc exec ncp -- "tail -n20 /var/log/ncp.log" exit 1 } lxc stop ncp test-fresh-install: needs: - determine-runner - build-current runs-on: ${{ needs.determine-runner.outputs.runner_label }} env: VERSION: "${{ inputs.git_ref || github.head_ref || github.ref_name }}" ARTIFACT_NAME: ${{ needs.build-current.outputs.artifact_name }} ARTIFACT_FILE: ${{ needs.build-current.outputs.artifact_file }} steps: - name: Checkout code uses: actions/checkout@v3 with: ref: "${{ env.VERSION }}" - name: Cleanup lxd run: test -z "$(lxc profile device show default | grep eth0)" || lxc profile device remove default eth0 - uses: whywaita/setup-lxd@v1 continue-on-error: true with: lxd_version: latest/stable - name: Fix LXD continue-on-error: true run: | sudo iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT sudo iptables -I DOCKER-USER -o lxdbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT - name: Setup Firefox uses: browser-actions/setup-firefox@latest continue-on-error: true - name: Setup GeckoDriver uses: ChlodAlejandro/setup-geckodriver@latest continue-on-error: true with: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Selenium run: pip install selenium - name: download LXD image from artifact store uses: actions/download-artifact@v3 with: name: ${{ env.ARTIFACT_NAME }} - name: Remove old lxd images if: ${{ inputs.arch == 'arm64' }} run: | for img in $(lxc image list -c f -f csv) do lxc image delete "$img" done - name: Launch ncp container run: | set -x . ./build/buildlib.sh lxc delete -q -f ncp || true lxc image import -q "./${ARTIFACT_FILE?}" --alias "ncp/test" || true systemd-run --user --scope -p "Delegate=yes" lxc launch -q "ncp/test" ncp || \ sudo systemd-run --scope -p "Delegate=yes" lxc launch -q "ncp/test" ncp lxc exec ncp -- bash -c 'while [ "$(systemctl is-system-running 2>/dev/null)" != "running" ] && [ "$(systemctl is-system-running 2>/dev/null)" != "degraded" ]; do :; done' sleep 30 ip="$(lxc list -c n4 -f csv | grep '^ncp' | cut -d ',' -f2)" ip="${ip/% *}" echo "${ip} nextcloudpi.local" | sudo tee /etc/hosts - name: Test LXD Image working-directory: ./tests run: | lxc exec ncp -- bash -c 'tail -f /var/log/ncp.log' |& awk '{ print "NCP::" $0 }' & python activation_tests.py --no-gui "nextcloudpi.local" 443 4443 || { echo "Activation test failed!" echo "Geckodriver logs:" tail -n 20 geckodriver.log >&2 || true echo "================" echo "ncp.log: " lxc exec ncp -- "tail -n20 /var/log/ncp.log" exit 1 } python system_tests.py --non-interactive || { echo "System test failed!" exit 1 } python nextcloud_tests.py --no-gui "nextcloudpi.local" 443 4443 || { echo "Nextcloud test failed!" echo "Geckodriver logs:" tail -n 20 geckodriver.log >&2 || true echo "================" echo "ncp.log: " lxc exec ncp -- "tail -n20 /var/log/ncp.log" || true echo "================" echo "nextcloud log: " datadir="$(lxc exec ncp -- ncc config:system:get datadirectory)" lxc exec ncp -- cat "$datadir/nextcloud.log" || true exit 1 } lxc stop ncp convert-to-lxc-image: needs: - build-current runs-on: ubuntu-latest outputs: artifact_name: "${{ steps.lxd-to-lxc.outputs.artifact_name }}" artifact_file: "${{ steps.lxd-to-lxc.outputs.artifact_file }}" env: VERSION: "${{ inputs.git_ref || github.head_ref || github.ref_name }}" LXD_ARTIFACT_NAME: ${{ needs.build-current.outputs.artifact_name }} LXD_ARTIFACT_FILE: ${{ needs.build-current.outputs.artifact_file }} steps: - name: download LXD image from artifact store uses: actions/download-artifact@v3 with: name: ${{ env.LXD_ARTIFACT_NAME }} - name: convert to LXC image id: lxd-to-lxc run: | mkdir repackage output cd repackage sudo tar xpf "../${LXD_ARTIFACT_FILE?}" sudo rm -rf ./rootfs/dev LXC_ARTIFACT_FILE="${LXD_ARTIFACT_FILE//LXD/LXC}" sudo tar cpzf "../output/${LXC_ARTIFACT_FILE?}" -C rootfs/ . cd .. sudo chown "$(id -un):" "./output/${LXC_ARTIFACT_FILE}" echo "artifact_file=${LXC_ARTIFACT_FILE?}" >> $GITHUB_OUTPUT echo "artifact_name=${LXD_ARTIFACT_NAME//lxd/lxc}" >> $GITHUB_OUTPUT - name: upload LXD image to artifact store uses: actions/upload-artifact@v3 with: name: "${{ steps.lxd-to-lxc.outputs.artifact_name }}" path: "output/${{ steps.lxd-to-lxc.outputs.artifact_file }}" if-no-files-found: error