1#!/usr/bin/env nix-shell
2#!nix-shell -i perl -p perl -p perlPackages.JSON perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.TermReadKey
3
4# This script generates a list of teams to ping for the Feature Freeze announcement on Discourse.
5# It's intended to be used by Release Managers before creating such posts.
6#
7# The script interactively reads a GitHub username and a corresponding GitHub Personal Access token.
8# This is required to access the GitHub Teams API so the token needs at least the read:org privilege.
9
10## no critic (InputOutput::RequireCheckedSyscalls, InputOutput::ProhibitBacktickOperators)
11use strict;
12use warnings;
13use Carp;
14use Cwd 'abs_path';
15use File::Basename;
16use JSON qw(decode_json);
17use LWP::UserAgent;
18use Term::ReadKey qw(ReadLine ReadMode);
19
20sub github_team_members {
21 my ($team_name, $username, $token) = @_;
22 my @ret;
23
24 my $req = HTTP::Request->new('GET', "https://api.github.com/orgs/NixOS/teams/$team_name/members", [ 'Accept' => 'application/vnd.github.v3+json' ]);
25 $req->authorization_basic($username, $token);
26 my $response = LWP::UserAgent->new->request($req);
27
28 if ($response->is_success) {
29 my $content = decode_json($response->decoded_content);
30 foreach (@{$content}) {
31 push @ret, $_->{'login'};
32 }
33 } else {
34 print {*STDERR} "!! Requesting members of GitHub Team '$team_name' failed: " . $response->status_line;
35 }
36
37 return \@ret;
38}
39
40# Read GitHub credentials
41print {*STDERR} 'GitHub username: ';
42my $github_user = ReadLine(0);
43ReadMode('noecho');
44print {*STDERR} 'GitHub personal access token (no echo): ';
45my $github_token = ReadLine(0);
46ReadMode('restore');
47print {*STDERR} "\n";
48chomp $github_user;
49chomp $github_token;
50
51# Read nix output
52my $nix_version = `nix --version`;
53my $out;
54my $lib_path = abs_path(dirname(__FILE__)) . '../../../lib';
55if ($nix_version =~ m/2[.]3[.]/msx) {
56 $out = `nix eval --json '(import $lib_path).teams'` || croak 'nix eval failed';
57} else {
58 $out = `nix --extra-experimental-features nix-command eval --json --impure --expr '(import $lib_path).teams'` || croak('nix eval failed');
59}
60my $data = decode_json($out);
61
62# Process teams
63print {*STDERR} "\n";
64while (my ($team_nix_key, $team_config) = each %{$data}) {
65 # Ignore teams that don't want to be or can't be pinged
66 if (not defined $team_config->{enableFeatureFreezePing} or not $team_config->{enableFeatureFreezePing}) {
67 next;
68 }
69 if (not defined $team_config->{shortName}) {
70 print {*STDERR} "!! The team with the nix key '$team_nix_key' has no shortName set - ignoring";
71 next;
72 }
73 # Team name
74 print {*STDERR} "$team_config->{shortName}:";
75 # GitHub Teams
76 my @github_members;
77 if (defined $team_config->{githubTeams}) {
78 foreach (@{$team_config->{githubTeams}}) {
79 print {*STDERR} " \@NixOS/${_}";
80 push @github_members, @{github_team_members($_, $github_user, $github_token)};
81 }
82 }
83 my %github_members = map { $_ => 1 } @github_members;
84 # Members
85 if (defined $team_config->{members}) {
86 foreach (@{$team_config->{members}}) {
87 my %user = %{$_};
88 my $github_handle = $user{'github'};
89 # Ensure we don't ping team members twice (as team member and directly)
90 if (defined $github_members{$github_handle}) {
91 next;
92 }
93 print {*STDERR} " \@$github_handle";
94 }
95 }
96
97 print {*STDERR} "\n";
98}