Merge ~morphis/snappy-hwe-snaps/+git/jenkins-jobs:f/add-snap-docs-build into ~snappy-hwe-team/snappy-hwe-snaps/+git/jenkins-jobs:master

Proposed by Simon Fels
Status: Merged
Approved by: Konrad Zapałowicz
Approved revision: de9c52d08a653180f242938c7cd9ae2915f89f65
Merged at revision: 14e6ed725e26c6c417dd991d7c994062ccc10462
Proposed branch: ~morphis/snappy-hwe-snaps/+git/jenkins-jobs:f/add-snap-docs-build
Merge into: ~snappy-hwe-team/snappy-hwe-snaps/+git/jenkins-jobs:master
Diff against target: 299 lines (+234/-0)
6 files modified
jobs/snap/snap-build.yaml (+3/-0)
jobs/snap/snap-docs.sh (+38/-0)
jobs/snap/snap-docs.yaml (+38/-0)
jobs/snap/snap-project-jobs.yaml (+1/-0)
tools/se_utils/__init__.py (+90/-0)
tools/update-merge-proposal.py (+64/-0)
Reviewer Review Type Date Requested Status
Konrad Zapałowicz (community) continuous-integration Approve
Alfonso Sanchez-Beato Approve
System Enablement Bot continuous-integration Approve
Review via email: mp+330205@code.launchpad.net

Description of the change

Implement *-snap-docs build job

The new build job will build the documentation for every project and stage the generated documentation as build artifact for further inspection during the review process.

