diff --git a/.github/attrs.nix b/.github/attrs.nix new file mode 100644 index 0000000..e9762e2 --- /dev/null +++ b/.github/attrs.nix @@ -0,0 +1,10 @@ +{ + system ? builtins.currentSystem, + lib ? import , + prefix, +}: attrs: +lib.pipe attrs.${system} [ + builtins.attrNames + (builtins.map (x: "${prefix}.${system}.${x}")) + (builtins.concatStringsSep "\n") +] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..b75fee9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/.github/php-alpine.Dockerfile b/.github/php-alpine.Dockerfile deleted file mode 100644 index 15c073b..0000000 --- a/.github/php-alpine.Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -ARG PHP_VERSION=7.4 -ARG PHP_TYPE=alpine -ARG BASE_IMAGE=php:${PHP_VERSION}-${PHP_TYPE} - -# image0 -FROM ${BASE_IMAGE} -WORKDIR /build/php-stemmer -RUN apk --no-cache add alpine-sdk automake autoconf libtool snowball-dev -ADD . . -RUN phpize -RUN ./configure CFLAGS="-O3" -RUN make -RUN make install - -# image1 -FROM ${BASE_IMAGE} -RUN apk --no-cache add snowball -COPY --from=0 /usr/local/lib/php/extensions /usr/local/lib/php/extensions -RUN docker-php-ext-enable stemmer -ENTRYPOINT ["docker-php-entrypoint"] diff --git a/.github/php-debian.Dockerfile b/.github/php-debian.Dockerfile index eeeb2f8..89c78ad 100644 --- a/.github/php-debian.Dockerfile +++ b/.github/php-debian.Dockerfile @@ -1,29 +1,23 @@ -ARG PHP_VERSION=7.4 -ARG BASE_IMAGE=php:$PHP_VERSION +ARG PHP_VERSION=8.1 +ARG PHP_TYPE=bookworm +ARG BASE_IMAGE=php:$PHP_VERSION-cli-$PHP_TYPE # image0 FROM ${BASE_IMAGE} -RUN apt-get update && apt-get install -y \ - autoconf \ - automake \ - gcc \ - libstemmer-dev \ - libtool \ - m4 \ - make \ - pkg-config -WORKDIR /build/php-stemmer +ENV DEV_PACKAGES="libcap-dev libpfm4-dev" +WORKDIR /build +RUN apt-get update && apt-get install -y ${DEV_PACKAGES} ADD . . RUN phpize -RUN ./configure CFLAGS="-O3" +RUN ./configure RUN make RUN make install # image1 FROM ${BASE_IMAGE} -RUN apt-get update && apt-get install -y \ - libstemmer-dev +ENV BIN_PACKAGES="libcap2 libpfm4" +RUN apt-get update && apt-get install -y ${BIN_PACKAGES} COPY --from=0 /usr/local/lib/php/extensions /usr/local/lib/php/extensions -RUN docker-php-ext-enable stemmer +RUN docker-php-ext-enable perfidious ENTRYPOINT ["docker-php-entrypoint"] diff --git a/.github/php-fedora.Dockerfile b/.github/php-fedora.Dockerfile index 6249113..25a404a 100644 --- a/.github/php-fedora.Dockerfile +++ b/.github/php-fedora.Dockerfile @@ -3,27 +3,32 @@ ARG BASE_IMAGE=fedora:latest # image0 FROM ${BASE_IMAGE} +WORKDIR /build + RUN dnf groupinstall 'Development Tools' -y RUN dnf install \ + git-all \ gcc \ automake \ autoconf \ - libstemmer-devel \ libtool \ php-devel \ + libcap-devel \ + libpfm-devel \ -y -WORKDIR /build/php-stemmer + +WORKDIR /build ADD . . RUN phpize -RUN ./configure CFLAGS="-O3" +RUN ./configure RUN make RUN make install # image1 FROM ${BASE_IMAGE} -RUN dnf install php-cli libstemmer-devel -y +RUN dnf install php-cli libcap libpfm -y # this probably won't work on other arches -COPY --from=0 /usr/lib64/php/modules/stemmer.so /usr/lib64/php/modules/stemmer.so +COPY --from=0 /usr/lib64/php/modules/perfidious.so /usr/lib64/php/modules/perfidious.so # please forgive me COPY --from=0 /usr/lib64/php/build/run-tests.php /usr/local/lib/php/build/run-tests.php -RUN echo extension=stemmer.so | sudo tee /etc/php.d/90-stemmer.ini +RUN echo extension=perfidious.so | sudo tee /etc/php.d/90-perfidious.ini diff --git a/.github/scripts/docker.sh b/.github/scripts/docker.sh index ab7f4cd..3188c7a 100755 --- a/.github/scripts/docker.sh +++ b/.github/scripts/docker.sh @@ -1,44 +1,29 @@ #!/usr/bin/env bash -set -e -o pipefail -source .github/scripts/fold.sh +set -ex -o pipefail # config -export DOCKER_NAME=${DOCKER_NAME:-"alpine"} -export PHP_VERSION=${PHP_VERSION:-"7.4"} -export TEST_PHP_EXECUTABLE=${TEST_PHP_EXECUTABLE:-"/usr/local/bin/php"} -export RUN_TESTS_PHP=${RUN_TESTS_PHP:-"/usr/local/lib/php/build/run-tests.php"} +export PHP_VERSION="${PHP_VERSION:-"8.1"}" +export TEST_PHP_EXECUTABLE="${TEST_PHP_EXECUTABLE:-"/usr/local/bin/php"}" +export RUN_TESTS_PHP="${RUN_TESTS_PHP:-"/usr/local/lib/php/build/run-tests.php"}" +export IMAGE_TAG="${IMAGE_TAG:-"php-stemmer-${DOCKER_NAME}"}" -function docker_build() ( - docker build \ - -f .github/php-${DOCKER_NAME}.Dockerfile \ - -t php-stemmer \ - --build-arg PHP_VERSION=${PHP_VERSION} \ - . -) +docker build \ + -f ".github/php-${DOCKER_NAME}.Dockerfile" \ + -t "${IMAGE_TAG}" \ + --build-arg "PHP_VERSION=${PHP_VERSION}" \ + . -function docker_run() ( - set -x - docker run \ - --env NO_INTERACTION=1 \ - --env REPORT_EXIT_STATUS=1 \ - --env TEST_PHP_EXECUTABLE=${TEST_PHP_EXECUTABLE} \ - -v "$PWD/tests:/mnt" \ - php-stemmer \ - php ${RUN_TESTS_PHP} /mnt -) +trap 'catch' ERR -function install_apt_packages() ( - ${SUDO} add-apt-repository ppa:ondrej/php - ${SUDO} apt-get update - ${SUDO} apt-get install -y php${PHP_VERSION}-dev -) +catch() { + find tests -print0 -name '*.log' | xargs -0 -n1 cat +} -function generate_tests() ( - php generate_tests.php -) - -# cifold "install apt packages" install_apt_packages -# cifold "generate tests" generate_tests -cifold "docker build" docker_build -cifold "docker run" docker_run +docker run \ + --env NO_INTERACTION=1 \ + --env REPORT_EXIT_STATUS=1 \ + --env "TEST_PHP_EXECUTABLE=${TEST_PHP_EXECUTABLE}" \ + -v "${PWD}/tests:/mnt" \ + "${IMAGE_TAG}" \ + php "${RUN_TESTS_PHP}" /mnt diff --git a/.github/scripts/fold.sh b/.github/scripts/fold.sh deleted file mode 100755 index 0bdd3ab..0000000 --- a/.github/scripts/fold.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -# adapted from: https://gist.github.com/prisis/e050c4da44c6ee7fa1519912eac19563 - -set -e -o pipefail - -nanoseconds() { - local cmd="date" - local format="+%s%N" - local os=$(uname) - - if hash gdate > /dev/null 2>&1; then - cmd="gdate" - elif [[ "$os" = Darwin ]]; then - format="+%s000000000" - fi - - $cmd -u $format -} - -# Arguments: -# $1 fold name -# $2 command to execute -travisfold () ( - set -e -o pipefail - local title=$1 - shift - local fold=$(echo "$title" | sed -r 's/[^-_A-Za-z\d]+/./g') - local id=$(printf %08x $(( RANDOM * RANDOM ))) - local start=$(nanoseconds) - - function travisfoldend() { - local end=$(nanoseconds) - echo -e "\\ntravis_time:end:$id:start=$start,finish=$end,duration=$(($end-$start))" - if [ "$1" == "true" ]; then - echo -e "\\e[41mKO\\e[0m $title\\n" - else - echo -e "\\e[32mOK\\e[0m $title\\n\\ntravis_fold:end:$fold" - fi - } - - echo -e "travis_fold:start:$fold" - echo -e "travis_time:start:$id" - echo -e "\\e[1;34m$title\\e[0m" - - trap "travisfoldend true" EXIT - $* - trap - EXIT - travisfoldend -) - -function githubfold () ( - set -e -o pipefail - local name=$1 - shift - - echo "::group::$name" - $* - echo "::endgroup::" -) - -function nullfold () ( - set -e -o pipefail - shift - $* -) - -function cifold () ( - set -e -o pipefail - if [[ ! -z "${TRAVIS}" ]]; then - travisfold "$@" - elif [[ ! -z "${GITHUB_RUN_ID}" ]]; then - githubfold "$@" - else - nullfold "$@" - fi -) diff --git a/.github/scripts/linux.sh b/.github/scripts/linux.sh deleted file mode 100755 index e27cfd4..0000000 --- a/.github/scripts/linux.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -set -e -o pipefail -source .github/scripts/fold.sh - -# config -export PHP_VERSION=${PHP_VERSION:-"7.4"} -export COVERAGE=${COVERAGE:-false} -export DEBIAN_FRONTEND=noninteractive -export SUDO=sudo - -function install_apt_packages() ( - ${SUDO} add-apt-repository ppa:ondrej/php - ${SUDO} apt-get update - ${SUDO} apt-get install -y composer php${PHP_VERSION}-dev libstemmer-dev lcov -) - -cifold "install apt packages" install_apt_packages - -# source and execute script used in travis -source .github/scripts/suite.sh -run_all diff --git a/.github/scripts/suite.sh b/.github/scripts/suite.sh deleted file mode 100644 index 4796d0c..0000000 --- a/.github/scripts/suite.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash - -export COVERAGE=${COVERAGE:-true} - -export PHP_MAJOR=$(php -r 'echo phpversion();' | cut -d '.' -f 1) -export PHP_MINOR=$(php -r 'echo phpversion();' | cut -d '.' -f 2) -export PHP_MAJOR_MINOR="${PHP_MAJOR}.${PHP_MINOR}" - -export PHP_WITH_EXT="`which php` -d extension=`pwd`/modules/stemmer.so" - -export DEFAULT_COMPOSER_FLAGS="--no-interaction --no-ansi --no-progress --no-suggest" - -# friendsofphp/php-cs-fixer v2.9.3 requires php ^5.6 || >=7.0 <7.3 -# We'll remove this in the future -if [[ "${PHP_MAJOR_MINOR}" = "7.3" ]] || [[ "${PHP_MAJOR_MINOR}" = "7.4" ]]; then - export DEFAULT_COMPOSER_FLAGS="${DEFAULT_COMPOSER_FLAGS} --ignore-platform-reqs" -fi - -export NO_INTERACTION=1 -export REPORT_EXIT_STATUS=1 -export TEST_PHP_EXECUTABLE=`which php` - -function before_install() ( - set -e -o pipefail - - return 0 -) - -function install() ( - set -e -o pipefail - - phpize - if [[ "${COVERAGE}" = "true" ]]; then - ./configure CFLAGS="-fprofile-arcs -ftest-coverage ${CFLAGS}" LDFLAGS="--coverage ${LDFLAGS}" - else - ./configure - fi - make clean all -) - -function before_script() ( - set -e -o pipefail - - if [[ "${COVERAGE}" = "true" ]]; then - echo "Initializing coverage" - lcov --directory . --zerocounters - lcov --directory . --capture --compat-libtool --initial --output-file coverage.info - fi -) - -function script() ( - set -e -o pipefail - - echo "Running main test suite" - php run-tests.php -d extension=stemmer.so -d extension_dir=modules -n ./tests/*.phpt -) - -function after_success() ( - set -e -o pipefail - - if [[ "${COVERAGE}" = "true" ]]; then - echo "Processing coverage" - lcov --no-checksum --directory . --capture --compat-libtool --output-file coverage.info - lcov --remove coverage.info "/usr*" \ - --remove coverage.info "*/.phpenv/*" \ - --remove coverage.info "/home/travis/build/include/*" \ - --compat-libtool \ - --output-file coverage.info - fi -) - -function after_failure() ( - set -e -o pipefail - - for i in `find tests -name "*.out" 2>/dev/null`; do - echo "-- START ${i}"; - cat ${i}; - echo "-- END"; - done - for i in `find tests -name "*.mem" 2>/dev/null`; do - echo "-- START ${i}"; - cat ${i}; - echo "-- END"; - done -) - -function run_all() ( - set -e - trap after_failure ERR - before_install - install - before_script - script - after_success -) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d383bb3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,269 @@ +name: ci + +on: + push: + branches: + - master + - develop + - ci + pull_request: + branches: + - master + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + name: "Test | PHP ${{ matrix.php-version }}" + strategy: + matrix: + php-version: + - "8.1" + - "8.2" + - "8.3" + steps: + - uses: actions/checkout@v4 + + - uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: libstemmer-dev valgrind + version: 1 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + coverage: "none" + extensions: json, opcache + php-version: "${{ matrix.php-version }}" + tools: composer:v2 + + - run: phpize + + - run: ./configure + + - run: make + + - run: make test + env: + NO_INTERACTION: 1 + REPORT_EXIT_STATUS: 1 + + - run: make test TEST_PHP_ARGS='-m' + env: + NO_INTERACTION: 1 + REPORT_EXIT_STATUS: 1 + USE_ZEND_ALLOC: 0 + + - run: cat tests/*.log + if: failure() + + coverage: + runs-on: ubuntu-latest + name: "Coverage | PHP ${{ matrix.php-version }}" + strategy: + matrix: + php-version: + - "8.1" + - "8.2" + - "8.3" + steps: + - uses: actions/checkout@v4 + + - uses: awalsh128/cache-apt-pkgs-action@latest + with: + packages: libstemmer-dev valgrind + version: 1 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + coverage: pcov + extensions: json, opcache + php-version: "${{ matrix.php-version }}" + tools: composer:v2 + + - run: phpize + + - run: ./configure CFLAGS="-fprofile-arcs -ftest-coverage ${CFLAGS}" LDFLAGS="--coverage ${LDFLAGS}" + + - run: lcov --directory . --zerocounters + + - run: lcov --directory . --capture --compat-libtool --initial --output-file coverage.info + + - run: make + + - run: make test + env: + NO_INTERACTION: 1 + REPORT_EXIT_STATUS: 1 + + - run: cat tests/*.log + if: failure() + + - run: | + lcov --no-checksum --directory . --capture --compat-libtool --output-file coverage.info + lcov --remove coverage.info "/usr*" \ + --remove coverage.info "*/.phpenv/*" \ + --compat-libtool \ + --output-file coverage.info + + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4 + with: + file: coverage.info + token: ${{ secrets.CODECOV_TOKEN }} + slug: jbboehr/php-stemmer + + - name: Coveralls + uses: coverallsapp/github-action@v2 + continue-on-error: true + with: + file: coverage.info + format: lcov + parallel: true + + finish: + needs: + - coverage + - nix + if: ${{ always() }} + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@v2 + with: + parallel-finished: true + + nix-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v4 + - uses: cachix/install-nix-action@v26 + - id: set-matrix + name: Generate Nix Matrix + run: | + set -Eeu + matrix="$(nix eval --json '.#githubActions.matrix')" + echo "matrix=$matrix" >> "$GITHUB_OUTPUT" + + nix: + name: "nix (${{ matrix.name }})" + runs-on: ${{ matrix.os }} + needs: nix-matrix + strategy: + matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}} + steps: + - uses: actions/checkout@v4 + + - name: Set Up Build Cache + uses: actions/cache@v4 + id: nix-cache + with: + path: /tmp/nix-store.nar + key: nix-store.nar-${{ runner.os }}-${{ hashFiles('flake.lock') }}-${{ matrix.attr }} + restore-keys: | + nix-store.nar-${{ runner.os }}-${{ hashFiles('flake.lock') }}-${{ matrix.attr }} + nix-store.nar-${{ runner.os }}-${{ hashFiles('flake.lock') }}- + nix-store.nar-${{ runner.os }}- + + - uses: cachix/install-nix-action@v26 + with: + nix_path: nixpkgs=channel:nixos-23.11 + extra_nix_config: "system-features = nixos-test benchmark big-parallel kvm" + + - name: Import Nix Store Cache + if: "steps.nix-cache.outputs.cache-hit == 'true'" + run: | + nix-store --import < /tmp/nix-store.nar + + - run: nix build -L ".#${{ matrix.attr }}" + + - run: find -L result*; cp result-coverage/coverage.info coverage.info || true + + - name: Upload coverage reports to Codecov + if: ${{ hashFiles('coverage.info') != '' }} + uses: codecov/codecov-action@v4 + with: + file: coverage.info + token: ${{ secrets.CODECOV_TOKEN }} + slug: jbboehr/php-stemmer + + - name: Coveralls + if: ${{ hashFiles('coverage.info') != '' }} + uses: coverallsapp/github-action@v2 + continue-on-error: true + with: + file: coverage.info + format: lcov + parallel: true + + - name: Export Nix Store Cache + shell: bash + # partially based on https://github.com/NixOS/nix/issues/1245#issuecomment-282586759 + run: | + drv="$(nix-store -qd "$(readlink result)")" + drvRefs="$( echo "$drv" | xargs nix-store -q --references )" + ( echo "$drvRefs" | grep '[.]drv$' | xargs nix-store -q --outputs ; + echo "$drvRefs" | grep -v '[.]drv$' ) | \ + xargs nix-store -r | \ + xargs nix-store -qR | + xargs nix-store --export > /tmp/nix-store.nar + + docker: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + PHP_VERSION: + - "8.1" + - "8.2" + - "8.3" + DOCKER_NAME: + - debian + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: docker/setup-buildx-action@v3 + - uses: docker/build-push-action@v5 + with: + context: . + file: .github/php-${{ matrix.DOCKER_NAME }}.Dockerfile + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: PHP_VERSION=${{ matrix.PHP_VERSION }} + tags: php-stemmer-${{ matrix.DOCKER_NAME }} + - name: I am tired of writing this shit in YAML and learning a new DSL for every CI service so I am putting everything in a FSCKING BASH SCRIPT + env: + PHP_VERSION: ${{ matrix.PHP_VERSION }} + DOCKER_NAME: ${{ matrix.DOCKER_NAME }} + run: bash ./.github/scripts/docker.sh + + docker-fedora: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + DOCKER_NAME: + - fedora + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: docker/setup-buildx-action@v3 + - uses: docker/build-push-action@v5 + with: + context: . + file: .github/php-${{ matrix.DOCKER_NAME }}.Dockerfile + cache-from: type=gha + cache-to: type=gha,mode=max + tags: php-stemmer-${{ matrix.DOCKER_NAME }} + - name: I am tired of writing this shit in YAML and learning a new DSL for every CI service so I am putting everything in a FSCKING BASH SCRIPT + env: + DOCKER_NAME: ${{ matrix.DOCKER_NAME }} + TEST_PHP_EXECUTABLE: /usr/bin/php + run: bash ./.github/scripts/docker.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index d004069..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: docker - -on: - push: - branches: - - master - - github-actions - - ci - pull_request: - branches: - - master - -jobs: - docker: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - PHP_VERSION: - - "7.2" - - "7.3" - - "7.4" - - "8.0-rc" - DOCKER_NAME: - - "alpine" - - "debian" - steps: - - uses: actions/checkout@v2 - - name: I am tired of writing this shit in YAML and learning a new DSL for every CI service so I am putting everything in a FSCKING BASH SCRIPT - env: - PHP_VERSION: ${{ matrix.PHP_VERSION }} - DOCKER_NAME: ${{ matrix.DOCKER_NAME }} - run: bash ./.github/scripts/docker.sh - fedora: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: I am tired of writing this shit in YAML and learning a new DSL for every CI service so I am putting everything in a FSCKING BASH SCRIPT - env: - DOCKER_NAME: fedora - TEST_PHP_EXECUTABLE: /usr/bin/php - run: bash ./.github/scripts/docker.sh diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index 1c17e24..0000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: linux - -on: - push: - branches: - - master - - github-actions - - ci - pull_request: - branches: - - master - -jobs: - linux: - runs-on: ubuntu-20.04 - strategy: - fail-fast: false - matrix: - PHP_VERSION: - - "7.2" - - "7.3" - - "7.4" - - "8.0" - COVERAGE: ["true", "false"] - steps: - - uses: actions/checkout@v2 - - name: I am tired of writing this shit in YAML and learning a new DSL for every CI service so I'm putting everything in a FSCKING BASH SCRIPT - env: - PHP_VERSION: ${{ matrix.PHP_VERSION }} - COVERAGE: ${{ matrix.COVERAGE }} - run: bash ./.github/scripts/linux.sh - - name: Coveralls - if: ${{ matrix.COVERAGE == 'true' }} - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: ./coverage.info diff --git a/flake.nix b/flake.nix index 27b208b..ec7de11 100644 --- a/flake.nix +++ b/flake.nix @@ -47,7 +47,7 @@ src' = gitignore.lib.gitignoreSource ./.; src = pkgs.lib.cleanSourceWith { - name = "php-perfidious-source"; + name = "php-stemmer-source"; src = src'; filter = gitignore.lib.gitignoreFilterWith { basePath = ./.;