diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index ff424a04..b478feab 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -7,73 +7,19 @@ on: pull_request: jobs: - build: - name: 'PHP ${{ matrix.php.branch }}' + prepare-ci: + name: 'Prepare actions' runs-on: ubuntu-latest - strategy: - matrix: - php: - - branch: '8.2' - - branch: '8.1' - - branch: '8.0' - - branch: '7.4' - - branch: '7.3' - - branch: '7.2' - - branch: '7.1' - - branch: '7.0' - - branch: '5.6' - # We want to fix failures individually. - fail-fast: false steps: - uses: actions/checkout@v3 - name: Install Nix uses: cachix/install-nix-action@v18 - - name: Set up Nix cache - uses: cachix/cachix-action@v12 - with: - name: fossar - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - - name: Set job parameters - id: params - run: | - branch=${{ matrix.php.branch }} - major=${branch%%.*} - minor=${branch#*.} - attr=php$major$minor - echo "major=$major" >> $GITHUB_OUTPUT - echo "attr=$attr" >> $GITHUB_OUTPUT - - - name: Build PHP - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-php - - - name: Build Imagick extension - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-imagick - - - name: Build Redis extension - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-redis - - - name: Build Redis 3 extension - if: ${{ steps.params.outputs.major < 8 }} - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-redis3 - - - name: Build MySQL extension - if: ${{ steps.params.outputs.major < 7 }} - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-mysql - - - name: Build Xdebug extension - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-xdebug - - - name: Build Tidy extension - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-tidy - - - name: Check that composer PHAR works - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-composer-phar - - - name: Validate php.extensions.mysqli default unix socket path - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-mysqli-socket-path - - - name: Validate php.extensions.pdo_mysql default unix socket path - run: nix-build -A outputs.checks.x86_64-linux.${{ steps.params.outputs.attr }}-pdo_mysql-socket-path + - name: Generate actions + run: nix-shell .github/workflows/workflow-from-flake-checks.nix + test: + needs: + - prepare-ci + uses: ./.github/workflows/test.yaml + secrets: inherit diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 00000000..6d4d123a --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,134 @@ +{ + "jobs": { + "test": { + "name": "PHP ${{ matrix.php.branch }}", + "runs-on": "${{ matrix.os.image }}", + "steps": [ + { + "uses": "actions/checkout@v3" + }, + { + "name": "Install Nix", + "uses": "cachix/install-nix-action@v18" + }, + { + "name": "Set up Nix cache", + "uses": "cachix/cachix-action@v10", + "with": { + "authToken": "${{ secrets.CACHIX_AUTH_TOKEN }}", + "name": "fossar" + } + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Check that composer PHAR works", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-composer-phar" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Build Imagick extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-imagick" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\"]'), matrix.php.attr) }}", + "name": "Build MySQL extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-mysql" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Validate php.extensions.mysqli default unix socket path", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-mysqli-socket-path" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Validate php.extensions.pdo_mysql default unix socket path", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-pdo_mysql-socket-path" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Build PHP", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-php" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Build Redis extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-redis" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\"]'), matrix.php.attr) }}", + "name": "Build Redis 3 extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-redis3" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Build Tidy extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-tidy" + }, + { + "if": "${{ contains(fromJSON('[\"aarch64-darwin\",\"aarch64-linux\",\"x86_64-darwin\",\"x86_64-linux\"]'), matrix.os.platform) && contains(fromJSON('[\"php56\",\"php70\",\"php71\",\"php72\",\"php73\",\"php74\",\"php80\",\"php81\",\"php82\"]'), matrix.php.attr) }}", + "name": "Build Xdebug extension", + "run": "nix-build -A outputs.checks.${{ matrix.os.platform }}.${{ matrix.php.attr }}-xdebug" + } + ], + "strategy": { + "fail-fast": false, + "matrix": { + "os": [ + { + "image": "ubuntu-latest", + "platform": "x86_64-linux" + } + ], + "php": [ + { + "attr": "php56", + "branch": "5.6" + }, + { + "attr": "php70", + "branch": "7.0" + }, + { + "attr": "php71", + "branch": "7.1" + }, + { + "attr": "php72", + "branch": "7.2" + }, + { + "attr": "php73", + "branch": "7.3" + }, + { + "attr": "php74", + "branch": "7.4" + }, + { + "attr": "php80", + "branch": "8.0" + }, + { + "attr": "php81", + "branch": "8.1" + }, + { + "attr": "php82", + "branch": "8.2" + } + ] + } + } + } + }, + "name": "Test", + "on": { + "workflow_call": { + "secrets": { + "CACHIX_AUTH_TOKEN": { + "required": true + } + } + } + } +} diff --git a/.github/workflows/workflow-from-flake-checks.nix b/.github/workflows/workflow-from-flake-checks.nix new file mode 100644 index 00000000..3a570d34 --- /dev/null +++ b/.github/workflows/workflow-from-flake-checks.nix @@ -0,0 +1,151 @@ +# Runs Nix flake checks individually with group markers for GitHub Actions. +# Invoke with `nix-shell workflow-from-flake-checks.nix` + +let + self = import ../..; + + pkgs = self.inputs.nixpkgs.legacyPackages.${builtins.currentSystem}; + inherit (self.inputs.nixpkgs) lib; + + checkAttrs = + lib.foldl' + ( + acc: + { + name, + value, + }: + + acc // { + "${name}" = { + inherit (value) description; + platforms = acc.${name}.platforms or {} // { "${value.platform}" = null; }; + phps = acc.${name}.phps or {} // { "${value.php}" = null; }; + }; + } + ) + {} + ( + builtins.concatLists ( + lib.mapAttrsToList + ( + platform: + checks: + + lib.mapAttrsToList + ( + attr: + check: + + let + match = builtins.match "(php[0-9]+)-(.+)" attr; + in + { + name = builtins.head (builtins.tail match); + value = { + inherit (check) description; + inherit platform; + php = builtins.head match; + }; + } + ) + checks + ) + self.outputs.checks + ) + ); + + packages = self.outputs.packages.${builtins.currentSystem}; + phpPackages = builtins.filter (name: builtins.match "php[0-9]+" name != null) (builtins.attrNames packages); + + workflow = { + name = "Test"; + + on = { + workflow_call = { + secrets = { + CACHIX_AUTH_TOKEN = { + required = true; + }; + }; + }; + }; + + jobs = { + test = { + name = "PHP \${{ matrix.php.branch }}"; + runs-on = "\${{ matrix.os.image }}"; + steps = [ + { + uses = "actions/checkout@v3"; + } + { + name = "Install Nix"; + uses = "cachix/install-nix-action@v18"; + } + { + name = "Set up Nix cache"; + uses = "cachix/cachix-action@v10"; + "with" = { + authToken = "\${{ secrets.CACHIX_AUTH_TOKEN }}"; + name = "fossar"; + }; + } + ] + ++ lib.mapAttrsToList + ( + attr: + check: + + { + name = check.description; + "if" = "\${{ contains(fromJSON('${lib.escape [ "\\" "'" ] (builtins.toJSON (builtins.attrNames check.platforms))}'), matrix.os.platform) && contains(fromJSON('${lib.escape [ "\\" "'" ] (builtins.toJSON (builtins.attrNames check.phps))}'), matrix.php.attr) }}"; + run = "nix-build -A outputs.checks.\${{ matrix.os.platform }}.\${{ matrix.php.attr }}-${attr}"; + } + ) + checkAttrs + ; + strategy = { + # We want to fix failures individually. + fail-fast = false; + matrix = { + os = [ + { + image = "ubuntu-latest"; + platform = "x86_64-linux"; + } + ]; + php = + builtins.map + ( + phpAttr: + + { + branch = lib.versions.majorMinor packages.${phpAttr}.version; + attr = phpAttr; + } + ) + phpPackages; + }; + }; + }; + }; + }; +in + +pkgs.stdenv.mkDerivation { + name = "workflow-from-flake-checks"; + + buildCommand = '' + echo 'Please run `nix-shell .github/workflows/workflow-from-flake-checks.nix`, `nix-build` cannot be used.' > /dev/stderr + exit 1 + ''; + + shellHook = + '' + set -o errexit + echo ${lib.escapeShellArgs [ (builtins.toJSON workflow) ]} | ${pkgs.jq}/bin/jq . > .github/workflows/test.yaml + exit 0 + '' + ; +} diff --git a/checks.nix b/checks.nix index b322f85d..842719f0 100644 --- a/checks.nix +++ b/checks.nix @@ -1,160 +1,96 @@ { - system, - packages, - pkgs, + lib, + php, + runCommand, }: -let - phpPackages = builtins.filter (name: builtins.match "php[0-9]+" name != null) (builtins.attrNames packages); - - checks = { - php = { - description = "Build PHP"; - drv = { php, ... }: php; - }; - - imagick = { - description = "Build Imagick extension"; - drv = { php, ... }: php.extensions.imagick; - }; - - redis = { - description = "Build Redis extension"; - drv = { php, ... }: php.extensions.redis; - }; - - redis3 = { - description = "Build Redis 3 extension"; - enabled = { php, lib, ... }: lib.versionOlder php.version "8"; - drv = { php, ... }: php.extensions.redis3; - }; - - mysql = { - description = "Build MySQL extension"; - enabled = { php, lib, ... }: lib.versionOlder php.version "7"; - drv = { php, ... }: php.extensions.mysql; - }; - - xdebug = { - description = "Build Xdebug extension"; - drv = { php, ... }: php.extensions.xdebug; - }; +{ + php = { + description = "Build PHP"; + drv = php; + }; - tidy = { - description = "Build Tidy extension"; - drv = { php, ... }: php.extensions.tidy; - }; + imagick = { + description = "Build Imagick extension"; + drv = php.extensions.imagick; + }; - composer-phar = { - description = "Check that composer PHAR works"; - drv = - { pkgs, php, ... }: - pkgs.runCommand - "composer-phar-check" - { - buildInputs = [ - php.packages.composer - ]; - } - '' - composer --version - touch "$out" - ''; - }; + redis = { + description = "Build Redis extension"; + drv = php.extensions.redis; + }; - mysqli-socket-path = { - description = "Validate php.extensions.mysqli default unix socket path"; - drv = - { pkgs, php, ... }: - pkgs.runCommand - "mysqli-socket-path-check" - { - buildInputs = [ - (php.withExtensions ({ all, ... }: [ - all.mysqli - ])) - ]; - } - '' - php -r "echo ini_get('mysqli.default_socket') . PHP_EOL;" | grep /run/mysqld/mysqld.sock - touch "$out" - ''; - }; + redis3 = { + description = "Build Redis 3 extension"; + enabled = lib.versionOlder php.version "8"; + drv = php.extensions.redis3; + }; - pdo_mysql-socket-path = { - description = "Validate php.extensions.pdo_mysql default unix socket path"; - drv = - { pkgs, php, ... }: - pkgs.runCommand - "pdo_mysql-socket-path-check" - { - buildInputs = [ - (php.withExtensions ({ all, ... }: [ - all.pdo_mysql - ])) - ]; - } - '' - php -r "echo ini_get('pdo_mysql.default_socket') . PHP_EOL;" | grep /run/mysqld/mysqld.sock - touch "$out" - ''; - }; + mysql = { + description = "Build MySQL extension"; + enabled = lib.versionOlder php.version "7"; + drv = php.extensions.mysql; }; - inherit (pkgs) lib; + xdebug = { + description = "Build Xdebug extension"; + drv = php.extensions.xdebug; + }; - /* AttrSet> */ - checksPerVersion = - lib.listToAttrs ( - builtins.map - (phpName: - let - php = packages.${phpName}; - phpVersion = lib.versions.majorMinor php.version; - args = { inherit lib php pkgs system; }; - supportedChecks = lib.filterAttrs (_name: { enabled ? lib.const true, ... }: enabled args) checks; - in - { - name = phpName; - value = - lib.mapAttrs - ( - _name: - { - description, - drv, - ... - }: + tidy = { + description = "Build Tidy extension"; + drv = php.extensions.tidy; + }; - let - check = drv args; - in - check // { - passthru = check.passthru or { } // { - description = "PHP ${phpVersion} – ${description}"; - }; - } - ) - supportedChecks; - } - ) - phpPackages - ); -in -lib.foldAttrs - lib.mergeAttrs - {} - ( - lib.mapAttrsToList - ( - phpName: + composer-phar = { + description = "Check that composer PHAR works"; + drv = + runCommand + "composer-phar-check" + { + buildInputs = [ + php.packages.composer + ]; + } + '' + composer --version + touch "$out" + ''; + }; - lib.mapAttrs' - ( - name: + mysqli-socket-path = { + description = "Validate php.extensions.mysqli default unix socket path"; + drv = + runCommand + "mysqli-socket-path-check" + { + buildInputs = [ + (php.withExtensions ({ all, ... }: [ + all.mysqli + ])) + ]; + } + '' + php -r "echo ini_get('mysqli.default_socket') . PHP_EOL;" | grep /run/mysqld/mysqld.sock + touch "$out" + ''; + }; - lib.nameValuePair "${phpName}-${name}" - ) - ) - checksPerVersion - ) + pdo_mysql-socket-path = { + description = "Validate php.extensions.pdo_mysql default unix socket path"; + drv = + runCommand + "pdo_mysql-socket-path-check" + { + buildInputs = [ + (php.withExtensions ({ all, ... }: [ + all.pdo_mysql + ])) + ]; + } + '' + php -r "echo ini_get('pdo_mysql.default_socket') . PHP_EOL;" | grep /run/mysqld/mysqld.sock + touch "$out" + ''; + }; +} diff --git a/flake.nix b/flake.nix index a5ecb1a5..43f9f260 100644 --- a/flake.nix +++ b/flake.nix @@ -32,9 +32,67 @@ inherit (pkgs) php php56 php70 php71 php72 php73 php74 php80 php81 php82; }; - checks = import ./checks.nix { - inherit packages pkgs system; - }; + checks = + let + phpPackages = builtins.filter (name: builtins.match "php[0-9]+" name != null) (builtins.attrNames packages); + + inherit (pkgs) lib; + + + /* AttrSet> */ + checksPerVersion = + lib.listToAttrs ( + builtins.map + (phpName: + let + php = packages.${phpName}; + phpVersion = lib.versions.majorMinor php.version; + checks = import ./checks.nix { + inherit lib php; + inherit (pkgs) runCommand; + }; + supportedChecks = lib.filterAttrs (_name: { enabled ? true, ... }: enabled) checks; + in + { + name = phpName; + value = + lib.mapAttrs + ( + _name: + { + description, + drv, + ... + }: + + drv // { + inherit description; + phpBranch = phpVersion; + } + ) + supportedChecks; + } + ) + phpPackages + ); + in + lib.foldAttrs + lib.mergeAttrs + {} + ( + lib.mapAttrsToList + ( + phpName: + + lib.mapAttrs' + ( + name: + + lib.nameValuePair "${phpName}-${name}" + ) + ) + checksPerVersion + ); } ) // { overlays.default = import ./pkgs/phps.nix nixpkgs.outPath;