diff --git a/doc/manual/src/webhooks.md b/doc/manual/src/webhooks.md index 2b26cd61..674e1064 100644 --- a/doc/manual/src/webhooks.md +++ b/doc/manual/src/webhooks.md @@ -1,9 +1,12 @@ # Webhooks -Hydra can be notified by github's webhook to trigger a new evaluation when a +Hydra can be notified by github or gitea with webhooks to trigger a new evaluation when a jobset has a github repo in its input. -To set up a github webhook go to `https://github.com///settings` and in the `Webhooks` tab -click on `Add webhook`. + +## GitHub + +To set up a webhook for a GitHub repository go to `https://github.com///settings` +and in the `Webhooks` tab click on `Add webhook`. - In `Payload URL` fill in `https:///api/push-github`. - In `Content type` switch to `application/json`. @@ -11,3 +14,14 @@ click on `Add webhook`. - For `Which events would you like to trigger this webhook?` keep the default option for events on `Just the push event.`. Then add the hook with `Add webhook`. + +## Gitea + +To set up a webhook for a Gitea repository go to the settings of the repository in your Gitea instance +and in the `Webhooks` tab click on `Add Webhook` and choose `Gitea` in the drop down. + +- In `Target URL` fill in `https:///api/push-gitea`. +- Keep HTTP method `POST`, POST Content Type `application/json` and Trigger On `Push Events`. +- Change the branch filter to match the git branch hydra builds. + +Then add the hook with `Add webhook`. diff --git a/src/hydra-queue-runner/build-remote.cc b/src/hydra-queue-runner/build-remote.cc index 57a5f0df..57be4070 100644 --- a/src/hydra-queue-runner/build-remote.cc +++ b/src/hydra-queue-runner/build-remote.cc @@ -468,11 +468,6 @@ void State::buildRemote(ref destStore, infos.insert_or_assign(info.path, info); } - if (totalNarSize > maxOutputSize) { - result.stepStatus = bsNarSizeLimitExceeded; - return; - } - /* Copy each path. */ printMsg(lvlDebug, "copying outputs of ā€˜%sā€™ from ā€˜%sā€™ (%d bytes)", localStore->printStorePath(step->drvPath), machine->sshName, totalNarSize); diff --git a/src/lib/Hydra/Controller/API.pm b/src/lib/Hydra/Controller/API.pm index 6f10ef57..12073595 100644 --- a/src/lib/Hydra/Controller/API.pm +++ b/src/lib/Hydra/Controller/API.pm @@ -285,6 +285,22 @@ sub push_github : Chained('api') PathPart('push-github') Args(0) { $c->response->body(""); } +sub push_gitea : Chained('api') PathPart('push-gitea') Args(0) { + my ($self, $c) = @_; + + $c->{stash}->{json}->{jobsetsTriggered} = []; + + my $in = $c->request->{data}; + my $url = $in->{repository}->{clone_url} or die; + print STDERR "got push from Gitea repository $url\n"; + + triggerJobset($self, $c, $_, 0) foreach $c->model('DB::Jobsets')->search( + { 'project.enabled' => 1, 'me.enabled' => 1 }, + { join => 'project' + , where => \ [ 'me.flake like ? or exists (select 1 from JobsetInputAlts where project = me.project and jobset = me.name and value like ?)', [ 'flake', "%$url%"], [ 'value', "%$url%" ] ] + }); + $c->response->body(""); +} 1; diff --git a/src/lib/Hydra/Controller/Root.pm b/src/lib/Hydra/Controller/Root.pm index c6843d29..1b33db2a 100644 --- a/src/lib/Hydra/Controller/Root.pm +++ b/src/lib/Hydra/Controller/Root.pm @@ -32,6 +32,7 @@ sub noLoginNeeded { return $whitelisted || $c->request->path eq "api/push-github" || + $c->request->path eq "api/push-gitea" || $c->request->path eq "google-login" || $c->request->path eq "github-redirect" || $c->request->path eq "github-login" || @@ -77,7 +78,7 @@ sub begin :Private { $_->supportedInputTypes($c->stash->{inputTypes}) foreach @{$c->hydra_plugins}; # XSRF protection: require POST requests to have the same origin. - if ($c->req->method eq "POST" && $c->req->path ne "api/push-github") { + if ($c->req->method eq "POST" && $c->req->path ne "api/push-github" && $c->req->path ne "api/push-gitea") { my $referer = $c->req->header('Referer'); $referer //= $c->req->header('Origin'); my $base = $c->req->base; diff --git a/src/lib/Hydra/Plugin/GiteaStatus.pm b/src/lib/Hydra/Plugin/GiteaStatus.pm index 426c93f5..b4346870 100644 --- a/src/lib/Hydra/Plugin/GiteaStatus.pm +++ b/src/lib/Hydra/Plugin/GiteaStatus.pm @@ -29,6 +29,53 @@ sub toGiteaState { } } +sub url_from_jobsetevalinputs { + my ($eval) = @_; + my $giteastatusInput = $eval->jobsetevalinputs->find({ name => "gitea_status_repo" }); + return undef unless defined $giteastatusInput && defined $giteastatusInput->value; + my $i = $eval->jobsetevalinputs->find({ name => $giteastatusInput->value, altnr => 0 }); + return undef unless defined $i; + my $gitea_url = $eval->jobsetevalinputs->find({ name => "gitea_http_url" }); + + my $repoOwner = $eval->jobsetevalinputs->find({ name => "gitea_repo_owner" })->value; + my $repoName = $eval->jobsetevalinputs->find({ name => "gitea_repo_name" })->value; + + my $rev = $i->revision; + my $domain = URI->new($i->uri)->host; + my $host; + unless (defined $gitea_url) { + $host = "https://$domain"; + } else { + $host = $gitea_url->value; + } + + return ("$host/api/v1/repos/$repoOwner/$repoName/statuses/$rev", $repoOwner); +} +sub is_gitea { + my ($ua, $hostname) = @_; + my $req = HTTP::Request->new('GET', "https://$hostname/api/swagger"); + my $res = $ua->request($req); + return 0 unless $res->is_success; + return index($res->as_string(), "Gitea") != -1; +} + +sub try_gitea_from_repo_url { + my ($ua, $url) = @_; + if ($url =~ m!git\+https://([^/]+)/([^/]+)/([^/]+)\?.*rev=([[:xdigit:]]{40})$!) { + return ("https://$1/api/v1/repos/$2/$3/statuses/$4", $2) if is_gitea($ua, $1); + } + return undef; +} + +sub try_gitea { + my ($ua, $eval) = @_; + if (defined $eval->flake) { + return try_gitea_from_repo_url($ua, $eval->flake); + } + return undef; +} + + sub common { my ($self, $topbuild, $dependents, $status) = @_; my $baseurl = $self->{config}->{'base_uri'} || "http://localhost:3000"; @@ -52,26 +99,12 @@ sub common { }); while (my $eval = $evals->next) { - my $giteastatusInput = $eval->jobsetevalinputs->find({ name => "gitea_status_repo" }); - next unless defined $giteastatusInput && defined $giteastatusInput->value; - my $i = $eval->jobsetevalinputs->find({ name => $giteastatusInput->value, altnr => 0 }); - next unless defined $i; - my $gitea_url = $eval->jobsetevalinputs->find({ name => "gitea_http_url" }); - - my $repoOwner = $eval->jobsetevalinputs->find({ name => "gitea_repo_owner" })->value; - my $repoName = $eval->jobsetevalinputs->find({ name => "gitea_repo_name" })->value; - my $accessToken = $self->{config}->{gitea_authorization}->{$repoOwner}; - - my $rev = $i->revision; - my $domain = URI->new($i->uri)->host; - my $host; - unless (defined $gitea_url) { - $host = "https://$domain"; - } else { - $host = $gitea_url->value; + my ($url, $repoOwner) = url_from_jobsetevalinputs($eval); + if (! defined $url) { + ($url, $repoOwner) = try_gitea($ua, $eval); } - - my $url = "$host/api/v1/repos/$repoOwner/$repoName/statuses/$rev"; + next unless defined $url; + my $accessToken = $self->{config}->{gitea_authorization}->{$repoOwner}; print STDERR "GiteaStatus POSTing $state to $url\n"; my $req = HTTP::Request->new('POST', $url);