From 286067b36d28d76cc8cadcc18170142b3690c8a1 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Wed, 11 May 2022 12:01:27 +0200 Subject: [PATCH 1/3] checks: do not use fake passthru MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Exposing passhtru attributes as the derivation attributes is done by `stdenv.mkDerivation` so if we just add them to the passthru attribute of the resulting derivation attrset, they will be only available inside the passthru attribute. We can just append those attributes to the derivation attrset directly, it won’t affect the derivation either way. --- checks.nix | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/checks.nix b/checks.nix index b322f85d..12b086dc 100644 --- a/checks.nix +++ b/checks.nix @@ -130,9 +130,7 @@ let check = drv args; in check // { - passthru = check.passthru or { } // { - description = "PHP ${phpVersion} – ${description}"; - }; + description = "PHP ${phpVersion} – ${description}"; } ) supportedChecks; From 9c82c8af3cf850e4c6aa8d5f770e6af88b1c4618 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Wed, 11 May 2022 15:11:00 +0200 Subject: [PATCH 2/3] checks: Move most of the code to flake.nix This will basically allow us to treat `checks.nix` like something that supports having its dependencies injected by `callPackages`, allowing us to simplify the expression a bit. It will also allow other scripts to get the check names trivially. --- checks.nix | 228 +++++++++++++++++++---------------------------------- flake.nix | 63 ++++++++++++++- 2 files changed, 143 insertions(+), 148 deletions(-) diff --git a/checks.nix b/checks.nix index 12b086dc..842719f0 100644 --- a/checks.nix +++ b/checks.nix @@ -1,158 +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 // { - 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..b230c02e 100644 --- a/flake.nix +++ b/flake.nix @@ -32,9 +32,66 @@ 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 // { + description = "PHP ${phpVersion} – ${description}"; + } + ) + 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; From 1b245c7c2720487e00b9003775054ea0ed7cbfb9 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Wed, 11 May 2022 12:21:01 +0200 Subject: [PATCH 3/3] ci: Auto-determine checks to run This will allow us to support multiple platforms easily. --- .github/workflows/build.yaml | 72 ++------- .github/workflows/test.yaml | 134 ++++++++++++++++ .../workflows/workflow-from-flake-checks.nix | 151 ++++++++++++++++++ flake.nix | 3 +- 4 files changed, 296 insertions(+), 64 deletions(-) create mode 100644 .github/workflows/test.yaml create mode 100644 .github/workflows/workflow-from-flake-checks.nix 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/flake.nix b/flake.nix index b230c02e..43f9f260 100644 --- a/flake.nix +++ b/flake.nix @@ -66,7 +66,8 @@ }: drv // { - description = "PHP ${phpVersion} – ${description}"; + inherit description; + phpBranch = phpVersion; } ) supportedChecks;