From 629c7617a2673bfe3871f3bf1ea856149fa11e22 Mon Sep 17 00:00:00 2001 From: Tomoyuki Sakurai Date: Sun, 13 Oct 2024 13:35:34 +0700 Subject: [PATCH] ci: add poudriere test --- .github/workflows/poudriere.yml | 134 ++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 .github/workflows/poudriere.yml diff --git a/.github/workflows/poudriere.yml b/.github/workflows/poudriere.yml new file mode 100644 index 0000000..a913105 --- /dev/null +++ b/.github/workflows/poudriere.yml @@ -0,0 +1,134 @@ +--- +name: Build all ports in the repository +on: + - push +env: + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + +jobs: + list-ports: + runs-on: ubuntu-latest + outputs: + PORTS_TO_BUILD_JSON: ${{ steps.list_ports_to_build.outputs.PORTS_TO_BUILD_JSON }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Create a list of ports to build + id: list_ports_to_build + shell: sh + run: | + # find ports in the repository and make it a list of one line + # separated by a space. + PORTS_TO_BUILD=`find * -type d -maxdepth 1 -mindepth 1 | tr '\n' ' ' | sed -e 's/ $//'` + + # create a JSON from the list + PORTS_TO_BUILD_JSON=`jq -n -c -M --arg V "${PORTS_TO_BUILD}" '{ PORT: ($V | split(" ")) }'` + + # pass the JSON to other jobs + echo "PORTS_TO_BUILD_JSON=${PORTS_TO_BUILD_JSON}" >> "${GITHUB_OUTPUT}" + cat "${GITHUB_OUTPUT}" + build: + runs-on: ubuntu-latest + needs: + - list-ports + strategy: + # use matrix so that the total time of build does not exceed max job (6 + # hours) and workflow time (35 days). + # https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration + # + # each job builds one port in the repository + matrix: ${{ fromJSON(needs.list-ports.outputs.PORTS_TO_BUILD_JSON) }} + + # do dont cancel other jobs in the matrix when a job fails. + fail-fast: false + steps: + - name: Maximize build space + if: runner.os == 'Linux' + uses: AdityaGarg8/remove-unwanted-software@8831c82abf29b34eb2caac48d5f999ecfc0d8eef + with: + remove-android: 'true' + remove-dotnet: 'true' + remove-haskell: 'true' + remove-codeql: 'true' + remove-docker-images: 'true' + remove-large-packages: 'true' + remove-cached-tools: 'true' + + - name: Checkout + uses: actions/checkout@v4 + + - name: poudriere bulk + id: make + uses: cross-platform-actions/action@v0.25.0 + with: + operating_system: freebsd + version: '14.1' + image_url: https://github.com/trombik/freebsd-builder-poudriere/releases/download/v1.0.0/freebsd-14.1-x86-64.qcow2 + run: | + set -x + set -e + + poudriere ports -l + poudriere jail -l + + JAIL_NAME_VERSION=`uname -r | sed -E -e 's/-(CURRENT|RELEASE).*//' -e 's/\.//'` + JAIL_NAME_ARCH=`uname -m` + JAIL_NAME="${JAIL_NAME_VERSION}${JAIL_NAME_ARCH}" + PORTS_NAME="default" + OVERLAY_DIR=`realpath .` + PORT_TO_BUILD=${{ matrix.PORT }} + + # avoid "fatal: detected dubious ownership in repository at ..." + sudo chown -R root:wheel "${OVERLAY_DIR}" + + # create an overlay + sudo poudriere ports -c -p overlay -B "${{ env.BRANCH_NAME }}" -m git+file -U "${OVERLAY_DIR}" + poudriere ports -l + + # build the ports with the overlay (-o) and binary packages from + # PACKAGE_FETCH_URL (-b). Test the port with Q/A checks (-Ct). use + # `true` to prevent failure on build failures. the job will fail + # later if any build fails. limit the number of job to 2. + sudo poudriere bulk -j "${JAIL_NAME}" -O overlay -b latest -J 2 -Ct ${PORT_TO_BUILD} || true + + # collect the logs. freebsd-vm will copy them back to the host OS. + tree "/usr/local/poudriere/data/logs/bulk/${JAIL_NAME}-${PORTS_NAME}/latest/logs" + sudo cp -R "/usr/local/poudriere/data/logs/bulk/${JAIL_NAME}-${PORTS_NAME}/latest/logs" ${OVERLAY_DIR}/logs + + - name: Create a safe port name from matrix.PORT + shell: sh + run: | + SAFE_PORT_NAME=`echo -n "${{ matrix.PORT }}" | sed -e 's/[ \t:\/\\"<>|*?]/-/g' -e 's/--*/-/g'` + echo "SAFE_PORT_NAME=${SAFE_PORT_NAME}" >> "${GITHUB_ENV}" + + - name: upload logs + id: logs-upload-step + uses: actions/upload-artifact@v4 + with: + name: logs-${{ env.SAFE_PORT_NAME }} + path: logs/ + + - name: Fail if any build failed + shell: sh + run: | + tree . + # logs under `errors` are symlink, not file + ERROR_LOG_FILES=`find logs/errors -type l -name '*.log'` + echo "ERROR_LOG_FILES: ${ERROR_LOG_FILES}" + FAILED_PACKAGES="" + for F in ${ERROR_LOG_FILES}; do + FAILED_PACKAGE=`basename "${F}" | sed -e 's/\.log//'` + FAILED_PACKAGES="${FAILED_PACKAGES} ${FAILED_PACKAGE}" + done + echo "${FAILED_PACKAGE}" > failed_packages.txt + echo "===> Failed package" + cat failed_packages.txt + + echo "Logs are available in an artifact. ID: ${{ steps.logs-upload-step.outputs.artifact-id }}" + + EXIT_STATUS=0 + if [ ! -z "${FAILED_PACKAGES}" ]; then + EXIT_STATUS=1 + fi + exit "${EXIT_STATUS}"