supabase-postgres.git / summary / log / commit / refs

commit    1493ca62cd8023c0c60c157b89eecb76d1b2b3fe
Author:   Yvan Sraka <yvan@sraka.xyz>
Commit:   GitHub <noreply@github.com>
Date:     Mon Dec 08 16:20:41 2025 +0000

    ci: Custom GitHub Runners for Nix Builds (#1745)
    
    * chores(ci): opted-out nix-fast-build
    
    * chores(ci): set up nix-github-actions
    
    * chores(ci): comment out vestigal testinfra-ami-build
    
    * chores(ci): use custom github runners
    
    * chores(ci): use nix-eval-jobs and sets AWS creds to /etc/nix/aws
    
    * feat(ci): do not build if already cached
    
    * chore: improve reproducibility of postgresql builds
    
    Do not create postgresql package that depends on the runtime evaluation context as
    that harms reproducibility.
    
    * chore: remove nix-github-actions dependency
    
    * feat(ci): split nix build workflow into separate extensions and checks jobs
    
    Split the monolithic nix-build job into two workflows:
    one for building PostgreSQL extensions and another for checks.
    
    Building extensions can be resource-intensive and time-consuming, 
    so isolating them allows for better resource allocation and parallelism.
    
    Once they are built, the checks job can run tests and validations
    on the already built extensions.
    
    * feat(ci): extract nix build setup into reusable action and split builds by architecture
    
    Extract AWS credential setup and nix build steps into a composite action
    to reduce duplication. Split extension builds into separate jobs per
    architecture (aarch64-linux, aarch64-darwin, x86_64-linux) and update
    matrix generation to group packages by system.
    
    * fix(ci): do not hide cached builds
    
    * Revert "fix(ci): do not hide cached builds"
    
    This reverts commit 9d41b1e45fd92df646baaf078b9889cf308ac32b.
    
    * chore: Temporarily disable x86_64-linux builds
    
    We don't have a self hosted runner for x86_64-linux at the moment
    
    * fix: sort packages and filter out cached ones
    
    * fix: do not skip checks-matrix if dependencies are skipped
    
    * fix: do not return debug fields in GitHub Actions matrix output
    
    * debugging
    
    * fix(ci): use !cancelled() instead of always() for dependent job conditions
    
    Replace always() with !cancelled() to prevent jobs from running when the workflow
    is cancelled. Add explicit success/skip conditions for dependent jobs to ensure
    proper workflow execution flow.
    
    * fix(ci): stop chaining aws roles
    
    We couldn't set duration to 18000 seconds when chaining roles.
    
    * ci: run nixos test on aarch64-linux
    
    * fix(ci): disable eval-cache and accept-flake-config
    
    * ci: split checks build jobs by system architecture
    
    Refactor GitHub Actions workflow to run build checks in parallel across different
    architectures (aarch64-linux, aarch64-darwin) with separate job matrices.
    
    * fix(ci): use correct architecture name in aarch64-linux builds
    
    * fix(ci): do not try to build already cached checks
    
    * fix(ci): simplify GitHub Actions workflow for Nix builds
    
    Create a single nix-eval job to determine packages to build, removing
    redundant extension and check matrices.
    
    * Revert "chores(ci): comment out vestigal testinfra-ami-build"
    
    This reverts commit e2db36800b8a2a0ad9e132fdad688613aeb5aa37.
    
    * feat(ci): eval on blacksmith-32vcpu-ubuntu-2404
    
    * feat: add ephemeral Nix install action for GitHub runners
    
    * refactor(ci): extract nix eval into reusable workflow
    
    * feat: enable x86_64-linux builds in CI
    
    * feat: add PostgreSQL version to GitHub Actions job names
    
    When building a postgres extension, the build matrix may include
    multiple time the same extension for different PostgreSQL versions.
    This change makes it easier to identify which job corresponds to which PostgreSQL
    version in the workflow runs.
    
    * fix: disable treefmt flake check
    
    treefmt is already included in the pre-commit hooks check.
    
    * feat: run actionlint on new GitHub Actions workflows
    
    * chore: improve github matrix script type annotations
    
    * feat: optimize CI runner selection based on package size
    
    Dynamically assign larger runners (32vcpu) for Rust and PostGIS extensions
    while using smaller runners (8vcpu) for standard packages.
    
    * chore: fix package meta maintainers format
    
    * chore: create a nix package for generating GitHub Actions matrix
    
    Add pytest tests for the package
    Add nix-eval-jobs in path for the package
    
    * fix: configure runner according to the matrix job
    
    The matrix job returns the type of runner, so we can configure the nix
    installation step accordingly.
    
    * Update nix-eval-jobs
    
    Our changes were merged upstream, so we can now track the original
    repository again.
    
    * refactor(ci): standardize nix installation and disable cache push by default
    
    - Replace DeterminateSystems/nix-installer-action with custom nix-install-ephemeral action across all workflows
    - Change default push-to-cache from 'true' to 'false' to prevent unnecessary nix/aws configurations
    - Explicitly enable push-to-cache only for nix-build and nix-eval workflows where caching is beneficial
    
    * feat: use big-parallel to identify large packages
    
    * fix(ci): ensure x86_64-linux build is considered in testinfra and test workflows
    
    * fix: nix devShell inclusion condition
    
    * fix(ci): eval should fail if github-matrix run fails
    
    * fix(ci): remove redundant build psql bundle step
    
    * fix: reduce ARM runner size from 8vcpu to 4vcpu for ephemeral builds
    
    We might not need the full 8vcpu for aarch64-linux builds, so this
    change reduces the runner size to 4vcpu to wait less for available
    blacksmith runners.
    
    * feat: do not return empty matrices if no package has to be built
    
    * feat: fail pipeline if nix evaluation fails
    
    * Update nix/ext/pgvector.nix
    
    Co-authored-by: samrose <samuel@supabase.io>
    
    * fix: add skip job only for systems that don't have any job
    
    * fix(github-matrix): handle evaluation errors without deadlock
    
    Fix github-matrix that would hang when nix-eval-jobs encountered errors due to subprocess pipe deadlock - stderr buffer would fill while reading stdout.
    
    This change ensure that evaluation errors are visible and the workflow fails properly while still showing which packages succeeded.
    
    * feat(github-matrix): integrate github-action-utils for better error visibility
    
    Integrates github-action-utils library to improve error and warning
    visibility in GitHub Actions UI through workflow command annotations.
    
    * feat(github-matrix): group evaluation errors by message
    
    Refactor error handling to collect and group evaluation errors similar to warnings. Errors with the same message are now displayed together with a list of affected attributes.
    
    * fix(github-matrix): improve multiline error display in GitHub Actions
    
    Extract core error messages and format them better for GitHub Actions
    annotations.
    
    * fix(ci): skip run-testinfra and run-tests when nix-eval fails
    
    Add nix-eval to needs dependencies and check its result in conditional expressions to prevent downstream test jobs from running when evaluation fails.
    
    * chore(github-matrix): update message when there are no build for a system
    
    * fix(github-matrix): backward compatibility for Result access
    
    We are running an older version of the 'result' library that uses
    '_value' instead of 'ok_value' to access the successful result of a
    computation.
    
    * refactor: migrate from packages to legacyPackages for PostgreSQL extensions
    
    To be able to build extensions versions packages separately in CI, we
    need to expose them in a nested structure. It is currently not possible
    to do so with the flattened packages structure, as the individual
    extension packages are not directly accessible.
    
    In this change, we replace the flattened package structure with nested
    legacyPackages to improve discoverability of individual extension
    packages.
    
    * refactor(nix): remove "-all" suffix from extension package names
    
    Simplify extension package naming by removing the redundant "-all" suffix that was appended to pname attributes.
    
    * refactor(ci): split nix build jobs into separate packages and checks workflows
    
    To make sure we only build what is necessary, we start building packages first, 
    then run checks once all packages are built successfully.
    
    * feat: use 8 vCPU runner for aarch64 builds
    
    Use the same 8 vCPU runner for aarch64 builds as used for x86_64 builds to improve build performance.
    
    * feat(ci): test blacksmith stickydisk for eval
    
    ---------
    
    Co-authored-by: Jean-François Roche <jfroche@pyxel.be>
    Co-authored-by: samrose <samuel@supabase.io>


.github/actionlint.yaml | 5 + .github/actions/nix-install-self-hosted/action.yml | 30 ++ .github/workflows/nix-build.yml | 236 +++++++++--- .github/workflows/nix-eval.yml | 54 +++ flake.lock | 148 +++++++- flake.nix | 1 + nix/checks.nix | 26 +- nix/docs/adding-new-package.md | 2 +- nix/ext/hypopg.nix | 3 +- nix/ext/index_advisor.nix | 3 +- nix/ext/pg-safeupdate.nix | 3 +- nix/ext/pg_cron/default.nix | 1 - nix/ext/pg_graphql/default.nix | 10 +- nix/ext/pg_hashids.nix | 3 +- nix/ext/pg_jsonschema/default.nix | 10 +- nix/ext/pg_net.nix | 3 +- nix/ext/pg_plan_filter.nix | 3 +- nix/ext/pg_repack.nix | 3 +- nix/ext/pg_stat_monitor.nix | 3 +- nix/ext/pg_tle.nix | 3 +- nix/ext/pgaudit.nix | 3 +- nix/ext/pgjwt.nix | 3 +- nix/ext/pgmq/default.nix | 3 +- nix/ext/pgroonga/default.nix | 3 +- nix/ext/pgrouting.nix | 3 +- nix/ext/pgsodium.nix | 3 +- nix/ext/pgsql-http.nix | 3 +- nix/ext/pgvector.nix | 4 +- nix/ext/plpgsql-check.nix | 1 - nix/ext/plv8/default.nix | 3 +- nix/ext/postgis.nix | 10 +- nix/ext/rum.nix | 3 +- nix/ext/tests/default.nix | 3 +- nix/ext/tests/http.nix | 3 +- nix/ext/tests/orioledb.nix | 2 +- nix/ext/tests/pg_plan_filter.nix | 3 +- nix/ext/tests/pg_repack.nix | 3 +- nix/ext/tests/pg_safeupdate.nix | 3 +- nix/ext/tests/pgjwt.nix | 3 +- nix/ext/tests/pgmq.nix | 3 +- nix/ext/tests/pgroonga.nix | 3 +- nix/ext/tests/pgrouting.nix | 10 +- nix/ext/tests/pgsodium.nix | 5 +- nix/ext/tests/plpgsql_check.nix | 3 +- nix/ext/tests/plv8.nix | 3 +- nix/ext/tests/postgis.nix | 3 +- nix/ext/tests/timescaledb.nix | 3 +- nix/ext/tests/vault.nix | 5 +- nix/ext/timescaledb.nix | 1 - nix/ext/vault.nix | 3 +- nix/ext/wal2json.nix | 3 +- nix/ext/wrappers/default.nix | 22 +- nix/fmt.nix | 1 + nix/hooks.nix | 15 + nix/packages/default.nix | 5 +- nix/packages/github-matrix/default.nix | 51 +++ nix/packages/github-matrix/github_matrix.py | 396 +++++++++++++++++++++ .../github-matrix/tests/test_github_matrix.py | 262 ++++++++++++++ nix/packages/postgres.nix | 46 ++- nix/postgresql/generic.nix | 10 +- 60 files changed, 1281 insertions(+), 184 deletions(-) diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 00000000..6eea24e6 --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,5 @@ +self-hosted-runner: + labels: + - aarch64-darwin + - aarch64-linux + - blacksmith-32vcpu-ubuntu-2404 diff --git a/.github/actions/nix-install-self-hosted/action.yml b/.github/actions/nix-install-self-hosted/action.yml new file mode 100644 index 00000000..52e49db9 --- /dev/null +++ b/.github/actions/nix-install-self-hosted/action.yml @@ -0,0 +1,30 @@ +name: 'Configure Nix on self hosted runners' +description: 'Sets up AWS credentials to push to the Nix binary cache' +inputs: + aws-role-duration: + description: 'AWS role session duration in seconds' + required: false + default: '18000' + +runs: + using: 'composite' + steps: + - name: aws-creds + uses: aws-actions/configure-aws-credentials@v4.3.1 + with: + disable-retry: true + aws-region: us-east-2 + role-to-assume: arn:aws:iam::436098097459:role/nix-artifacts-deploy-role # supabase-dev + role-session-name: gha-oidc-${{ github.run_id }} + role-duration-seconds: ${{ inputs.aws-role-duration }} + + - name: Write creds files + shell: bash + run: | + umask 006 + cat > /etc/nix/aws/nix-aws-credentials <<EOF + [ci-uploader] + aws_access_key_id = ${AWS_ACCESS_KEY_ID} + aws_secret_access_key = ${AWS_SECRET_ACCESS_KEY} + aws_session_token = ${AWS_SESSION_TOKEN} + EOF diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 0a5d5180..c1f9c35f 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -14,77 +14,201 @@ permissions: contents: write packages: write -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - jobs: - build-run-image: + nix-eval: + uses: ./.github/workflows/nix-eval.yml + secrets: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} + NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} + + nix-build-packages-aarch64-linux: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (aarch64-linux) + needs: nix-eval + runs-on: ${{ matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).aarch64_linux != null }} + strategy: + fail-fast: false + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).aarch64_linux }} + steps: + - name: Checkout Repo + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix (ephemeral) + if: ${{ matrix.attr != '' && matrix.runs_on.group != 'self-hosted-runners-nix' }} + uses: ./.github/actions/nix-install-ephemeral + with: + push-to-cache: 'true' + env: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} + NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} + - name: Install nix (self-hosted) + if: ${{ matrix.attr != '' && matrix.runs_on.group == 'self-hosted-runners-nix' }} + uses: ./.github/actions/nix-install-self-hosted + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} + + nix-build-checks-aarch64-linux: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (aarch64-linux) + needs: [nix-eval, nix-build-packages-aarch64-linux] + runs-on: ${{ matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).aarch64_linux != null }} + strategy: + fail-fast: false + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).aarch64_linux }} + steps: + - name: Checkout Repo + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix (ephemeral) + if: ${{ matrix.attr != '' && matrix.runs_on.group != 'self-hosted-runners-nix' }} + uses: ./.github/actions/nix-install-ephemeral + with: + push-to-cache: 'true' + env: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} + NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} + - name: Install nix (self-hosted) + if: ${{ matrix.attr != '' && matrix.runs_on.group == 'self-hosted-runners-nix' }} + uses: ./.github/actions/nix-install-self-hosted + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} + + nix-build-packages-aarch64-darwin: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (aarch64-darwin) + needs: nix-eval + runs-on: ${{ matrix.attr != '' && matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).aarch64_darwin != null }} + strategy: + fail-fast: false + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).aarch64_darwin }} + steps: + - name: Checkout Repo + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix + if: ${{ matrix.attr != '' }} + uses: ./.github/actions/nix-install-self-hosted + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} + + nix-build-checks-aarch64-darwin: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (aarch64-darwin) + needs: [nix-eval, nix-build-packages-aarch64-darwin] + runs-on: ${{ matrix.attr != '' && matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).aarch64_darwin != null }} + strategy: + fail-fast: false + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).aarch64_darwin }} + steps: + - name: Checkout Repo + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix + if: ${{ matrix.attr != '' }} + uses: ./.github/actions/nix-install-self-hosted + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} + + nix-build-packages-x86_64-linux: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (x86_64-linux) + needs: nix-eval + runs-on: ${{ matrix.attr != '' && matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).x86_64_linux != null }} strategy: fail-fast: false - matrix: - include: - - runner: blacksmith-32vcpu-ubuntu-2404 - arch: amd64 - - runner: blacksmith-32vcpu-ubuntu-2404-arm - arch: arm64 - - runner: macos-latest-xlarge - arch: arm64 - runs-on: ${{ matrix.runner }} - timeout-minutes: 180 + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.packages_matrix).x86_64_linux }} steps: - name: Checkout Repo - uses: supabase/postgres/.github/actions/shared-checkout@HEAD - - uses: ./.github/actions/nix-install-ephemeral + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix + if: ${{ matrix.attr != '' }} + uses: ./.github/actions/nix-install-ephemeral with: - push-to-cache: ${{ github.secret_source == 'Actions' && 'true' || 'false' }} + push-to-cache: 'true' env: DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} - - name: Aggressive disk cleanup for DuckDB build - if: matrix.runner == 'macos-latest-xlarge' - run: | - nix --version - echo "=== BEFORE CLEANUP ===" - df -h - # Remove major space consumers - sudo rm -rf /usr/share/dotnet || true - sudo rm -rf /usr/local/lib/android || true - sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform || true - sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/watchOS.platform || true - sudo rm -rf /Applications/Xcode.app/Contents/Developer/Platforms/tvOS.platform || true - # Clean everything possible - sudo rm -rf /opt/ghc || true - sudo rm -rf /usr/local/share/boost || true - sudo rm -rf /opt/homebrew || true - sudo xcrun simctl delete all 2>/dev/null || true - # Aggressive cache cleanup - sudo rm -rf /System/Library/Caches/* 2>/dev/null || true - sudo rm -rf /Library/Caches/* 2>/dev/null || true - sudo rm -rf ~/Library/Caches/* 2>/dev/null || true - sudo rm -rf /private/var/log/* 2>/dev/null || true - sudo rm -rf /tmp/* 2>/dev/null || true - echo "=== AFTER CLEANUP ===" - df -h - - - name: Build psql bundle - run: > - nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48" - -- --skip-cached --no-nom ${{ matrix.runner == 'macos-latest-xlarge' && '--max-jobs 1' || '' }} --copy-to "s3://nix-postgres-artifacts?secret-key=/etc/nix/nix-secret-key" - --flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')" + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} + + nix-build-checks-x86_64-linux: + name: >- + ${{ matrix.name }}${{ matrix.postgresql_version && format(' - Postgres {0}', matrix.postgresql_version) || '' }} + (x86_64-linux) + needs: [nix-eval, nix-build-packages-x86_64-linux] + runs-on: ${{ matrix.attr != '' && matrix.runs_on.group && matrix.runs_on || matrix.runs_on.labels }} + if: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).x86_64_linux != null }} + strategy: + fail-fast: false + max-parallel: 5 + matrix: ${{ fromJSON(needs.nix-eval.outputs.checks_matrix).x86_64_linux }} + steps: + - name: Checkout Repo + if: ${{ matrix.attr != '' }} + uses: actions/checkout@v4 + - name: Install nix + if: ${{ matrix.attr != '' }} + uses: ./.github/actions/nix-install-ephemeral + with: + push-to-cache: 'true' env: - AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} - AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }} + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} + NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} + - name: nix build + if: ${{ matrix.attr != '' }} + shell: bash + run: nix build --accept-flake-config -L .#${{ matrix.attr }} run-testinfra: - needs: build-run-image - if: ${{ success() }} + needs: [nix-eval, nix-build-packages-aarch64-linux, nix-build-checks-aarch64-linux, nix-build-packages-aarch64-darwin, nix-build-checks-aarch64-darwin, nix-build-packages-x86_64-linux, nix-build-checks-x86_64-linux] + if: | + !cancelled() && + needs.nix-eval.result == 'success' && + (needs.nix-build-packages-aarch64-linux.result == 'skipped' || needs.nix-build-packages-aarch64-linux.result == 'success') && + (needs.nix-build-checks-aarch64-linux.result == 'skipped' || needs.nix-build-checks-aarch64-linux.result == 'success') && + (needs.nix-build-packages-aarch64-darwin.result == 'skipped' || needs.nix-build-packages-aarch64-darwin.result == 'success') && + (needs.nix-build-checks-aarch64-darwin.result == 'skipped' || needs.nix-build-checks-aarch64-darwin.result == 'success') && + (needs.nix-build-packages-x86_64-linux.result == 'skipped' || needs.nix-build-packages-x86_64-linux.result == 'success') && + (needs.nix-build-checks-x86_64-linux.result == 'skipped' || needs.nix-build-checks-x86_64-linux.result == 'success') uses: ./.github/workflows/testinfra-ami-build.yml secrets: DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} run-tests: - needs: build-run-image - if: ${{ success() }} + needs: [nix-eval, nix-build-packages-aarch64-linux, nix-build-checks-aarch64-linux, nix-build-packages-aarch64-darwin, nix-build-checks-aarch64-darwin, nix-build-packages-x86_64-linux, nix-build-checks-x86_64-linux] + if: | + !cancelled() && + needs.nix-eval.result == 'success' && + (needs.nix-build-packages-aarch64-linux.result == 'skipped' || needs.nix-build-packages-aarch64-linux.result == 'success') && + (needs.nix-build-checks-aarch64-linux.result == 'skipped' || needs.nix-build-checks-aarch64-linux.result == 'success') && + (needs.nix-build-packages-aarch64-darwin.result == 'skipped' || needs.nix-build-packages-aarch64-darwin.result == 'success') && + (needs.nix-build-checks-aarch64-darwin.result == 'skipped' || needs.nix-build-checks-aarch64-darwin.result == 'success') && + (needs.nix-build-packages-x86_64-linux.result == 'skipped' || needs.nix-build-packages-x86_64-linux.result == 'success') && + (needs.nix-build-checks-x86_64-linux.result == 'skipped' || needs.nix-build-checks-x86_64-linux.result == 'success') uses: ./.github/workflows/test.yml diff --git a/.github/workflows/nix-eval.yml b/.github/workflows/nix-eval.yml new file mode 100644 index 00000000..c8967a63 --- /dev/null +++ b/.github/workflows/nix-eval.yml @@ -0,0 +1,54 @@ +name: Nix Eval + +on: + workflow_call: + outputs: + packages_matrix: + description: 'Generated build matrix for packages' + value: ${{ jobs.eval.outputs.packages_matrix }} + checks_matrix: + description: 'Generated build matrix for checks' + value: ${{ jobs.eval.outputs.checks_matrix }} + secrets: + DEV_AWS_ROLE: + required: false + NIX_SIGN_SECRET_KEY: + required: false + +jobs: + eval: + runs-on: blacksmith-32vcpu-ubuntu-2404 + outputs: + packages_matrix: ${{ steps.set-matrix.outputs.packages_matrix }} + checks_matrix: ${{ steps.set-matrix.outputs.checks_matrix }} + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Install nix + uses: ./.github/actions/nix-install-ephemeral + with: + push-to-cache: 'true' + env: + DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }} + NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }} + - name: Restart Nix Daemon + run: | + sudo mv /nix/var/nix/daemon-socket/socket /tmp + - name: Mount Nix cache disk + uses: useblacksmith/stickydisk@v1 + with: + key: ${{ github.repository }}-nix-cache-eval-${{ runner.os }} + path: /nix + - name: Restart Nix Daemon + run: | + sudo systemctl restart nix-daemon.service nix-daemon.socket + - id: set-matrix + name: Generate Nix Matrix + run: | + set -Eeu -o pipefail + nix run --accept-flake-config .\#github-matrix -- checks legacyPackages + + sudo systemctl stop nix-daemon.socket || true + sudo systemctl stop nix-daemon.service || true + sudo pkill -9 nix-daemon || true + sleep 2 diff --git a/flake.lock b/flake.lock index b2d4ff6e..a28edf94 100644 --- a/flake.lock +++ b/flake.lock @@ -34,6 +34,27 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nix-eval-jobs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1759362264, + "narHash": "sha256-wfG0S7pltlYyZTM+qqlhJ7GMw2fTF4mLKCIVhLii/4M=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "758cf7296bee11f1706a574c77d072b8a7baa881", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -95,6 +116,22 @@ "type": "github" } }, + "nix": { + "flake": false, + "locked": { + "lastModified": 1760472641, + "narHash": "sha256-BuKtM7Vr5EcxBXxUENBQPlOBwmNd5mkTRkSmlJi/iQ4=", + "owner": "NixOS", + "repo": "nix", + "rev": "4041bfdb401ad6d1c31a292fab90392254be506a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nix", + "type": "github" + } + }, "nix-editor": { "inputs": { "nixpkgs": [ @@ -131,11 +168,11 @@ ] }, "locked": { - "lastModified": 1749427739, - "narHash": "sha256-Nm0oMqFNRnJsiZYeNChmefmjeVCOzngikpSQhgs7iXI=", + "lastModified": 1763868605, + "narHash": "sha256-wO8Lk66GPQeSpzXUzXCBpe2Pj1De17xByrROXxnwIPY=", "owner": "Mic92", "repo": "nix-fast-build", - "rev": "b1dae483ab7d4139a6297e02b6de9e5d30e43d48", + "rev": "0c7fd47fb587250e931a01c6645ab5c0cd737af8", "type": "github" }, "original": { @@ -144,6 +181,27 @@ "type": "github" } }, + "nix-eval-jobs": { + "inputs": { + "flake-parts": "flake-parts_2", + "nix": "nix", + "nixpkgs": "nixpkgs_2", + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1760478325, + "narHash": "sha256-hA+NOH8KDcsuvH7vJqSwk74PyZP3MtvI/l+CggZcnTc=", + "owner": "nix-community", + "repo": "nix-eval-jobs", + "rev": "daa42f9e9c84aeff1e325dd50fda321f53dfd02c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-eval-jobs", + "type": "github" + } + }, "nix2container": { "inputs": { "flake-utils": [ @@ -230,6 +288,66 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 315532800, + "narHash": "sha256-vhAtaRMIQiEghARviANBmSnhGz9Qf2IQJ+nQgsDXnVs=", + "rev": "c12c63cd6c5eb34c7b4c3076c6a99e00fcab86ec", + "type": "tarball", + "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre877036.c12c63cd6c5e/nixexprs.tar.xz" + }, + "original": { + "type": "tarball", + "url": "https://nixos.org/channels/nixpkgs-unstable/nixexprs.tar.xz" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1697269602, + "narHash": "sha256-dSzV7Ud+JH4DPVD9od53EgDrxUVQOcSj4KGjggCDVJI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9cb540e9c1910d74a7e10736277f6eb9dff51c81", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1712666087, + "narHash": "sha256-WwjUkWsjlU8iUImbivlYxNyMB1L5YVqE8QotQdL9jWc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a76c4553d7e741e17f289224eda135423de0491d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-parts": "flake-parts", @@ -239,10 +357,11 @@ "nix-fast-build": "nix-fast-build", "nix2container": "nix2container", "nixpkgs": "nixpkgs", + "nix-eval-jobs": "nix-eval-jobs", "nixpkgs-go124": "nixpkgs-go124", "nixpkgs-pgbackrest": "nixpkgs-pgbackrest", "rust-overlay": "rust-overlay", - "treefmt-nix": "treefmt-nix" + "treefmt-nix": "treefmt-nix_2" } }, "rust-overlay": { @@ -281,6 +400,27 @@ } }, "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nix-eval-jobs", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1760120816, + "narHash": "sha256-gq9rdocpmRZCwLS5vsHozwB6b5nrOBDNc2kkEaTXHfg=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "761ae7aff00907b607125b2f57338b74177697ed", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "treefmt-nix_2": { "inputs": { "nixpkgs": [ "nixpkgs" diff --git a/flake.nix b/flake.nix index 8f83a0a2..efd0b7e9 100644 --- a/flake.nix +++ b/flake.nix @@ -28,6 +28,7 @@ git-hooks.inputs.nixpkgs.follows = "nixpkgs"; nixpkgs-go124.url = "github:Nixos/nixpkgs/d2ac4dfa61fba987a84a0a81555da57ae0b9a2b0"; nixpkgs-pgbackrest.url = "github:nixos/nixpkgs/nixos-unstable-small"; + nix-eval-jobs.url = "github:nix-community/nix-eval-jobs"; }; outputs = diff --git a/nix/checks.nix b/nix/checks.nix index 0bc5261b..81e0b411 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -88,7 +88,7 @@ builtins.trace "Major version result: ${result}" result; # Select the appropriate pgroonga package for this PostgreSQL version - pgroonga = self'.packages."psql_${majorVersion}/exts/pgroonga-all"; + pgroonga = self'.legacyPackages."psql_${majorVersion}".exts.pgroonga; pgPort = if (majorVersion == "17") then @@ -396,24 +396,22 @@ pg_regress ; } - // pkgs.lib.optionalAttrs (system == "aarch64-linux") { - inherit (self'.packages) - postgresql_15_debug - postgresql_15_src - postgresql_orioledb-17_debug - postgresql_orioledb-17_src - postgresql_17_debug - postgresql_17_src - ; - } - // pkgs.lib.optionalAttrs (system == "x86_64-linux") ( + // pkgs.lib.optionalAttrs (system == "aarch64-linux") ( { - devShell = self'.devShells.default; + inherit (self'.packages) + postgresql_15_debug + postgresql_15_src + postgresql_orioledb-17_debug + postgresql_orioledb-17_src + postgresql_17_debug + postgresql_17_src + ; } // (import ./ext/tests { inherit self; inherit pkgs; }) - ); + ) + // pkgs.lib.optionalAttrs (system == "x86_64-linux") ({ devShell = self'.devShells.default; }); }; } diff --git a/nix/docs/adding-new-package.md b/nix/docs/adding-new-package.md index 7d9fbdae..d5620de0 100644 --- a/nix/docs/adding-new-package.md +++ b/nix/docs/adding-new-package.md @@ -42,7 +42,7 @@ stdenv.mkDerivation rec { meta = with lib; { description = "Open-source vector similarity search for Postgres"; homepage = "https://github.com/${src.owner}/${src.repo}"; - maintainers = with maintainers; [ olirice ]; + maintainers = [ "olirice" ]; platforms = postgresql.meta.platforms; license = licenses.postgresql; }; diff --git a/nix/ext/hypopg.nix b/nix/ext/hypopg.nix index 28e847d4..92784a8d 100644 --- a/nix/ext/hypopg.nix +++ b/nix/ext/hypopg.nix @@ -87,8 +87,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/index_advisor.nix b/nix/ext/index_advisor.nix index 9e6a54ae..85a23bfd 100644 --- a/nix/ext/index_advisor.nix +++ b/nix/ext/index_advisor.nix @@ -78,8 +78,7 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pg-safeupdate.nix b/nix/ext/pg-safeupdate.nix index bc343037..ee31f437 100644 --- a/nix/ext/pg-safeupdate.nix +++ b/nix/ext/pg-safeupdate.nix @@ -74,8 +74,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; defaultSettings = { shared_preload_libraries = [ "safeupdate" ]; }; diff --git a/nix/ext/pg_cron/default.nix b/nix/ext/pg_cron/default.nix index 75215d56..cec9d8ec 100644 --- a/nix/ext/pg_cron/default.nix +++ b/nix/ext/pg_cron/default.nix @@ -110,7 +110,6 @@ buildEnv { passthru = { inherit versions numberOfVersions switch-ext-version; - pname = "${pname}-all"; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ "pg_cron" ]; diff --git a/nix/ext/pg_graphql/default.nix b/nix/ext/pg_graphql/default.nix index d944d5ed..a7f6d106 100644 --- a/nix/ext/pg_graphql/default.nix +++ b/nix/ext/pg_graphql/default.nix @@ -129,7 +129,7 @@ let lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) supportedVersions ); in -buildEnv { +(buildEnv { name = pname; paths = packages; pathsToLink = [ @@ -172,9 +172,11 @@ buildEnv { ) ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; -} +}).overrideAttrs + (_: { + requiredSystemFeatures = [ "big-parallel" ]; + }) diff --git a/nix/ext/pg_hashids.nix b/nix/ext/pg_hashids.nix index 79bba3dc..b11c5ce6 100644 --- a/nix/ext/pg_hashids.nix +++ b/nix/ext/pg_hashids.nix @@ -93,8 +93,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pg_jsonschema/default.nix b/nix/ext/pg_jsonschema/default.nix index 74742bed..1a2e8ee5 100644 --- a/nix/ext/pg_jsonschema/default.nix +++ b/nix/ext/pg_jsonschema/default.nix @@ -130,7 +130,7 @@ let lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) supportedVersions ); in -pkgs.buildEnv { +(pkgs.buildEnv { name = pname; paths = packages; pathsToLink = [ @@ -165,9 +165,11 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; -} +}).overrideAttrs + (_: { + requiredSystemFeatures = [ "big-parallel" ]; + }) diff --git a/nix/ext/pg_net.nix b/nix/ext/pg_net.nix index 62dad438..229971a8 100644 --- a/nix/ext/pg_net.nix +++ b/nix/ext/pg_net.nix @@ -116,8 +116,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ "pg_net" ]; diff --git a/nix/ext/pg_plan_filter.nix b/nix/ext/pg_plan_filter.nix index 4e52bf22..dfb3262b 100644 --- a/nix/ext/pg_plan_filter.nix +++ b/nix/ext/pg_plan_filter.nix @@ -75,8 +75,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; defaultSettings = { shared_preload_libraries = [ "plan_filter" ]; }; diff --git a/nix/ext/pg_repack.nix b/nix/ext/pg_repack.nix index 4a62b68b..153cebd7 100644 --- a/nix/ext/pg_repack.nix +++ b/nix/ext/pg_repack.nix @@ -129,8 +129,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pg_stat_monitor.nix b/nix/ext/pg_stat_monitor.nix index 2a2ce009..ddf46de3 100644 --- a/nix/ext/pg_stat_monitor.nix +++ b/nix/ext/pg_stat_monitor.nix @@ -97,8 +97,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pg_tle.nix b/nix/ext/pg_tle.nix index f2fc5d1d..7101952a 100644 --- a/nix/ext/pg_tle.nix +++ b/nix/ext/pg_tle.nix @@ -100,8 +100,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; defaultSettings = { shared_preload_libraries = [ "pg_tle" ]; }; diff --git a/nix/ext/pgaudit.nix b/nix/ext/pgaudit.nix index 9953e12f..7660f2bd 100644 --- a/nix/ext/pgaudit.nix +++ b/nix/ext/pgaudit.nix @@ -231,8 +231,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); defaultSettings = { diff --git a/nix/ext/pgjwt.nix b/nix/ext/pgjwt.nix index 72f1614d..6bac9dcd 100644 --- a/nix/ext/pgjwt.nix +++ b/nix/ext/pgjwt.nix @@ -77,8 +77,7 @@ buildEnv { pathsToLink = [ "/share/postgresql/extension" ]; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgmq/default.nix b/nix/ext/pgmq/default.nix index 32a7354e..51830821 100644 --- a/nix/ext/pgmq/default.nix +++ b/nix/ext/pgmq/default.nix @@ -99,11 +99,10 @@ buildEnv { pathsToLink = [ "/share/postgresql/extension" ]; passthru = { - inherit versions numberOfVersions; + inherit versions numberOfVersions pname; defaultSettings = { search_path = "\"$user\", public, auth, extensions"; }; - pname = "${pname}-all"; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgroonga/default.nix b/nix/ext/pgroonga/default.nix index 55c0abed..22a8c2df 100644 --- a/nix/ext/pgroonga/default.nix +++ b/nix/ext/pgroonga/default.nix @@ -170,8 +170,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgrouting.nix b/nix/ext/pgrouting.nix index b20b89c4..48833791 100644 --- a/nix/ext/pgrouting.nix +++ b/nix/ext/pgrouting.nix @@ -136,8 +136,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgsodium.nix b/nix/ext/pgsodium.nix index 5c8b07df..fa111d8a 100644 --- a/nix/ext/pgsodium.nix +++ b/nix/ext/pgsodium.nix @@ -101,8 +101,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgsql-http.nix b/nix/ext/pgsql-http.nix index ba669e22..3ad03b80 100644 --- a/nix/ext/pgsql-http.nix +++ b/nix/ext/pgsql-http.nix @@ -103,8 +103,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/pgvector.nix b/nix/ext/pgvector.nix index fa6dba77..bcf86ebf 100644 --- a/nix/ext/pgvector.nix +++ b/nix/ext/pgvector.nix @@ -69,7 +69,6 @@ let meta = with lib; { description = "Open-source vector similarity search for Postgres"; homepage = "https://github.com/${src.owner}/${src.repo}"; - maintainers = with maintainers; [ olirice ]; platforms = postgresql.meta.platforms; license = licenses.postgresql; }; @@ -84,8 +83,7 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); pgRegressTestName = "pgvector"; diff --git a/nix/ext/plpgsql-check.nix b/nix/ext/plpgsql-check.nix index dc4cd946..2ee225ca 100644 --- a/nix/ext/plpgsql-check.nix +++ b/nix/ext/plpgsql-check.nix @@ -131,7 +131,6 @@ buildEnv { passthru = { inherit versions numberOfVersions switch-ext-version; - pname = "${pname}-all"; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ diff --git a/nix/ext/plv8/default.nix b/nix/ext/plv8/default.nix index 188ad99b..d858405e 100644 --- a/nix/ext/plv8/default.nix +++ b/nix/ext/plv8/default.nix @@ -240,8 +240,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/postgis.nix b/nix/ext/postgis.nix index ed1b738e..cdf48fb2 100644 --- a/nix/ext/postgis.nix +++ b/nix/ext/postgis.nix @@ -179,7 +179,7 @@ let }; }; in -buildEnv { +(buildEnv { name = pname; paths = packages; @@ -204,9 +204,11 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; -} +}).overrideAttrs + (_: { + requiredSystemFeatures = [ "big-parallel" ]; + }) diff --git a/nix/ext/rum.nix b/nix/ext/rum.nix index f0839241..6a9492e3 100644 --- a/nix/ext/rum.nix +++ b/nix/ext/rum.nix @@ -94,8 +94,7 @@ buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); }; diff --git a/nix/ext/tests/default.nix b/nix/ext/tests/default.nix index a3e67d6d..57644ee7 100644 --- a/nix/ext/tests/default.nix +++ b/nix/ext/tests/default.nix @@ -11,7 +11,8 @@ let pname = extension_name; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/http.nix b/nix/ext/tests/http.nix index 09075c37..f465da25 100644 --- a/nix/ext/tests/http.nix +++ b/nix/ext/tests/http.nix @@ -3,7 +3,8 @@ let pname = "http"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/orioledb.nix b/nix/ext/tests/orioledb.nix index a6f5484c..7d0475ce 100644 --- a/nix/ext/tests/orioledb.nix +++ b/nix/ext/tests/orioledb.nix @@ -11,7 +11,7 @@ let paths = [ postgresql postgresql.lib - self.packages.${pkgs.system}."psql_orioledb-17/exts/orioledb" + (self.legacyPackages.${pkgs.system}."psql_orioledb-17".exts.orioledb) ]; passthru = { inherit (postgresql) version psqlSchema; diff --git a/nix/ext/tests/pg_plan_filter.nix b/nix/ext/tests/pg_plan_filter.nix index fe007377..c9efb480 100644 --- a/nix/ext/tests/pg_plan_filter.nix +++ b/nix/ext/tests/pg_plan_filter.nix @@ -3,7 +3,8 @@ let pname = "plan_filter"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pg_repack.nix b/nix/ext/tests/pg_repack.nix index dae534d2..ff06a9b4 100644 --- a/nix/ext/tests/pg_repack.nix +++ b/nix/ext/tests/pg_repack.nix @@ -3,7 +3,8 @@ let pname = "pg_repack"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pg_safeupdate.nix b/nix/ext/tests/pg_safeupdate.nix index 19a0132a..1c7e09c7 100644 --- a/nix/ext/tests/pg_safeupdate.nix +++ b/nix/ext/tests/pg_safeupdate.nix @@ -3,7 +3,8 @@ let pname = "safeupdate"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pgjwt.nix b/nix/ext/tests/pgjwt.nix index 98884f4c..ef2e6b93 100644 --- a/nix/ext/tests/pgjwt.nix +++ b/nix/ext/tests/pgjwt.nix @@ -3,7 +3,8 @@ let pname = "pgjwt"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pgmq.nix b/nix/ext/tests/pgmq.nix index 94438d61..b0c43292 100644 --- a/nix/ext/tests/pgmq.nix +++ b/nix/ext/tests/pgmq.nix @@ -3,7 +3,8 @@ let pname = "pgmq"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pgroonga.nix b/nix/ext/tests/pgroonga.nix index 83af20ac..abfef880 100644 --- a/nix/ext/tests/pgroonga.nix +++ b/nix/ext/tests/pgroonga.nix @@ -3,7 +3,8 @@ let pname = "pgroonga"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/pgrouting.nix b/nix/ext/tests/pgrouting.nix index f8775e4a..f4550b57 100644 --- a/nix/ext/tests/pgrouting.nix +++ b/nix/ext/tests/pgrouting.nix @@ -3,7 +3,8 @@ let pname = "pgrouting"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: @@ -16,10 +17,11 @@ let postgresql postgresql.lib (installedExtension majorVersion) - self.packages.${pkgs.system}."psql_${majorVersion}/exts/postgis-all" + (self.legacyPackages.${pkgs.system}."psql_${majorVersion}".exts.postgis) ] - ++ lib.optional (postgresql.isOrioleDB - ) self.packages.${pkgs.system}."psql_orioledb-17/exts/orioledb"; + ++ lib.optional (postgresql.isOrioleDB) ( + self.legacyPackages.${pkgs.system}."psql_orioledb-17".exts.orioledb + ); passthru = { inherit (postgresql) version psqlSchema; lib = pkg; diff --git a/nix/ext/tests/pgsodium.nix b/nix/ext/tests/pgsodium.nix index 9ad1aec4..0eae3c0a 100644 --- a/nix/ext/tests/pgsodium.nix +++ b/nix/ext/tests/pgsodium.nix @@ -3,7 +3,8 @@ let pname = "pgsodium"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: @@ -15,7 +16,7 @@ let postgresql postgresql.lib (installedExtension majorVersion) - self.packages.${pkgs.system}."psql_${majorVersion}/exts/hypopg-all" + (self.legacyPackages.${pkgs.system}."psql_${majorVersion}".exts.hypopg) ]; passthru = { inherit (postgresql) version psqlSchema; diff --git a/nix/ext/tests/plpgsql_check.nix b/nix/ext/tests/plpgsql_check.nix index 105ed8a8..4d964ad9 100644 --- a/nix/ext/tests/plpgsql_check.nix +++ b/nix/ext/tests/plpgsql_check.nix @@ -3,7 +3,8 @@ let pname = "plpgsql_check"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/plv8.nix b/nix/ext/tests/plv8.nix index 085ddd42..26a34963 100644 --- a/nix/ext/tests/plv8.nix +++ b/nix/ext/tests/plv8.nix @@ -4,7 +4,8 @@ let pname = "plv8"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/postgis.nix b/nix/ext/tests/postgis.nix index ab6a4b3f..f20e2de2 100644 --- a/nix/ext/tests/postgis.nix +++ b/nix/ext/tests/postgis.nix @@ -3,7 +3,8 @@ let pname = "postgis"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/timescaledb.nix b/nix/ext/tests/timescaledb.nix index 1bab187d..0cea7a50 100644 --- a/nix/ext/tests/timescaledb.nix +++ b/nix/ext/tests/timescaledb.nix @@ -3,7 +3,8 @@ let pname = "timescaledb"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = (installedExtension "15").versions; postgresqlWithExtension = postgresql: diff --git a/nix/ext/tests/vault.nix b/nix/ext/tests/vault.nix index 7b16247a..a3f9cb24 100644 --- a/nix/ext/tests/vault.nix +++ b/nix/ext/tests/vault.nix @@ -3,7 +3,8 @@ let pname = "supabase_vault"; inherit (pkgs) lib; installedExtension = - postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all"; + postgresMajorVersion: + self.legacyPackages.${pkgs.system}."psql_${postgresMajorVersion}".exts."${pname}"; versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions; postgresqlWithExtension = postgresql: @@ -15,7 +16,7 @@ let postgresql postgresql.lib (installedExtension majorVersion) - self.packages.${pkgs.system}."psql_${majorVersion}/exts/pgsodium-all" # dependency + (self.legacyPackages.${pkgs.system}."psql_${majorVersion}".exts.pgsodium) # dependency ]; passthru = { inherit (postgresql) version psqlSchema; diff --git a/nix/ext/timescaledb.nix b/nix/ext/timescaledb.nix index a58e8e2b..91605a48 100644 --- a/nix/ext/timescaledb.nix +++ b/nix/ext/timescaledb.nix @@ -141,7 +141,6 @@ buildEnv { passthru = { inherit versions numberOfVersions switch-ext-version; - pname = "${pname}-all"; hasBackgroundWorker = true; defaultSettings = { shared_preload_libraries = [ "timescaledb" ]; diff --git a/nix/ext/vault.nix b/nix/ext/vault.nix index c518e1e1..cb90882a 100644 --- a/nix/ext/vault.nix +++ b/nix/ext/vault.nix @@ -87,8 +87,7 @@ pkgs.buildEnv { ]; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); pgRegressTestName = "vault"; diff --git a/nix/ext/wal2json.nix b/nix/ext/wal2json.nix index f66e689d..bd1e8ddd 100644 --- a/nix/ext/wal2json.nix +++ b/nix/ext/wal2json.nix @@ -95,8 +95,7 @@ pkgs.buildEnv { ''; passthru = { - inherit versions numberOfVersions; - pname = "${pname}-all"; + inherit versions numberOfVersions pname; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); defaultSettings = { diff --git a/nix/ext/wrappers/default.nix b/nix/ext/wrappers/default.nix index b3798084..c9f22dc4 100644 --- a/nix/ext/wrappers/default.nix +++ b/nix/ext/wrappers/default.nix @@ -154,6 +154,7 @@ let doCheck = false; postInstall = '' + create_control_files() { sed -e "/^default_version =/d" \ -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}-${version}'|" \ @@ -220,11 +221,13 @@ let v: !(builtins.elem v versions) ) allPreviouslyPackagedVersions; numberOfPreviouslyPackagedVersions = builtins.length previouslyPackagedVersions; - packages = builtins.attrValues ( - lib.mapAttrs (name: value: build name value.hash value.rust value.pgrx) supportedVersions - ); + packagesAttrSet = lib.mapAttrs' (name: value: { + name = lib.replaceStrings [ "." ] [ "_" ] name; + value = build name value.hash value.rust value.pgrx; + }) supportedVersions; + packages = builtins.attrValues packagesAttrSet; in -buildEnv { +(buildEnv { name = pname; paths = packages; pathsToLink = [ @@ -305,8 +308,15 @@ buildEnv { ''; passthru = { inherit versions numberOfVersions; - pname = "${pname}-all"; + pname = "${pname}"; version = "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions); + # Expose individual packages for CI to build separately + packages = packagesAttrSet // { + recurseForDerivations = true; + }; }; -} +}).overrideAttrs + (_: { + requiredSystemFeatures = [ "big-parallel" ]; + }) diff --git a/nix/fmt.nix b/nix/fmt.nix index 562c3b3c..08763e5b 100644 --- a/nix/fmt.nix +++ b/nix/fmt.nix @@ -4,6 +4,7 @@ perSystem = { pkgs, ... }: { + treefmt.flakeCheck = false; treefmt.programs = { deadnix.enable = true; nixfmt = { diff --git a/nix/hooks.nix b/nix/hooks.nix index 896c262b..b659635f 100644 --- a/nix/hooks.nix +++ b/nix/hooks.nix @@ -1,4 +1,11 @@ { inputs, ... }: +let + ghWorkflows = builtins.attrNames (builtins.readDir ../.github/workflows); + lintedWorkflows = [ + "nix-eval.yml" + "nix-build.yml" + ]; +in { imports = [ inputs.git-hooks.flakeModule ]; perSystem = @@ -8,9 +15,17 @@ check.enable = true; settings = { hooks = { + actionlint = { + enable = true; + excludes = builtins.filter (name: !builtins.elem name lintedWorkflows) ghWorkflows; + verbose = true; + }; + treefmt = { enable = true; package = config.treefmt.build.wrapper; + pass_filenames = false; + verbose = true; }; }; }; diff --git a/nix/packages/default.nix b/nix/packages/default.nix index 0f5f43ff..b3fc83a0 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -33,6 +33,9 @@ cleanup-ami = pkgs.callPackage ./cleanup-ami.nix { }; dbmate-tool = pkgs.callPackage ./dbmate-tool.nix { inherit (self.supabase) defaults; }; docs = pkgs.callPackage ./docs.nix { }; + github-matrix = pkgs.callPackage ./github-matrix { + nix-eval-jobs = inputs'.nix-eval-jobs.packages.default; + }; supabase-groonga = pkgs.callPackage ./groonga { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { }; @@ -60,7 +63,7 @@ start-server = pkgs-lib.makePostgresDevSetup { inherit pkgs; name = "start-postgres-server"; - pgroonga = self'.packages."psql_${activeVersion}/exts/pgroonga-all"; + pgroonga = self'.legacyPackages."psql_${activeVersion}".exts.pgroonga; }; switch-ext-version = pkgs.callPackage ./switch-ext-version.nix { inherit (self'.packages) overlayfs-on-package; diff --git a/nix/packages/github-matrix/default.nix b/nix/packages/github-matrix/default.nix new file mode 100644 index 00000000..3e1be2df --- /dev/null +++ b/nix/packages/github-matrix/default.nix @@ -0,0 +1,51 @@ +{ + lib, + nix-eval-jobs, + python3Packages, +}: +let + pname = "github-matrix"; + + github-action-utils = python3Packages.buildPythonPackage rec { + pname = "github-action-utils"; + version = "1.1.0"; + pyproject = true; + + src = python3Packages.fetchPypi { + inherit pname version; + sha256 = "0q9xrb4jcvbn6954lvpn85gva1yc885ykdqb2q2410cxp280v94a"; + }; + + build-system = with python3Packages; [ setuptools ]; + + meta = with lib; { + description = "Collection of Python functions for GitHub Action Workflow Commands"; + homepage = "https://github.com/saadmk11/github-action-utils"; + license = licenses.mit; + }; + }; +in + +python3Packages.buildPythonApplication { + inherit pname; + version = "0.1.0"; + pyproject = false; + + src = ./.; + + propagatedBuildInputs = [ + github-action-utils + python3Packages.result + ]; + + makeWrapperArgs = [ "--suffix PATH : ${lib.makeBinPath [ nix-eval-jobs ]}" ]; + + nativeCheckInputs = with python3Packages; [ + pytestCheckHook + pytest-mypy + ]; + + installPhase = '' + install -Dm755 github_matrix.py "$out/bin/${pname}" + ''; +} diff --git a/nix/packages/github-matrix/github_matrix.py b/nix/packages/github-matrix/github_matrix.py new file mode 100755 index 00000000..0108d5cb --- /dev/null +++ b/nix/packages/github-matrix/github_matrix.py @@ -0,0 +1,396 @@ +#!/usr/bin/env python3 + +import argparse +from collections import Counter, defaultdict +import graphlib +import json +import os +import subprocess +import sys +from typing import ( + Any, + Dict, + List, + Literal, + NotRequired, + Optional, + Set, + Tuple, + TypedDict, + get_args, +) + +from github_action_utils import debug, notice, error, set_output, warning +from result import Err, Ok, Result + +System = Literal["x86_64-linux", "aarch64-linux", "aarch64-darwin"] +RunnerType = Literal["ephemeral", "self-hosted"] + + +class NixEvalJobsOutput(TypedDict): + """Raw output from nix-eval-jobs command.""" + + attr: str + attrPath: List[str] + cacheStatus: Literal["notBuilt", "cached", "local"] + drvPath: str + name: str + system: System + neededBuilds: NotRequired[List[Any]] + neededSubstitutes: NotRequired[List[Any]] + outputs: NotRequired[Dict[str, str]] + error: NotRequired[str] + requiredSystemFeatures: NotRequired[List[str]] + + +class RunsOnConfig(TypedDict): + """GitHub Actions runs-on configuration.""" + + group: NotRequired[str] + labels: List[str] + + +class GitHubActionPackage(TypedDict): + """Final package output for GitHub Actions matrix.""" + + attr: str + name: str + system: System + runs_on: RunsOnConfig + postgresql_version: NotRequired[str] + + +class NixEvalError(TypedDict): + """Error information from nix evaluation.""" + + attr: str + error: str + + +BUILD_RUNNER_MAP: Dict[RunnerType, Dict[System, RunsOnConfig]] = { + "ephemeral": { + "aarch64-linux": { + "labels": ["blacksmith-8vcpu-ubuntu-2404-arm"], + }, + "x86_64-linux": { + "labels": ["blacksmith-8vcpu-ubuntu-2404"], + }, + }, + "self-hosted": { + "aarch64-darwin": { + "group": "self-hosted-runners-nix", + "labels": ["aarch64-darwin"], + }, + "aarch64-linux": { + "group": "self-hosted-runners-nix", + "labels": ["aarch64-linux"], + }, + }, +} + + +def build_nix_eval_command(max_workers: int, flake_outputs: List[str]) -> List[str]: + """Build the nix-eval-jobs command with appropriate flags.""" + nix_eval_cmd = [ + "nix-eval-jobs", + "--flake", + ".", + "--check-cache-status", + "--force-recurse", + "--quiet", + "--option", + "eval-cache", + "false", + "--option", + "accept-flake-config", + "true", + "--workers", + str(max_workers), + "--select", + f"outputs: {{ inherit (outputs) {' '.join(flake_outputs)}; }}", + ] + return nix_eval_cmd + + +def parse_nix_eval_line( + line: str, drv_paths: Set[str] +) -> Result[Optional[NixEvalJobsOutput], NixEvalError]: + """Parse a single line of nix-eval-jobs output. + + Returns: + Ok(package_data) if successful (None for empty/duplicate lines) + Err(NixEvalError) if a nix evaluation error occurred + """ + if not line.strip(): + return Ok(None) + + try: + data: NixEvalJobsOutput = json.loads(line) + if "error" in data: + error_msg = data["error"] + + # Extract the core error message (last "error:" line and following context) + error_lines = error_msg.split("\n") + core_error_idx = -1 + for i in range(len(error_lines) - 1, -1, -1): + if error_lines[i].strip().startswith("error:"): + core_error_idx = i + break + + if core_error_idx >= 0: + # Take the last error line and up to 3 lines of context after it + error_msg = "\n".join( + error_lines[ + core_error_idx : min(core_error_idx + 4, len(error_lines)) + ] + ).strip() + + return Err({"attr": data["attr"], "error": error_msg}) + if data["drvPath"] in drv_paths: + return Ok(None) + drv_paths.add(data["drvPath"]) + return Ok(data) + except json.JSONDecodeError as e: + warning(f"Skipping invalid JSON line: {line}", title="JSON Parse Warning") + return Ok(None) + + +def run_nix_eval_jobs( + cmd: List[str], +) -> Tuple[List[NixEvalJobsOutput], List[str], List[NixEvalError]]: + """Run nix-eval-jobs and return parsed package data, warnings, and errors. + + Returns: + Tuple of (packages, warnings_list, errors_list) + """ + debug(f"Running command: {' '.join(cmd)}") + + # Disable colors in nix output + env = os.environ.copy() + env["NO_COLOR"] = "1" + + process = subprocess.Popen( + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, env=env + ) + stdout_data, stderr_data = process.communicate() + + # Parse stdout for packages + packages: List[NixEvalJobsOutput] = [] + drv_paths: Set[str] = set() + errors_list: List[NixEvalError] = [] + for line in stdout_data.splitlines(): + result = parse_nix_eval_line(line, drv_paths) + if result.is_err(): + errors_list.append(result._value) + elif result._value is not None: + packages.append(result._value) + + # Parse stderr for warnings (lines starting with "warning:") + warnings_list: List[str] = [] + for line in stderr_data.splitlines(): + line = line.strip() + if line.startswith("warning:") or line.startswith("evaluation warning:"): + # Remove "warning:" prefix for cleaner messages + warnings_list.append(line[8:].strip()) + + if process.returncode != 0: + error( + "nix-eval-jobs process failed with non-zero exit code", + title="Process Failure", + ) + + return packages, warnings_list, errors_list + + +def is_extension_pkg(pkg: NixEvalJobsOutput) -> bool: + """Check if the package is a postgresql extension package.""" + attrs = pkg["attr"].split(".") + return attrs[-2] == "exts" + + +# thank you buildbot-nix https://github.com/nix-community/buildbot-nix/blob/985d069a2a45cf4a571a4346107671adc2bd2a16/buildbot_nix/buildbot_nix/build_trigger.py#L297 +def sort_pkgs_by_closures(jobs: List[NixEvalJobsOutput]) -> List[NixEvalJobsOutput]: + sorted_jobs = [] + + # Prepare job dependencies + job_set = {job["drvPath"] for job in jobs} + job_closures = { + k["drvPath"]: set(k.get("neededSubstitutes", [])) + .union(set(k.get("neededBuilds", []))) + .intersection(job_set) + .difference({k["drvPath"]}) + for k in jobs + } + + sorter = graphlib.TopologicalSorter(job_closures) + + job_by_drv = {job["drvPath"]: job for job in jobs} + for item in sorter.static_order(): + if item in job_by_drv: + sorted_jobs.append(job_by_drv[item]) + + return sorted_jobs + + +def is_large_pkg(pkg: NixEvalJobsOutput) -> bool: + """Determine if a package is considered large based on its attribute path.""" + return "big-parallel" in pkg.get("requiredSystemFeatures", []) + + +def is_kvm_pkg(pkg: NixEvalJobsOutput) -> bool: + """Determine if a package requires KVM""" + return "kvm" in pkg.get("requiredSystemFeatures", []) + + +def get_runner_for_package(pkg: NixEvalJobsOutput) -> RunsOnConfig | None: + """Determine the appropriate GitHub Actions runner for a package. + + Priority order: + 1. KVM packages → self-hosted runners + 2. Large packages on Linux → 32vcpu ephemeral runners + 3. Darwin packages → self-hosted runners + 4. Default → ephemeral runners + """ + system = pkg["system"] + + if is_kvm_pkg(pkg): + runConfig = BUILD_RUNNER_MAP["self-hosted"].get(system) + if runConfig is None: + raise ValueError( + f"No self-hosted with kvm support available for system: {system}" + ) + return runConfig + + if is_large_pkg(pkg) and system in ("x86_64-linux", "aarch64-linux"): + suffix = "-arm" if system == "aarch64-linux" else "" + return {"labels": [f"blacksmith-32vcpu-ubuntu-2404{suffix}"]} + + if system == "aarch64-darwin": + return BUILD_RUNNER_MAP["self-hosted"]["aarch64-darwin"] + + return BUILD_RUNNER_MAP["ephemeral"].get(system) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Generate GitHub Actions matrix for Nix builds" + ) + parser.add_argument( + "flake_outputs", nargs="+", help="Nix flake outputs to evaluate" + ) + + args = parser.parse_args() + + max_workers: int = os.cpu_count() or 1 + + cmd = build_nix_eval_command(max_workers, args.flake_outputs) + + # Run evaluation and collect packages, warnings, and errors + packages, warnings_list, errors_list = run_nix_eval_jobs(cmd) + gh_action_packages = sort_pkgs_by_closures(packages) + + def clean_package_for_output(pkg: NixEvalJobsOutput) -> GitHubActionPackage: + """Convert nix-eval-jobs output to GitHub Actions matrix package""" + runner = get_runner_for_package(pkg) + if runner is None: + raise ValueError(f"No runner configuration for system: {pkg['system']}") + returned_pkg: GitHubActionPackage = { + "attr": pkg["attr"], + "name": pkg["name"], + "system": pkg["system"], + "runs_on": runner, + } + if is_extension_pkg(pkg): + # Extract PostgreSQL version from attribute path + attrs = pkg["attr"].split(".") + returned_pkg["postgresql_version"] = attrs[-3].split("_")[-1] + return returned_pkg + + # Group packages by system and type (checks vs packages) + packages_by_system: Dict[System, List[GitHubActionPackage]] = defaultdict(list) + checks_by_system: Dict[System, List[GitHubActionPackage]] = defaultdict(list) + for pkg in gh_action_packages: + if pkg.get("cacheStatus") == "notBuilt": + cleaned_pkg = clean_package_for_output(pkg) + if pkg["attr"].startswith("checks."): + checks_by_system[pkg["system"]].append(cleaned_pkg) + elif pkg["attr"].startswith("legacyPackages."): + packages_by_system[pkg["system"]].append(cleaned_pkg) + + packages_output: Dict[str, Dict[str, List[GitHubActionPackage]]] = {} + for pkg_system, pkg_list in packages_by_system.items(): + packages_output[pkg_system.replace("-", "_")] = {"include": pkg_list} + + checks_output: Dict[str, Dict[str, List[GitHubActionPackage]]] = {} + for check_system, check_list in checks_by_system.items(): + checks_output[check_system.replace("-", "_")] = {"include": check_list} + + for system in get_args(System): + s = system.replace("-", "_") + if s not in checks_output: + checks_output[s] = { + "include": [ + { + "attr": "", + "name": "no checks to build", + "system": system, + "runs_on": {"labels": ["ubuntu-latest"]}, + } + ] + } + if s not in packages_output: + packages_output[s] = { + "include": [ + { + "attr": "", + "name": "no packages to build", + "system": system, + "runs_on": {"labels": ["ubuntu-latest"]}, + } + ] + } + + gh_output = { + "packages": packages_output, + "checks": checks_output, + } + + if warnings_list: + warning_counts = Counter(warnings_list) + for warn_msg, count in warning_counts.items(): + if count > 1: + warning( + f"{warn_msg} (occurred {count} times)", + title="Nix Evaluation Warning", + ) + else: + warning(warn_msg, title="Nix Evaluation Warning") + + if errors_list: + # Group errors by error message + errors_by_message: Dict[str, List[str]] = defaultdict(list) + for err in errors_list: + errors_by_message[err["error"]].append(err["attr"]) + + for error_msg, attrs in errors_by_message.items(): + # Format message with attributes on first line, then error details + if len(attrs) > 1: + formatted_msg = f"Affected attributes ({len(attrs)}): {', '.join(attrs)}\n\n{error_msg}" + else: + formatted_msg = f"Attribute: {attrs[0]}\n\n{error_msg}" + formatted_msg = formatted_msg.replace("\n", "%0A") + error(formatted_msg, title="Nix Evaluation Error") + + if errors_list: + sys.exit(1) + else: + formatted_msg = f"Generated GitHub Actions matrix: {json.dumps(gh_output, indent=2)}".replace( + "\n", "%0A" + ) + notice(formatted_msg, title="GitHub Actions Matrix") + set_output("packages_matrix", json.dumps(gh_output["packages"])) + set_output("checks_matrix", json.dumps(gh_output["checks"])) + + +if __name__ == "__main__": + main() diff --git a/nix/packages/github-matrix/tests/test_github_matrix.py b/nix/packages/github-matrix/tests/test_github_matrix.py new file mode 100644 index 00000000..17ce8132 --- /dev/null +++ b/nix/packages/github-matrix/tests/test_github_matrix.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 + +import pytest + +from github_matrix import ( + NixEvalJobsOutput, + get_runner_for_package, + is_extension_pkg, + is_kvm_pkg, + is_large_pkg, + sort_pkgs_by_closures, +) + + +class TestIsExtensionPkg: + def test_extension_package(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.x86_64-linux.psql_15.exts.pg_cron", + "attrPath": [ + "legacyPackages", + "x86_64-linux", + "psql_15", + "exts", + "pg_cron", + ], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "pg_cron", + "system": "x86_64-linux", + } + assert is_extension_pkg(pkg) is True + + def test_non_extension_package(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.x86_64-linux.psql_15", + "attrPath": ["legacyPackages", "x86_64-linux", "psql_15"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "postgresql-16.0", + "system": "x86_64-linux", + } + assert is_extension_pkg(pkg) is False + + +class TestIsLargePkg: + @pytest.mark.parametrize( + "attr,expected", + [ + ("legacyPackages.x86_64-linux.psql_15.exts.wrappers", True), + ("legacyPackages.x86_64-linux.psql_15.exts.pg_jsonschema", True), + ("legacyPackages.x86_64-linux.psql_15.exts.pg_graphql", True), + ("legacyPackages.x86_64-linux.psql_15.exts.postgis", True), + ("legacyPackages.x86_64-linux.psql_15.exts.pg_cron", False), + ("legacyPackages.x86_64-linux.psql_15", False), + ], + ) + def test_large_package_detection(self, attr: str, expected: bool): + pkg: NixEvalJobsOutput = { + "attr": attr, + "attrPath": attr.split("."), + "cacheStatus": "notBuilt", + "drvPath": f"/nix/store/{attr}.drv", + "name": attr.split(".")[-1], + "system": "x86_64-linux", + "requiredSystemFeatures": ["big-parallel"] if expected else [], + } + assert is_large_pkg(pkg) is expected + + +class TestIsKvmPkg: + def test_kvm_package(self): + pkg: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.vm-test", + "attrPath": ["packages", "x86_64-linux", "vm-test"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "vm-test", + "system": "x86_64-linux", + "requiredSystemFeatures": ["kvm"], + } + assert is_kvm_pkg(pkg) is True + + def test_non_kvm_package(self): + pkg: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.psql_15", + "attrPath": ["packages", "x86_64-linux", "psql_15"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "postgresql-16.0", + "system": "x86_64-linux", + } + assert is_kvm_pkg(pkg) is False + + +class TestGetRunnerForPackage: + def test_kvm_package_x86_64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.vm-test", + "attrPath": ["packages", "x86_64-linux", "vm-test"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "vm-test", + "system": "x86_64-linux", + "requiredSystemFeatures": ["kvm"], + } + with pytest.raises( + ValueError, + match=r"No self-hosted with kvm support available for system: x86_64-linux", + ): + get_runner_for_package(pkg) + + def test_kvm_package_aarch64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "packages.aarch64-linux.vm-test", + "attrPath": ["packages", "aarch64-linux", "vm-test"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "vm-test", + "system": "aarch64-linux", + "requiredSystemFeatures": ["kvm"], + } + result = get_runner_for_package(pkg) + assert result == { + "group": "self-hosted-runners-nix", + "labels": ["aarch64-linux"], + } + + def test_large_package_x86_64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.x86_64-linux.psql_15.exts.postgis", + "attrPath": [ + "legacyPackages", + "x86_64-linux", + "psql_15", + "exts", + "postgis", + ], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "postgis", + "system": "x86_64-linux", + "requiredSystemFeatures": ["big-parallel"], + } + result = get_runner_for_package(pkg) + assert result == {"labels": ["blacksmith-32vcpu-ubuntu-2404"]} + + def test_large_package_aarch64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.aarch64-linux.psql_15.exts.pg_graphql", + "attrPath": [ + "legacyPackages", + "aarch64-linux", + "psql_15", + "exts", + "pg_graphql", + ], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "pg_graphql", + "system": "aarch64-linux", + "requiredSystemFeatures": ["big-parallel"], + } + result = get_runner_for_package(pkg) + assert result == {"labels": ["blacksmith-32vcpu-ubuntu-2404-arm"]} + + def test_darwin_package(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.aarch64-darwin.psql_15", + "attrPath": ["legacyPackages", "aarch64-darwin", "psql_15"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "postgresql-16.0", + "system": "aarch64-darwin", + } + result = get_runner_for_package(pkg) + assert result == { + "group": "self-hosted-runners-nix", + "labels": ["aarch64-darwin"], + } + + def test_default_x86_64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.x86_64-linux.psql_15.exts.pg_cron", + "attrPath": [ + "legacyPackages", + "x86_64-linux", + "psql_15", + "exts", + "pg_cron", + ], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "pg_cron", + "system": "x86_64-linux", + } + result = get_runner_for_package(pkg) + assert result == {"labels": ["blacksmith-8vcpu-ubuntu-2404"]} + + def test_default_aarch64_linux(self): + pkg: NixEvalJobsOutput = { + "attr": "legacyPackages.aarch64-linux.psql_15.exts.pg_cron", + "attrPath": [ + "legacyPackages", + "aarch64-linux", + "psql_15", + "exts", + "pg_cron", + ], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "pg_cron", + "system": "aarch64-linux", + } + result = get_runner_for_package(pkg) + assert result == {"labels": ["blacksmith-8vcpu-ubuntu-2404-arm"]} + + +class TestSortPkgsByClosures: + def test_empty_list(self): + result = sort_pkgs_by_closures([]) + assert result == [] + + def test_single_package(self): + pkg: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.psql_15", + "attrPath": ["packages", "x86_64-linux", "psql_15"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/test.drv", + "name": "postgresql-16.0", + "system": "x86_64-linux", + } + result = sort_pkgs_by_closures([pkg]) + assert result == [pkg] + + def test_dependency_order(self): + pkg1: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.lib", + "attrPath": ["packages", "x86_64-linux", "lib"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/lib.drv", + "name": "lib", + "system": "x86_64-linux", + "neededBuilds": [], + "neededSubstitutes": [], + } + pkg2: NixEvalJobsOutput = { + "attr": "packages.x86_64-linux.app", + "attrPath": ["packages", "x86_64-linux", "app"], + "cacheStatus": "notBuilt", + "drvPath": "/nix/store/app.drv", + "name": "app", + "system": "x86_64-linux", + "neededBuilds": ["/nix/store/lib.drv"], + "neededSubstitutes": [], + } + + # Regardless of input order, lib should come before app + result = sort_pkgs_by_closures([pkg2, pkg1]) + assert result == [pkg1, pkg2] + + result = sort_pkgs_by_closures([pkg1, pkg2]) + assert result == [pkg1, pkg2] diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index 8472e05f..aa6cc9e4 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -1,7 +1,7 @@ { inputs, ... }: { perSystem = - { pkgs, ... }: + { pkgs, lib, ... }: let # Custom extensions that exist in our repository. These aren't upstream # either because nobody has done the work, maintaining them here is @@ -108,15 +108,21 @@ # Create an attrset that contains all the extensions included in a server. makeOurPostgresPkgsSet = version: - (builtins.listToAttrs ( - map (drv: { - name = drv.pname; - value = drv; - }) (makeOurPostgresPkgs version) - )) - // { - recurseForDerivations = true; - }; + let + pkgsList = makeOurPostgresPkgs version; + baseAttrs = builtins.listToAttrs ( + map (drv: { + name = drv.name; + value = drv; + }) pkgsList + ); + # Expose individual packages from extensions that have them in passthru.packages + # This makes them discoverable by nix-eval-jobs --force-recurse + individualPkgs = lib.concatMapAttrs ( + name: drv: lib.optionalAttrs (drv ? passthru.packages) { "${name}-pkgs" = drv.passthru.packages; } + ) baseAttrs; + in + baseAttrs // individualPkgs // { recurseForDerivations = true; }; # Create a binary distribution of PostgreSQL, given a version. # @@ -131,7 +137,7 @@ let postgresql = getPostgresqlPackage version; ourExts = map (ext: { - name = ext.pname; + name = ext.name; version = ext.version; }) (makeOurPostgresPkgs version); @@ -154,18 +160,24 @@ # install. # - exts: an attrset containing all the extensions, mapped to their # package names. - makePostgres = version: { - bin = makePostgresBin version; - exts = makeOurPostgresPkgsSet version; - recurseForDerivations = true; - }; + makePostgres = + version: + lib.recurseIntoAttrs { + bin = makePostgresBin version; + exts = makeOurPostgresPkgsSet version; + }; basePackages = { psql_15 = makePostgres "15"; psql_17 = makePostgres "17"; psql_orioledb-17 = makePostgres "orioledb-17"; }; + binPackages = lib.mapAttrs' (name: value: { + name = "${name}/bin"; + value = value.bin; + }) basePackages; in { - packages = inputs.flake-utils.lib.flattenTree basePackages; + packages = binPackages; + legacyPackages = basePackages; }; } diff --git a/nix/postgresql/generic.nix b/nix/postgresql/generic.nix index 76904ced..ea67cbc9 100644 --- a/nix/postgresql/generic.nix +++ b/nix/postgresql/generic.nix @@ -21,7 +21,6 @@ let libxml2, tzdata, libkrb5, - substituteAll, darwin, linux-pam, #orioledb specific @@ -193,11 +192,7 @@ let ./patches/paths-for-split-outputs.patch ./patches/specify_pkglibdir_at_runtime.patch ./patches/paths-with-postgresql-suffix.patch - - (substituteAll { - src = ./patches/locale-binary-path.patch; - locale = "${if stdenv.isDarwin then darwin.adv_cmds else lib.getBin stdenv.cc.libc}/bin/locale"; - }) + ./patches/locale-binary-path.patch ] ++ lib.optionals stdenv'.hostPlatform.isMusl ( # Using fetchurl instead of fetchpatch on purpose: https://github.com/NixOS/nixpkgs/issues/240141 @@ -213,6 +208,9 @@ let '' # Hardcode the path to pgxs so pg_config returns the path in $out substituteInPlace "src/common/config_info.c" --subst-var out + substituteInPlace "src/backend/commands/collationcmds.c" --replace-fail '@locale@' '${ + if stdenv.isDarwin then darwin.adv_cmds else lib.getBin stdenv.cc.libc + }/bin/locale' '' + lib.optionalString jitSupport '' # Force lookup of jit stuff in $out instead of $lib [parent: a431c10a356b]