Files
hydra/src/lib/Hydra/Plugin/PathInput.pm
Maximilian Bosch e499509595 Switch to new Nix bindings, update Nix for that
Implements support for Nix's new Perl bindings[1]. The current state
basically does `openStore()`, but always uses `auto` and doesn't support
stores at other URIs.

Even though the stores are cached inside the Perl implementation, I
decided to instantiate those once in the Nix helper module. That way
store openings aren't cluttered across the entire codebase. Also, there
are two stores used later on - MACHINE_LOCAL_STORE for `auto`,
BINARY_CACHE_STORE for the one from `store_uri` in `hydra.conf` - and
using consistent names should make the intent clearer then.

This doesn't contain any behavioral changes, i.e. the build product
availability issue from #1352 isn't fixed. This patch only contains the
migration to the new API.

[1] https://github.com/NixOS/nix/pull/9863
2024-02-12 18:50:56 +01:00

85 lines
2.7 KiB
Perl

package Hydra::Plugin::PathInput;
use strict;
use warnings;
use parent 'Hydra::Plugin';
use POSIX qw(strftime);
use Hydra::Helper::Nix;
sub supportedInputTypes {
my ($self, $inputTypes) = @_;
$inputTypes->{'path'} = 'Local path or URL';
}
sub fetchInput {
my ($self, $type, $name, $value) = @_;
return undef if $type ne "path";
my $uri = $value;
my $timestamp = time;
my $sha256;
my $storePath;
my $timeout = $self->{config}->{path_input_cache_validity_seconds} // 30;
# Some simple caching: don't check a path more than once every N seconds.
(my $cachedInput) = $self->{db}->resultset('CachedPathInputs')->search(
{srcpath => $uri, lastseen => {">", $timestamp - $timeout}},
{rows => 1, order_by => "lastseen DESC"});
if (defined $cachedInput && $MACHINE_LOCAL_STORE->isValidPath($cachedInput->storepath)) {
$storePath = $cachedInput->storepath;
$sha256 = $cachedInput->sha256hash;
$timestamp = $cachedInput->timestamp;
} else {
print STDERR "copying input ", $name, " from $uri\n";
if ( $uri =~ /^\// ) {
$storePath = `nix-store --add "$uri"`
or die "cannot copy path $uri to the Nix store.\n";
} else {
$storePath = `PRINT_PATH=1 nix-prefetch-url "$uri" | tail -n 1`
or die "cannot fetch $uri to the Nix store.\n";
}
chomp $storePath;
$sha256 = ($MACHINE_LOCAL_STORE->queryPathInfo($storePath, 0))[1] or die;
($cachedInput) = $self->{db}->resultset('CachedPathInputs')->search(
{srcpath => $uri, sha256hash => $sha256});
# Path inputs don't have a natural notion of a "revision", so
# we simulate it by using the timestamp that we first saw this
# path have this SHA-256 hash. So if the contents of the path
# changes, we get a new "revision", but if it doesn't change
# (or changes back), we don't get a new "revision".
if (!defined $cachedInput) {
$self->{db}->txn_do(sub {
$self->{db}->resultset('CachedPathInputs')->update_or_create(
{ srcpath => $uri
, timestamp => $timestamp
, lastseen => $timestamp
, sha256hash => $sha256
, storepath => $storePath
});
});
} else {
$timestamp = $cachedInput->timestamp;
$self->{db}->txn_do(sub {
$cachedInput->update({lastseen => time});
});
}
}
return
{ uri => $uri
, storePath => $storePath
, sha256hash => $sha256
, revision => (strftime "%Y%m%d%H%M%S", gmtime($timestamp)) . ':' . $sha256
};
}
1;