Skip to content

Commit

Permalink
Implement retrieving GitHub logins
Browse files Browse the repository at this point in the history
This is a precondition for the RCB to do things only priviledged users
can do. Otherwise it'd be a blatantly obvious security hole.
  • Loading branch information
patrickbkr committed Nov 6, 2023
1 parent 8f083db commit c167e81
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 69 deletions.
3 changes: 3 additions & 0 deletions config-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ db:
password: some_pw

github-app-id: "87729"
github-client-id: "Iv1.8f11845b87ff14f0"
github-client-secret: "fooop"
github-app-key-file: "rakudocibot.2020-11-06.private-key.pem"
projects:
rakudo:
Expand All @@ -28,6 +30,7 @@ projects:
install-id: 20243470

hook-url: https://cibot.rakudo.org/
jwt-secret: "N#xTe4>IGSWfH#M&MYXxI~#w9yj@X8X/g8-N{;n)5D>kFh~AaW"

obs-user: some_user
obs-password: "some_pw"
Expand Down
34 changes: 23 additions & 11 deletions lib/CITestSetManager.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ method process-worklist() is serial-dedup {
for DB::Command.^all.grep(*.status == DB::COMMAND_NEW) -> $command {
given $command.command {
when DB::RE_TEST {
my $ts;
if $command.pr {
my $ts = DB::CITestSet.^all.sort(-*.id).first( *.pr.number == $command.pr.number );
$ts = DB::CITestSet.^all.sort(-*.id).first( *.pr.number == $command.pr.number );
unless $ts {
error "No TestSet for the PR of the given command found: " ~ $command.id;
$command.status = DB::COMMAND_DONE;
Expand All @@ -37,21 +38,24 @@ method process-worklist() is serial-dedup {

$command.test-set = $ts;
$command.^save;
}
else {
$ts = $command.ts;
}

debug "CITestSetManager: Starting re-test for command: " ~ $command.id;
debug "CITestSetManager: Starting re-test for command: " ~ $command.id;

for $!test-set-listeners.keys {
$_.re-test-test-set($ts)
}
for $!test-set-listeners.keys {
$_.re-test-test-set($ts)
}

$ts.status = DB::WAITING_FOR_TEST_RESULTS;
$ts.^save;
$ts.status = DB::WAITING_FOR_TEST_RESULTS;
$ts.^save;

$command.status = DB::COMMAND_DONE;
$command.^save;
$command.status = DB::COMMAND_DONE;
$command.^save;

$_.command-accepted($command) for $!status-listeners.keys;
}
$_.command-accepted($command) for $!status-listeners.keys;
}
}
}
Expand Down Expand Up @@ -109,6 +113,14 @@ method add-test-set(:$test-set!, :$source-spec!) {
self.process-worklist;
}

method re-test(:$test-set!) {
DB::Command.^create:
:command(DB::RE_TEST),
:$test-set,
;
self.process-worklist;
}

method add-tests(*@tests) {
$_.tests-queued(@tests) for $!status-listeners.keys;
}
Expand Down
26 changes: 23 additions & 3 deletions lib/Config.rakumod
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use YAMLish;

enum Project <
MOAR
NQP
RAKUDO
>;

class ConfigProject {
has $.project;
has $.repo;
Expand All @@ -24,16 +30,27 @@ class ConfigProjects {
has $.rakudo is required;
has $.nqp is required;
has $.moar is required;

method for-id(Project $id) {
given $id {
when RAKUDO { return $!rakudo }
when NQP { return $!nqp }
when MOAR { return $!moar }
}
}
}

class Config {
has %.db;

has $.github-app-id;
has $.github-client-id;
has $.github-client-secret;
has $.github-app-key-file;
has $.projects;

has $.hook-url;
has $.jwt-secret;

has $.obs-user;
has $.obs-password;
Expand Down Expand Up @@ -70,15 +87,18 @@ class Config {
Config.new:
db => %config<db>,

github-app-id => %config<github-app-id>,
github-app-key-file => %config<github-app-key-file>,
projects => ConfigProjects.new(
github-app-id => %config<github-app-id>,
github-client-id => %config<github-client-id>,
github-client-secret => %config<github-client-secret>,
github-app-key-file => %config<github-app-key-file>,
projects => ConfigProjects.new(
rakudo => ConfigProject.from-config(%config<projects><rakudo>),
nqp => ConfigProject.from-config(%config<projects><nqp>),
moar => ConfigProject.from-config(%config<projects><moar>),
),

hook-url => %config<hook-url>,
jwt-secret => %config<jwt-secret>,

obs-user => %config<obs-user>,
obs-password => %config<obs-password>,
Expand Down
14 changes: 4 additions & 10 deletions lib/DB.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,6 @@ enum CIPlatformTestSetStatus <
PLATFORM_DONE
>;

enum Project <
MOAR
NQP
RAKUDO
>;

enum CITestSetStatus (
"NEW", # As created by the GitHubCITestRequester. SourceSpec has not been created yet.
"UNPROCESSED", # SourceSpec has been created. Now to be processed by the CITestSetManager
Expand Down Expand Up @@ -145,7 +139,7 @@ model CITestSet is rw is table<citest_set> {
# Responsibility of the GitHubCITestRequester
has DB::GitHubEventType $.event-type is column;

has DB::Project $.project is column;
has Project $.project is column;
has Str $.git-url is column;
has Str $.commit-sha is column;
has Str $.user-url is column;
Expand Down Expand Up @@ -205,7 +199,7 @@ model CITestSet is rw is table<citest_set> {
model GitHubPullState is rw is table<github_pull_state> {
has UInt $.id is serial;
has DateTime $.creation is column .= now;
has DB::Project $.project is column;
has Project $.project is column;

has Str $.last-default-branch-cursor is column{ :nullable };
has Str $.last-pr-cursor is column{ :nullable };
Expand All @@ -215,7 +209,7 @@ model GitHubPR is rw is table<github_pr> {
has UInt $.id is serial;
has DateTime $.creation is column .= now;
has UInt $.number is column;
has DB::Project $.project is column;
has Project $.project is column;
has Str $.base-url is column;
has Str $.head-url is column;
has Str $.head-branch is column;
Expand All @@ -240,7 +234,7 @@ model Command is rw is table<command> {
has Str $.comment-id is column;
has Str $.comment-url is column;

has DB::CommandStatus $.status is column;
has DB::CommandStatus $.status is column = DB::COMMAND_NEW;
has DB::CommandEnum $.command is column;

# If it's a re-test command, the test set we should re test
Expand Down
49 changes: 24 additions & 25 deletions lib/GitHubCITestRequester.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ method !process-pr-comment-task(PRCommentTask $comment) {
comment-id => $comment.id,
comment-url => $comment.user-url,
:$command,
status => DB::COMMAND_NEW,
;
if $command == DB::MERGE_ON_SUCCESS {
$!github-interface.add-issue-comment:
Expand Down Expand Up @@ -199,9 +198,9 @@ method !process-commit-task(CommitTask $commit) {

method poll-for-changes() is serial-dedup {
trace "GitHub: Polling for changes";
for DB::RAKUDO, config.projects.rakudo,
DB::NQP, config.projects.nqp,
DB::MOAR, config.projects.moar -> $db-project, $project {
for RAKUDO, config.projects.rakudo,
NQP, config.projects.nqp,
MOAR, config.projects.moar -> $db-project, $project {
my $state = DB::GitHubPullState.^all.first({ $_.project == $db-project }) // DB::GitHubPullState.^create(project => $db-project);

# PRs
Expand Down Expand Up @@ -338,12 +337,12 @@ method !determine-source-spec(:$project!, :$git-url!, :$commit-sha!, :$pr --> So
my $did-things = False;
with $pr {
my %head-data = self!github-url-to-project-repo($pr.head-url);
if $project == DB::RAKUDO && %head-data<repo> eq config.projects.rakudo.repo ||
$project == DB::NQP && %head-data<repo> eq config.projects.nqp.repo ||
$project == DB::MOAR && %head-data<repo> eq config.projects.moar.repo {
my $uses-core-repos = %head-data<slug> eq ($project == DB::RAKUDO ?? config.projects.rakudo.slug !!
$project == DB::NQP ?? config.projects.nqp.slug !!
$project == DB::MOAR ?? config.projects.moar.slug !!
if $project == RAKUDO && %head-data<repo> eq config.projects.rakudo.repo ||
$project == NQP && %head-data<repo> eq config.projects.nqp.repo ||
$project == MOAR && %head-data<repo> eq config.projects.moar.repo {
my $uses-core-repos = %head-data<slug> eq ($project == RAKUDO ?? config.projects.rakudo.slug !!
$project == NQP ?? config.projects.nqp.slug !!
$project == MOAR ?? config.projects.moar.slug !!
"should never happen");
my ($r-proj, $r-repo, $n-proj, $n-repo, $m-proj, $m-repo) = do if $uses-core-repos {
config.projects.rakudo.project, config.projects.rakudo.repo,
Expand All @@ -358,9 +357,9 @@ method !determine-source-spec(:$project!, :$git-url!, :$commit-sha!, :$pr --> So

my $branch = $pr.head-branch;

for DB::RAKUDO, $rakudo-git-url, $rakudo-commit-sha, $rakudo-fetch-ref, $r-proj, $r-repo,
DB::NQP, $nqp-git-url, $nqp-commit-sha, $nqp-fetch-ref, $n-proj, $n-repo,
DB::MOAR, $moar-git-url, $moar-commit-sha, $moar-fetch-ref, $m-proj, $m-repo
for RAKUDO, $rakudo-git-url, $rakudo-commit-sha, $rakudo-fetch-ref, $r-proj, $r-repo,
NQP, $nqp-git-url, $nqp-commit-sha, $nqp-fetch-ref, $n-proj, $n-repo,
MOAR, $moar-git-url, $moar-commit-sha, $moar-fetch-ref, $m-proj, $m-repo
-> $cur-proj, $out-url is rw, $out-commit-sha is rw, $out-fetch-ref is rw, $gh-project, $repo {
if $cur-proj == $project {
$out-url = $pr.base-url;
Expand Down Expand Up @@ -388,17 +387,17 @@ method !determine-source-spec(:$project!, :$git-url!, :$commit-sha!, :$pr --> So
if !$did-things {
with $pr {
given $project {
when DB::RAKUDO {
when RAKUDO {
$rakudo-git-url = $pr.base-url;
$rakudo-commit-sha = $commit-sha;
$rakudo-fetch-ref = "pull/{$pr.number}/head";
}
when DB::NQP {
when NQP {
$nqp-git-url = $pr.base-url;
$nqp-commit-sha = $commit-sha;
$nqp-fetch-ref = "pull/{$pr.number}/head";
}
when DB::MOAR {
when MOAR {
$moar-git-url = $pr.base-url;
$moar-commit-sha = $commit-sha;
$moar-fetch-ref = "pull/{$pr.number}/head";
Expand All @@ -407,15 +406,15 @@ method !determine-source-spec(:$project!, :$git-url!, :$commit-sha!, :$pr --> So
}
else {
given $project {
when DB::RAKUDO {
when RAKUDO {
$rakudo-git-url = $git-url;
$rakudo-commit-sha = $commit-sha;
}
when DB::NQP {
when NQP {
$nqp-git-url = $git-url;
$nqp-commit-sha = $commit-sha;
}
when DB::MOAR {
when MOAR {
$moar-git-url = $git-url;
$moar-commit-sha = $commit-sha;
}
Expand Down Expand Up @@ -467,18 +466,18 @@ method !command-to-enum($text is copy) {

method !repo-to-project-repo($repo) {
given $repo.lc {
when "rakudo" { { project => config.projects.rakudo.project, repo => config.projects.rakudo.repo, db-project => DB::RAKUDO } }
when "nqp" { { project => config.projects.nqp.project, repo => config.projects.nqp.repo, db-project => DB::NQP } }
when "moarvm" { { project => config.projects.moar.project, repo => config.projects.moar.repo, db-project => DB::MOAR } }
when "rakudo" { { project => config.projects.rakudo.project, repo => config.projects.rakudo.repo, db-project => RAKUDO } }
when "nqp" { { project => config.projects.nqp.project, repo => config.projects.nqp.repo, db-project => NQP } }
when "moarvm" { { project => config.projects.moar.project, repo => config.projects.moar.repo, db-project => MOAR } }
default { die "unknown project"; }
}
}

method !db-project-to-project-repo($db-project) {
my $repo = do given $db-project {
when DB::RAKUDO { "rakudo" }
when DB::NQP { "nqp" }
when DB::MOAR { "moarvm" }
when RAKUDO { "rakudo" }
when NQP { "nqp" }
when MOAR { "moarvm" }
}
self!repo-to-project-repo($repo);
}
Expand Down
37 changes: 35 additions & 2 deletions lib/GitHubInterface.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,51 @@ unit class GitHubInterface;
use Config;
use Log::Async;
use WebService::GitHub::AppAuth;
use WebService::GitHub::OAuth;
use WebService::GitHub;
use GitHubCITestRequester;

constant $gql-endpoint = "https://api.github.com/graphql";
has WebService::GitHub::AppAuth $!gh-auth;
has WebService::GitHub::OAuth $!gh-oauth;
has $!redirect-url;
has $!client-id;
has WebService::GitHub $!gh;
has GitHubCITestRequester $.processor is required;

submethod TWEAK(:$app-id!, :$pem!) {
method oauth-step-one-url($state) {
{
url => 'https://github.com/login/oauth/authorize',
query-params => [
client_id => $!client-id,
redirect_uri => $!redirect-url,
state => $state,
allow_signups => 'false',
],
}
}

method oauth-code-to-token($code, $state) {
$!gh-oauth.step-two($state, $code, $state);
}

method oauth-user-name($token) {
my WebService::GitHub $gh-oauth-client .= new: :pat($token);
my %user = self!validate($gh-oauth-client.users.get-authenticated().data);
return %user<login>;
}

submethod TWEAK(:$app-id!, :$!client-id!, :$client-secret!, :$pem!, :$!redirect-url!) {
$!gh-auth .= new:
:$app-id,
:$pem
:$pem,
;

$!gh-oauth .= new:
:$!client-id,
:$client-secret,
:$!redirect-url,
:$pem,
;

$!gh .= new:
Expand Down
2 changes: 1 addition & 1 deletion lib/OBSInterface.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ submethod TWEAK() {
headers => [
Accept => 'application/xml',
Authorization => $!auth-str,
];
]
#`[
tls => {
ssl-key-log-file => 'ssl-key-log-file',
Expand Down
5 changes: 4 additions & 1 deletion lib/RakudoCIBot.rakumod
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ submethod TWEAK() {
;
$!github-interface .= new:
app-id => config.github-app-id,
client-id => config.github-client-id,
client-secret => config.github-client-secret,
pem => $gh-pem,
processor => $!requester,
redirect-url => config.hook-url ~ "gh-oauth-callback",
;
$!requester.github-interface = $!github-interface;
$!testset-manager.register-status-listener($!requester);
Expand Down Expand Up @@ -127,7 +130,7 @@ method start() {
http => <1.1>,
host => config.web-host,
port => config.web-port,
application => routes($!source-archive-creator, $!github-interface, $!obs),
application => routes($!testset-manager, $!source-archive-creator, $!github-interface, $!obs),
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR)
]
Expand Down
Loading

0 comments on commit c167e81

Please sign in to comment.