Show More
@@ -0,0 +1,99 b'' | |||||
|
1 | # try_server.py - Interact with Try server | |||
|
2 | # | |||
|
3 | # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | # no-check-code because Python 3 native. | |||
|
9 | ||||
|
10 | import base64 | |||
|
11 | import json | |||
|
12 | import os | |||
|
13 | import subprocess | |||
|
14 | import tempfile | |||
|
15 | ||||
|
16 | from .aws import AWSConnection | |||
|
17 | ||||
|
18 | LAMBDA_FUNCTION = "ci-try-server-upload" | |||
|
19 | ||||
|
20 | ||||
|
21 | def trigger_try(c: AWSConnection, rev="."): | |||
|
22 | """Trigger a new Try run.""" | |||
|
23 | lambda_client = c.session.client("lambda") | |||
|
24 | ||||
|
25 | cset, bundle = generate_bundle(rev=rev) | |||
|
26 | ||||
|
27 | payload = { | |||
|
28 | "bundle": base64.b64encode(bundle).decode("utf-8"), | |||
|
29 | "node": cset["node"], | |||
|
30 | "branch": cset["branch"], | |||
|
31 | "user": cset["user"], | |||
|
32 | "message": cset["desc"], | |||
|
33 | } | |||
|
34 | ||||
|
35 | print("resolved revision:") | |||
|
36 | print("node: %s" % cset["node"]) | |||
|
37 | print("branch: %s" % cset["branch"]) | |||
|
38 | print("user: %s" % cset["user"]) | |||
|
39 | print("desc: %s" % cset["desc"].splitlines()[0]) | |||
|
40 | print() | |||
|
41 | ||||
|
42 | print("sending to Try...") | |||
|
43 | res = lambda_client.invoke( | |||
|
44 | FunctionName=LAMBDA_FUNCTION, | |||
|
45 | InvocationType="RequestResponse", | |||
|
46 | Payload=json.dumps(payload).encode("utf-8"), | |||
|
47 | ) | |||
|
48 | ||||
|
49 | body = json.load(res["Payload"]) | |||
|
50 | for message in body: | |||
|
51 | print("remote: %s" % message) | |||
|
52 | ||||
|
53 | ||||
|
54 | def generate_bundle(rev="."): | |||
|
55 | """Generate a bundle suitable for use by the Try service. | |||
|
56 | ||||
|
57 | Returns a tuple of revision metadata and raw Mercurial bundle data. | |||
|
58 | """ | |||
|
59 | # `hg bundle` doesn't support streaming to stdout. So we use a temporary | |||
|
60 | # file. | |||
|
61 | path = None | |||
|
62 | try: | |||
|
63 | fd, path = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg") | |||
|
64 | os.close(fd) | |||
|
65 | ||||
|
66 | args = [ | |||
|
67 | "hg", | |||
|
68 | "bundle", | |||
|
69 | "--type", | |||
|
70 | "gzip-v2", | |||
|
71 | "--base", | |||
|
72 | "public()", | |||
|
73 | "--rev", | |||
|
74 | rev, | |||
|
75 | path, | |||
|
76 | ] | |||
|
77 | ||||
|
78 | print("generating bundle...") | |||
|
79 | subprocess.run(args, check=True) | |||
|
80 | ||||
|
81 | with open(path, "rb") as fh: | |||
|
82 | bundle_data = fh.read() | |||
|
83 | ||||
|
84 | finally: | |||
|
85 | if path: | |||
|
86 | os.unlink(path) | |||
|
87 | ||||
|
88 | args = [ | |||
|
89 | "hg", | |||
|
90 | "log", | |||
|
91 | "-r", | |||
|
92 | rev, | |||
|
93 | # We have to upload as JSON, so it won't matter if we emit binary | |||
|
94 | # since we need to normalize to UTF-8. | |||
|
95 | "-T", | |||
|
96 | "json", | |||
|
97 | ] | |||
|
98 | res = subprocess.run(args, check=True, capture_output=True) | |||
|
99 | return json.loads(res.stdout)[0], bundle_data |
@@ -33,6 +33,46 b" side-effects so they don't impact the lo" | |||||
33 | into a remote machine, we create a temporary directory for the SSH |
|
33 | into a remote machine, we create a temporary directory for the SSH | |
34 | config so the user's known hosts file isn't updated. |
|
34 | config so the user's known hosts file isn't updated. | |
35 |
|
35 | |||
|
36 | Try Server | |||
|
37 | ========== | |||
|
38 | ||||
|
39 | There exists a *Try Server* which allows automation to run against | |||
|
40 | an arbitrary Mercurial changeset and displays results via the web. | |||
|
41 | ||||
|
42 | .. note:: | |||
|
43 | ||||
|
44 | The *Try Server* is still experimental infrastructure. | |||
|
45 | ||||
|
46 | To use the *Try Server*:: | |||
|
47 | ||||
|
48 | $ ./automation.py try | |||
|
49 | ||||
|
50 | With a custom AWS profile:: | |||
|
51 | ||||
|
52 | $ AWS_PROFILE=hg contrib/automation/automation.py try | |||
|
53 | ||||
|
54 | By default, the ``.`` revision is submitted. **Any uncommitted changes | |||
|
55 | are not submitted.** | |||
|
56 | ||||
|
57 | To switch which revision is used:: | |||
|
58 | ||||
|
59 | $ ./automation.py try -r abcdef | |||
|
60 | ||||
|
61 | Access to the *Try Server* requires access to a special AWS account. | |||
|
62 | This account is currently run by Gregory Szorc. Here is the procedure | |||
|
63 | for accessing the *Try Server*: | |||
|
64 | ||||
|
65 | 1. Email Gregory Szorc at gregory.szorc@gmail.com and request a | |||
|
66 | username. This username will be stored in the public domain. | |||
|
67 | 2. Wait for an email reply containing your temporary AWS credentials. | |||
|
68 | 3. Log in at https://gregoryszorc-hg.signin.aws.amazon.com/console | |||
|
69 | and set a new, secure password. | |||
|
70 | 4. Go to https://console.aws.amazon.com/iam/home?region=us-west-2#/security_credentials | |||
|
71 | 5. Under ``Access keys for CLI, SDK, & API access``, click the | |||
|
72 | ``Create access key`` button. | |||
|
73 | 6. See the ``AWS Integration`` section for instructions on | |||
|
74 | configuring your local client to use the generated credentials. | |||
|
75 | ||||
36 | AWS Integration |
|
76 | AWS Integration | |
37 | =============== |
|
77 | =============== | |
38 |
|
78 |
@@ -17,6 +17,7 b' from . import (' | |||||
17 | aws, |
|
17 | aws, | |
18 | HGAutomation, |
|
18 | HGAutomation, | |
19 | linux, |
|
19 | linux, | |
|
20 | try_server, | |||
20 | windows, |
|
21 | windows, | |
21 | ) |
|
22 | ) | |
22 |
|
23 | |||
@@ -193,6 +194,11 b' def publish_windows_artifacts(hg: HGAuto' | |||||
193 | ssh_username=ssh_username) |
|
194 | ssh_username=ssh_username) | |
194 |
|
195 | |||
195 |
|
196 | |||
|
197 | def run_try(hga: HGAutomation, aws_region: str, rev: str): | |||
|
198 | c = hga.aws_connection(aws_region, ensure_ec2_state=False) | |||
|
199 | try_server.trigger_try(c, rev=rev) | |||
|
200 | ||||
|
201 | ||||
196 | def get_parser(): |
|
202 | def get_parser(): | |
197 | parser = argparse.ArgumentParser() |
|
203 | parser = argparse.ArgumentParser() | |
198 |
|
204 | |||
@@ -439,6 +445,15 b' def get_parser():' | |||||
439 | ) |
|
445 | ) | |
440 | sp.set_defaults(func=publish_windows_artifacts) |
|
446 | sp.set_defaults(func=publish_windows_artifacts) | |
441 |
|
447 | |||
|
448 | sp = subparsers.add_parser( | |||
|
449 | 'try', | |||
|
450 | help='Run CI automation against a custom changeset' | |||
|
451 | ) | |||
|
452 | sp.add_argument('-r', '--rev', | |||
|
453 | default='.', | |||
|
454 | help='Revision to run CI on') | |||
|
455 | sp.set_defaults(func=run_try) | |||
|
456 | ||||
442 | return parser |
|
457 | return parser | |
443 |
|
458 | |||
444 |
|
459 |
@@ -18,6 +18,7 b' New errors are not allowed. Warnings are' | |||||
18 | Skipping contrib/automation/hgautomation/linux.py it has no-che?k-code (glob) |
|
18 | Skipping contrib/automation/hgautomation/linux.py it has no-che?k-code (glob) | |
19 | Skipping contrib/automation/hgautomation/pypi.py it has no-che?k-code (glob) |
|
19 | Skipping contrib/automation/hgautomation/pypi.py it has no-che?k-code (glob) | |
20 | Skipping contrib/automation/hgautomation/ssh.py it has no-che?k-code (glob) |
|
20 | Skipping contrib/automation/hgautomation/ssh.py it has no-che?k-code (glob) | |
|
21 | Skipping contrib/automation/hgautomation/try_server.py it has no-che?k-code (glob) | |||
21 | Skipping contrib/automation/hgautomation/windows.py it has no-che?k-code (glob) |
|
22 | Skipping contrib/automation/hgautomation/windows.py it has no-che?k-code (glob) | |
22 | Skipping contrib/automation/hgautomation/winrm.py it has no-che?k-code (glob) |
|
23 | Skipping contrib/automation/hgautomation/winrm.py it has no-che?k-code (glob) | |
23 | Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob) |
|
24 | Skipping contrib/packaging/hgpackaging/downloads.py it has no-che?k-code (glob) |
General Comments 0
You need to be logged in to leave comments.
Login now