To post a comment you must log in.
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
System Enablement Bot (system-enablement-ci-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

LGTM

review: Approve
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

ack

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/jobs/snap/snap-build.yaml b/jobs/snap/snap-build.yaml
index dec3b19..e5b22f5 100644
--- a/jobs/snap/snap-build.yaml
+++ b/jobs/snap/snap-build.yaml
@@ -57,6 +57,9 @@
57 RESULTS_ID=$BUILD_TAG57 RESULTS_ID=$BUILD_TAG
58 ARCHITECTURE=$ARCHITECTURE58 ARCHITECTURE=$ARCHITECTURE
59 block: true59 block: true
60 - project: '{name}-snap-docs'
61 current-parameters: true
62 block: true
60 - project: '{name}-snap-test'63 - project: '{name}-snap-test'
61 current-parameters: true64 current-parameters: true
62 predefined-parameters: |65 predefined-parameters: |
diff --git a/jobs/snap/snap-docs.sh b/jobs/snap/snap-docs.sh
63new file mode 10064466new file mode 100644
index 0000000..e256294
--- /dev/null
+++ b/jobs/snap/snap-docs.sh
@@ -0,0 +1,38 @@
1#!/bin/sh
2#
3# Copyright (C) 2017 Canonical Ltd
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 3 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17set -ex
18
19. "$WORKSPACE/.build_env"
20
21git clone -b $GIT_REPO_BRANCH $GIT_REPO $WORKSPACE/src
22if [ ! -e $WORKSPACE/src/docs ]; then
23 echo "WARNING: repository does not contain any documentation we can build. Aborting."
24 exit 0
25fi
26
27# Run documentation through the builder and ensure everything builds nicely.
28cd $WORKSPACE/src/docs
29documentation-builder
30
31# Generate an archive which will be available as build artifact
32DATE=$(date --rfc-3339=date --utc)
33(cd $WORKSPACE/src/docs/build ; tar cJf $WORKSPACE/docs-$DATE-$BUILD_ID.tar.xz *)
34
35$BUILD_SCRIPTS/tools/update-merge-proposal.py \
36 --merge-proposal=$MERGE_PROPOSAL \
37 --approve \
38 --message="PASSED: Successfully build documentation, rev: $REVISION\n\nGenerated documentation is available at $BUILD_URL"
diff --git a/jobs/snap/snap-docs.yaml b/jobs/snap/snap-docs.yaml
0new file mode 10064439new file mode 100644
index 0000000..3954f13
--- /dev/null
+++ b/jobs/snap/snap-docs.yaml
@@ -0,0 +1,38 @@
1- job-template:
2 name: '{name}-snap-docs'
3 project-type: freestyle
4 defaults: global
5 description: "Build documentation bits of the snap"
6 display-name: "{name}-snap-docs"
7 concurrent: true
8 node: snap && build
9 parameters:
10 - string:
11 name: GIT_REPO
12 default:
13 description: "Source git repository"
14 - string:
15 name: GIT_REPO_BRANCH
16 default:
17 description: "Branch of the source git repository to use"
18 - string:
19 name: MERGE_PROPOSAL
20 default:
21 description: "Link to the merge proposal this build relates to"
22 - string:
23 name: REVISION
24 default:
25 description: "Revision from the git repository to use"
26 builders:
27 - shell:
28 !include-raw:
29 - common-job-prepare.sh
30 - shell:
31 !include-raw-escape:
32 - snap-docs.sh
33 publishers:
34 - archive:
35 artifacts: 'docs-*.tar.xz'
36 allow-empty: 'true'
37 fingerprint: true
38 default-excludes: false
0\ No newline at end of file39\ No newline at end of file
diff --git a/jobs/snap/snap-project-jobs.yaml b/jobs/snap/snap-project-jobs.yaml
index b693af3..05e4f3f 100644
--- a/jobs/snap/snap-project-jobs.yaml
+++ b/jobs/snap/snap-project-jobs.yaml
@@ -11,3 +11,4 @@
11 - '{name}-snap-trigger-ci'11 - '{name}-snap-trigger-ci'
12 - '{name}-snap-update-mp'12 - '{name}-snap-update-mp'
13 - '{name}-snap-automerger'13 - '{name}-snap-automerger'
14 - '{name}-snap-docs'
diff --git a/tools/se_utils/__init__.py b/tools/se_utils/__init__.py
index 280450c..64cc0cc 100644
--- a/tools/se_utils/__init__.py
+++ b/tools/se_utils/__init__.py
@@ -20,6 +20,7 @@ import sys
20import time20import time
21import logging21import logging
22import os22import os
23import re
23import yaml24import yaml
24from shutil import rmtree25from shutil import rmtree
25from launchpadlib.credentials import RequestTokenAuthorizationEngine26from launchpadlib.credentials import RequestTokenAuthorizationEngine
@@ -27,6 +28,11 @@ from lazr.restfulclient.errors import HTTPError
27from launchpadlib.launchpad import Launchpad28from launchpadlib.launchpad import Launchpad
28from launchpadlib.credentials import UnencryptedFileCredentialStore29from launchpadlib.credentials import UnencryptedFileCredentialStore
2930
31class LaunchpadVote():
32 APPROVE = 'Approve'
33 DISAPPROVE = 'Disapprove'
34 NEEDS_FIXING = 'Needs Fixing'
35
30ACCESS_TOKEN_POLL_TIME = 1036ACCESS_TOKEN_POLL_TIME = 10
31WAITING_FOR_USER = """Open this link:37WAITING_FOR_USER = """Open this link:
32{}38{}
@@ -120,3 +126,87 @@ def load_config():
120def get_config_option(name):126def get_config_option(name):
121 config = load_config()127 config = load_config()
122 return config[name]128 return config[name]
129
130def get_branch_handle_from_url(lp_handle, url):
131 """ Return a branch/repo handle for the given url.
132 Returns a launchpad branch or git repository handle for the given url.
133 :param lp_handle: launchpad API handle/instance
134 :param url: url of the branch or git repository
135 """
136 if '+git' in url:
137 name = url.replace('https://code.launchpad.net/', '')
138 print('fetching repo: ' + name)
139 try:
140 return lp_handle.git_repositories.getByPath(path=name)
141 except AttributeError:
142 print('git_repositories.getByPath was not found. You may need to set lp_version=devel in the config')
143 return None
144 else:
145 name = url.replace('https://code.launchpad.net/', 'lp:')
146 name = name.replace('https://code.staging.launchpad.net/', 'lp://staging/')
147 print('fetching branch: ' + name)
148 return lp_handle.branches.getByUrl(url=name)
149
150def get_branch_from_mp(merge_proposal):
151 """Return a link to branch given a link to a merge proposal.
152
153 If merge_proposal is:
154 https://copde.launchpad.net/~user/project/name/+merge/12345
155 then the result will be:
156 https://copde.launchpad.net/~user/project/name/
157
158 :param merge_proposal: url of a launchpad merge proposal
159 """
160 m = re.search('(.*)\+merge/[0-9]+$', merge_proposal)
161 if m:
162 return m.group(1)
163 return None
164
165def get_mp_handle_from_url(lp_handle, merge_proposal_link):
166 """ Get launchpad handle for merge proposal given a merge proposal URL.
167
168 Returns None in case the merge proposal can't be found.
169 :param merge_proposal_link: URL of the merge proposal
170 """
171 branch_link = get_branch_from_mp(merge_proposal_link)
172 if not branch_link:
173 print('Unable to get branch link from merge proposal link.')
174 return None
175
176 branch = get_branch_handle_from_url(lp_handle, branch_link)
177 if not branch:
178 print('Branch {} does not exist'.format(branch_link))
179 return None
180
181 print('mp_link: {}.'.format(merge_proposal_link))
182
183 for mp in branch.landing_targets:
184 print('mp.web_link: {}'.format(mp.web_link))
185 if mp.web_link == merge_proposal_link:
186 return mp
187
188 return None
189
190def get_vote_subject(mp):
191 """Given a mp handle return a subject for the vote message
192
193 Unfortunately there is no method in the API that gives you the "standard"
194 subject that launchapd is using and some email clients (gmail) are
195 grouping conversations into threads based on subject.
196
197 This returns what seems to be the launchpad way of doing subjects.
198 :param mp: launchpad merge proposal handle
199 """
200
201 if '+git' in mp.web_link:
202 source = mp.source_git_repository.display_name.replace('lp:', '') + \
203 ':' + \
204 mp.source_git_path.replace('refs/heads/', '')
205 target = mp.target_git_repository.display_name.replace('lp:', '') + \
206 ':' + \
207 mp.target_git_path.replace('refs/heads/', '')
208 return 'Re: [Merge] {} into {}'.format(source, target)
209 else:
210 return 'Re: [Merge] {} into {}'.format(
211 mp.source_branch.display_name,
212 mp.target_branch.display_name)
123\ No newline at end of file213\ No newline at end of file
diff --git a/tools/se_utils/__init__.pyc b/tools/se_utils/__init__.pyc
124deleted file mode 100644214deleted file mode 100644
index f1be9ca..0000000
125Binary files a/tools/se_utils/__init__.pyc and /dev/null differ215Binary files a/tools/se_utils/__init__.pyc and /dev/null differ
diff --git a/tools/update-merge-proposal.py b/tools/update-merge-proposal.py
126new file mode 100755216new file mode 100755
index 0000000..9e0b95a
--- /dev/null
+++ b/tools/update-merge-proposal.py
@@ -0,0 +1,64 @@
1#!/usr/bin/env python
2# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
3#
4# Copyright (C) 2017 Canonical Ltd
5#
6# This program is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License version 3 as
8# published by the Free Software Foundation.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18import atexit
19import sys
20import time
21import logging
22import os
23import yaml
24import re
25from shutil import rmtree
26from argparse import ArgumentParser
27
28import se_utils
29
30parser = ArgumentParser(description="Vote on a Launchpad merge proposal.")
31parser.add_argument('-p', '--merge-proposal', required=True, help="URL of the merge proposal to update")
32parser.add_argument('-a', '--approve', action='store_true', help="approve merge proposal")
33parser.add_argument('-d', '--disapprove', action='store_true', help="disapprove merge proposal")
34parser.add_argument('-m', '--message', help="message to add as a comment to the merge-proposal")
35
36args = vars(parser.parse_args())
37
38# Get us connected with launchpad
39lp_app = se_utils.get_config_option("lp_app")
40lp_env = se_utils.get_config_option("lp_env")
41credential_store_path = se_utils.get_config_option('credential_store_path')
42lp_handle = se_utils.get_launchpad(None, credential_store_path, lp_app, lp_env)
43
44mp = se_utils.get_mp_handle_from_url(lp_handle, args["merge_proposal"])
45if not mp:
46 parser.error('merge proposal related to this branch was not found')
47
48content = args["message"]
49if content is None or len(content) == 0:
50 parser.error('no message was provided')
51# Unescape message to ensure we get all new lines etc.
52content = content.decode('string_escape')
53
54if not args['approve'] and not args['disapprove']:
55 parser.error('neither approved or disapproved the MP')
56
57vote=""
58if args["approve"]:
59 vote = se_utils.LaunchpadVote.APPROVE
60else if args["disapprove"]:
61 vote = se_utils.LaunchpadVote.DISAPPROVE
62
63subject = se_utils.get_vote_subject(mp)
64mp.createComment(content=content, subject=subject)

Subscribers

People subscribed via source and target branches

to all changes: