Commit | Line | Data |
6c315353 |
1 | #!/usr/bin/perl |
2 | |
3 | eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' |
4 | if 0; # not running under some shell |
5 | use strict; |
6 | use warnings; |
7 | use Getopt::Long; |
8 | use Pod::Usage; |
9 | |
10 | BEGIN { |
11 | eval { require WWW::Mechanize }; |
12 | if ($@) { |
13 | warn "\nCannot load WWW::Mechanize. " |
14 | . "\nPlease install it before using smolder_smoke_signal.\n"; |
15 | exit(1); |
16 | } |
17 | } |
18 | |
19 | =pod |
20 | |
21 | =head1 NAME |
22 | |
23 | smolder_smoke_signal |
24 | |
25 | =head1 SYNOPSIS |
26 | |
27 | ./bin/smolder_smoke_signal --server smolder.foo.com \ |
28 | --username myself --password s3cr3t --file test_report.xml \ |
29 | --project MyProject |
30 | |
31 | =head1 DESCRIPTION |
32 | |
33 | Script used to upload a Smoke test report to a running smolder server. |
34 | This is extremely useful for scripted/automatic test runs but also |
35 | helpful when using a CLI makes things faster. |
36 | |
37 | =head1 OPTIONS |
38 | |
39 | =head2 REQUIRED |
40 | |
41 | =over |
42 | |
43 | =item server |
44 | |
45 | This is the hostname (and port if not 80) of the running Smolder server. |
46 | |
47 | =item project |
48 | |
49 | The name of the Smolder project to use for the upload. |
50 | |
51 | =item username |
52 | |
53 | The name of the Smolder user to use for the upload. |
54 | |
55 | =item password |
56 | |
57 | The password for the Smolder user given by C<username>. |
58 | |
59 | =item file |
60 | |
61 | The name of the file to upload. Please see F<docs/upload_file_format.pod> |
62 | for more details about the format that Smolder expects this file to |
63 | take. |
64 | |
65 | =back |
66 | |
67 | =head2 OPTIONAL |
68 | |
69 | =over |
70 | |
71 | =item port |
72 | |
73 | If your Smolder server is running on a port other than 80, then you |
74 | can specify it here. |
75 | |
76 | =item architecture |
77 | |
78 | The architecture for the given smoke test run. If none is given |
79 | it will use the default architecture for the project. |
80 | |
81 | =item platform |
82 | |
83 | The platform for the given smoke test run. If none is given |
84 | it will use the default platform for the project. |
85 | |
86 | =item revision |
87 | |
88 | The revision control number for this test run. Only applies to |
89 | projects that use revision control (shouldn't they all) and only |
90 | applies to tests run against a checkout from revision control. |
91 | |
92 | This is just a free form text option so it will work with any |
93 | revision number that your preferred revision control system uses. |
94 | |
95 | =item tags |
96 | |
97 | A comma separated list of tags that are given for this smoke report run. |
98 | |
99 | ./bin/smolder_smoke_signal --server smolder.foo.com \ |
100 | --username myself --password s3cr3t --file test_report.xml \ |
101 | --project MyProject --tags "Foo, My Bar" |
102 | |
103 | =item comments |
104 | |
105 | Any comments that you want to associate with the smoke test run. |
106 | |
107 | =item verbose |
108 | |
109 | Print verbose output of our actions to STDOUT. |
110 | |
111 | =cut |
112 | |
113 | # default options |
114 | my ($server, $project, $user, $pw, $file, $arch, $platform, $tags, $comments, $verbose, $rev, |
115 | $port); |
116 | my ($help, $man); |
117 | |
118 | GetOptions( |
119 | 'server=s' => \$server, |
120 | 'port=s' => \$port, |
121 | 'project=s' => \$project, |
122 | 'username=s' => \$user, |
123 | 'password=s' => \$pw, |
124 | 'file=s' => \$file, |
125 | 'architecture=s' => \$arch, |
126 | 'platform=s' => \$platform, |
127 | 'tags=s' => \$tags, |
128 | 'comments=s' => \$comments, |
129 | 'revision=s' => \$rev, |
130 | 'verbose!' => \$verbose, |
131 | 'help' => \$help, |
132 | 'man' => \$man, |
133 | ) || pod2usage(); |
134 | |
135 | if ($help) { |
136 | pod2usage( |
137 | -exitval => 0, |
138 | -verbose => 1, |
139 | ); |
140 | } elsif ($man) { |
141 | pod2usage( |
142 | -exitval => 0, |
143 | -verbose => 2, |
144 | ); |
145 | } |
146 | |
147 | # make sure all the required fields are there |
148 | _missing_required('server') unless $server; |
149 | _missing_required('project') unless $project; |
150 | _missing_required('username') unless $user; |
151 | _missing_required('password') unless $pw; |
152 | _missing_required('file') unless $file; |
153 | |
154 | # make sure our file is there and is of the right type |
155 | if (-r $file) { |
156 | unless ($file =~ /\.tar(\.gz)?$/) { |
157 | warn "File '$file' is not of the correct type!\n"; |
158 | exit(1); |
159 | } |
160 | } else { |
161 | warn "File '$file' does not exist, or is not readable!\n"; |
162 | exit(1); |
163 | } |
164 | |
165 | # try and reach the smolder server |
166 | print "Trying to reach Smolder server at $server.\n" if ($verbose); |
167 | $port ||= 80; |
168 | my $mech = WWW::Mechanize->new(); |
169 | my $base_url = "http://$server:$port/app"; |
170 | eval { $mech->get($base_url) }; |
171 | unless ($mech->status eq '200') { |
172 | warn "Could not reach $server:$port successfully. Received status " . $mech->status . "\n"; |
173 | exit(1); |
174 | } |
175 | |
176 | # now login |
177 | print "Trying to login with username '$user'.\n" if ($verbose); |
178 | $mech->get($base_url . '/public_auth/login'); |
179 | my $form = $mech->form_name('login'); |
180 | if ($mech->status ne '200' || !$form) { |
181 | warn "Could not reach Smolder login form. Are you sure $server:$port is a Smolder server?\n"; |
182 | exit(1); |
183 | } |
184 | $mech->set_fields( |
185 | username => $user, |
186 | password => $pw, |
187 | ); |
188 | $mech->submit(); |
189 | my $content = $mech->content; |
190 | if ($mech->status ne '200' || $content !~ /Welcome \Q$user\E/) { |
191 | warn "Could not login with username '$user' and password '$pw'!\n"; |
192 | exit(1); |
193 | } |
194 | |
195 | # now go to this project's page |
196 | print "Retrieving project listing for user '$user'.\n" if ($verbose); |
197 | $mech->get($base_url . '/developer_projects'); |
198 | $content = $mech->content; |
199 | $content =~ />\Q$project\E<!--ID:(\d+)-->/; |
200 | my $project_id = $1; |
201 | if ($mech->status ne '200' || !$project_id) { |
202 | warn "Could not get your project listing, or you are not a member of the '$project' project!\n"; |
203 | exit(1); |
204 | } |
205 | |
206 | # now go to the add-smoke-report page for this project |
207 | print "Adding smoke report to project '$project'.\n" if ($verbose); |
208 | $mech->get($base_url . "/developer_projects/add_report/$project_id"); |
209 | $content = $mech->content; |
210 | if ($mech->status ne '200' || $content !~ /New Smoke Report/) { |
211 | warn "Could not reach the Add Smoke Report form!\n"; |
212 | exit(1); |
213 | } |
214 | $mech->form_name('add_report'); |
215 | my %fields = (report_file => $file); |
216 | $fields{platform} = $platform if $platform; |
217 | $fields{architecture} = $arch if $arch; |
218 | $fields{tags} = $tags if $tags; |
219 | $fields{comments} = $comments if $comments; |
220 | $fields{revision} = $rev if $rev; |
221 | $mech->set_fields(%fields); |
222 | $mech->submit(); |
223 | |
224 | $content = $mech->content; |
225 | if ($mech->status ne '200' || $content !~ /Recent Smoke Reports/) { |
226 | warn "Could not upload smoke report with the given information!\n"; |
227 | exit(1); |
228 | } |
229 | $content =~ /#(\d+) Added/; |
230 | my $report_id = $1; |
231 | |
232 | print "\nReport successfully uploaded as #$report_id.\n"; |
233 | |
234 | ########################################################## |
235 | # helper methods |
236 | ########################################################## |
237 | sub _missing_required { |
238 | my $field = shift; |
239 | warn "Missing required field '$field'!\n"; |
240 | pod2usage(); |
241 | } |