Merge lp:~renatofilho/account-polld/query-calendars into lp:~ubuntu-push-hackers/account-polld/trunk
- query-calendars
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~renatofilho/account-polld/query-calendars |
Merge into: | lp:~ubuntu-push-hackers/account-polld/trunk |
Diff against target: |
247 lines (+107/-49) 3 files modified
cmd/account-polld/account_manager.go (+0/-8) plugins/gcalendar/gcalendar.go (+81/-37) plugins/gcalendar/syncmonitor.go (+26/-4) |
To merge this branch: | bzr merge lp:~renatofilho/account-polld/query-calendars |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jonas G. Drange (community) | Approve | ||
system-apps-ci-bot | continuous-integration | Approve | |
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+296049@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-07-19.
Commit message
Check for changes on each calendar.
Description of the change
- 168. By Renato Araujo Oliveira Filho
-
More debug messages.
- 169. By Renato Araujo Oliveira Filho
-
Check if sync monitor is 'idle' before query for information.
- 170. By Renato Araujo Oliveira Filho
-
Use the correct calendar id to check for changes.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
- 171. By Renato Araujo Oliveira Filho
-
Update to use new sync monitor API.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:171
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 172. By Renato Araujo Oliveira Filho
-
Request sync using calendar id.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:172
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 173. By Renato Araujo Oliveira Filho
-
Sync new calendars.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:173
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 174. By Renato Araujo Oliveira Filho
-
Use calendar id to retrieve last sync date.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:174
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 175. By Renato Araujo Oliveira Filho
-
Added debug messages.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:175
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 176. By Renato Araujo Oliveira Filho
-
Extra debug.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:176
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 177. By Renato Araujo Oliveira Filho
-
Encode calendar names before query for changes.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:177
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 178. By Renato Araujo Oliveira Filho
-
Return error to plugin manager in case of 'ErrTokenExpired'.
system-apps-ci-bot (system-apps-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:178
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Jonas G. Drange (jonas-drange) wrote : | # |
L128, 136, 164: Maybe prefix these with “calendar:” as you have done elsewhere, so it becomes easier to understand the log output.
I also saw that the calendar did not display the correct timezone: http://
One other thing was that it seems the sync got in a bad state. Compare http://
- 179. By Renato Araujo Oliveira Filho
-
Added prefix "calendar" to log.
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
Thanks jonas,
> L128, 136, 164: Maybe prefix these with “calendar:” as you have done
> elsewhere, so it becomes easier to understand the log output.
Fixed on rev 179.
>
> I also saw that the calendar did not display the correct timezone:
> http://
Are you using the latest application, there is a click package on silo 73 that should be used with this branch. If the error still could you report a bug. This looks like not related with these changes.
>
> One other thing was that it seems the sync got in a bad state. Compare
> http://
> the same calendar, and I only have that one calendar installed.
What is the diff? I do not see the problem, could you point that? And make sure that you are using the latest app.
Thanks.
- 180. By Renato Araujo Oliveira Filho
-
Trunk merged.
- 181. By Renato Araujo Oliveira Filho
-
Merged: lp:~artmello/account-polld/account-polld-notifications, to fix build problems.
Unmerged revisions
Preview Diff
1 | === modified file 'cmd/account-polld/account_manager.go' |
2 | --- cmd/account-polld/account_manager.go 2015-11-03 13:40:45 +0000 |
3 | +++ cmd/account-polld/account_manager.go 2016-07-19 14:12:26 +0000 |
4 | @@ -24,7 +24,6 @@ |
5 | "launchpad.net/account-polld/accounts" |
6 | "launchpad.net/account-polld/plugins" |
7 | "launchpad.net/ubuntu-push/click" |
8 | - "launchpad.net/ubuntu-push/click/cblacklist" |
9 | ) |
10 | |
11 | type AccountManager struct { |
12 | @@ -52,8 +51,6 @@ |
13 | clickNotInstalledError = errors.New("Click not installed") |
14 | ) |
15 | |
16 | -var isBlacklisted = cblacklist.IsBlacklisted |
17 | - |
18 | func NewAccountManager(watcher *accounts.Watcher, postWatch chan *PostWatch, plugin plugins.Plugin) *AccountManager { |
19 | return &AccountManager{ |
20 | watcher: watcher, |
21 | @@ -80,11 +77,6 @@ |
22 | } |
23 | } |
24 | |
25 | - if id, ok := click.ParseAppId(string(a.plugin.ApplicationId())); (ok == nil) && isBlacklisted(id) { |
26 | - log.Printf("Account %d is blacklisted, not polling", a.authData.AccountId) |
27 | - return |
28 | - } |
29 | - |
30 | if a.penaltyCount > 0 { |
31 | log.Printf("Leaving poll for account %d as penalty count is %d", a.authData.AccountId, a.penaltyCount) |
32 | a.penaltyCount-- |
33 | |
34 | === modified file 'plugins/gcalendar/gcalendar.go' |
35 | --- plugins/gcalendar/gcalendar.go 2016-04-14 15:03:27 +0000 |
36 | +++ plugins/gcalendar/gcalendar.go 2016-07-19 14:12:26 +0000 |
37 | @@ -32,7 +32,7 @@ |
38 | pluginName = "gcalendar" |
39 | ) |
40 | |
41 | -var baseUrl, _ = url.Parse("https://www.googleapis.com/calendar/v3/calendars/primary/") |
42 | +var baseUrl,_ = url.Parse("https://www.googleapis.com/calendar/v3/calendars/") |
43 | |
44 | type GCalendarPlugin struct { |
45 | accountId uint |
46 | @@ -49,42 +49,83 @@ |
47 | func (p *GCalendarPlugin) Poll(authData *accounts.AuthData) ([]*plugins.PushMessageBatch, error) { |
48 | // This envvar check is to ease testing. |
49 | if token := os.Getenv("ACCOUNT_POLLD_TOKEN_GCALENDAR"); token != "" { |
50 | + log.Print("calendar: Using token from: ACCOUNT_POLLD_TOKEN_GCALENDAR env var") |
51 | authData.AccessToken = token |
52 | } |
53 | |
54 | + log.Print("calendar: Check calendar changes for account:", p.accountId) |
55 | + |
56 | syncMonitor := NewSyncMonitor() |
57 | if syncMonitor == nil { |
58 | - log.Print("Sync monitor not available yet.") |
59 | - return nil, nil |
60 | - } |
61 | - |
62 | - lastSyncDate, err := syncMonitor.LastSyncDate(p.accountId, "calendar") |
63 | - if err != nil { |
64 | - log.Print("calendar plugin ", p.accountId, ": cannot load previous sync date: ", err, ". Try next time.") |
65 | - return nil, nil |
66 | - } else { |
67 | - log.Print("calendar plugin ", p.accountId, ": last sync date: ", lastSyncDate) |
68 | - } |
69 | - |
70 | - resp, err := p.requestChanges(authData.AccessToken, lastSyncDate) |
71 | - if err != nil { |
72 | - return nil, err |
73 | - } |
74 | - |
75 | - messages, err := p.parseChangesResponse(resp) |
76 | - if err != nil { |
77 | - return nil, err |
78 | - } |
79 | - |
80 | - if len(messages) > 0 { |
81 | - // Update last sync date |
82 | - log.Print("Request calendar sync") |
83 | - err = syncMonitor.SyncAccount(p.accountId, "calendar") |
84 | - if err != nil { |
85 | - log.Print("Fail to start calendar sync ", p.accountId, " error: ", err) |
86 | - } |
87 | - } else { |
88 | - log.Print("Found no calendar updates for account: ", p.accountId) |
89 | + log.Print("calendar: Sync monitor not available yet.") |
90 | + return nil, nil |
91 | + } |
92 | + |
93 | + state, err := syncMonitor.State() |
94 | + if err != nil { |
95 | + log.Print("calendar: Fail to retrieve sync monitor state ", err) |
96 | + return nil, nil |
97 | + } |
98 | + if state != "idle" { |
99 | + log.Print("calendar: Sync monitor is not on 'idle' state, try later!") |
100 | + return nil, nil |
101 | + } |
102 | + |
103 | + calendars, err := syncMonitor.ListCalendarsByAccount(p.accountId) |
104 | + if err != nil { |
105 | + log.Print("calendar: Calendar plugin ", p.accountId, ": cannot load calendars: ", err) |
106 | + return nil, nil |
107 | + } |
108 | + |
109 | + var calendarsToSync []string |
110 | + log.Print("calendar: Number of calendars for account:", p.accountId, " size:", len(calendars)) |
111 | + |
112 | + for id, calendar := range calendars { |
113 | + lastSyncDate, err := syncMonitor.LastSyncDate(p.accountId, id) |
114 | + if err != nil { |
115 | + log.Print("\tcalendar: ", calendar, ", cannot load previous sync date: ", err, ". Try next time.") |
116 | + continue |
117 | + } else { |
118 | + log.Print("\tcalendar: ", calendar, " Id: ", id, ": last sync date: ", lastSyncDate) |
119 | + } |
120 | + |
121 | + var needSync bool |
122 | + needSync = (len(lastSyncDate) == 0) |
123 | + |
124 | + if !needSync { |
125 | + resp, err := p.requestChanges(authData.AccessToken, id, lastSyncDate) |
126 | + if err != nil { |
127 | + log.Print("\tcalendar: ERROR: Fail to query for changes: ", err) |
128 | + continue |
129 | + } |
130 | + |
131 | + messages, err := p.parseChangesResponse(resp) |
132 | + if err != nil { |
133 | + log.Print("\tcalendar: ERROR: Fail to parse changes: ", err) |
134 | + if err == plugins.ErrTokenExpired { |
135 | + log.Print("\t\tcalendar: Abort poll") |
136 | + return nil, err |
137 | + } else { |
138 | + continue |
139 | + } |
140 | + } |
141 | + needSync = (len(messages) > 0) |
142 | + } |
143 | + |
144 | + if needSync { |
145 | + log.Print("\tcalendar: Calendar needs sync: ", calendar) |
146 | + calendarsToSync = append(calendarsToSync, id) |
147 | + } else { |
148 | + log.Print("\tcalendar: Found no calendar updates for account: ", p.accountId, " calendar: ", calendar) |
149 | + } |
150 | + } |
151 | + |
152 | + if len(calendarsToSync) > 0 { |
153 | + log.Print("calendar: Request account sync") |
154 | + err = syncMonitor.SyncAccount(p.accountId, calendarsToSync) |
155 | + if err != nil { |
156 | + log.Print("calendar: ERROR: Fail to start account sync ", p.accountId, " message: ", err) |
157 | + } |
158 | } |
159 | |
160 | return nil, nil |
161 | @@ -96,6 +137,7 @@ |
162 | |
163 | if resp.StatusCode != http.StatusOK { |
164 | var errResp errorResp |
165 | + log.Print("calendar: Invalid response:", errResp.Err.Code) |
166 | if err := decoder.Decode(&errResp); err != nil { |
167 | return nil, err |
168 | } |
169 | @@ -107,24 +149,26 @@ |
170 | |
171 | var events eventList |
172 | if err := decoder.Decode(&events); err != nil { |
173 | + log.Print("calendar: Fail to decode") |
174 | return nil, err |
175 | } |
176 | |
177 | for _, ev := range events.Events { |
178 | - log.Print("Found event: ", ev.Etag, ev.Summary) |
179 | + log.Print("calendar: Found event: ", ev.Etag, ev.Summary) |
180 | } |
181 | |
182 | return events.Events, nil |
183 | } |
184 | |
185 | -func (p *GCalendarPlugin) requestChanges(accessToken string, lastSyncDate string) (*http.Response, error) { |
186 | - u, err := baseUrl.Parse("events") |
187 | +func (p *GCalendarPlugin) requestChanges(accessToken string, calendar string, lastSyncDate string) (*http.Response, error) { |
188 | + u, err := baseUrl.Parse("") |
189 | if err != nil { |
190 | return nil, err |
191 | } |
192 | + u.Path += calendar + "/events" |
193 | |
194 | - //GET https://www.googleapis.com/calendar/v3/calendars/primary/events?showDeleted=true&singleEvents=true&updatedMin=2016-04-06T10%3A00%3A00.00Z&fields=description%2Citems(description%2Cetag%2Csummary)&key={YOUR_API_KEY} |
195 | - query := baseUrl.Query() |
196 | + //GET https://www.googleapis.com/calendar/v3/calendars/<calendar>/events?showDeleted=true&singleEvents=true&updatedMin=2016-04-06T10%3A00%3A00.00Z&fields=description%2Citems(description%2Cetag%2Csummary)&key={YOUR_API_KEY} |
197 | + query := u.Query() |
198 | query.Add("showDeleted", "true") |
199 | query.Add("singleEvents", "true") |
200 | query.Add("fields", "description,items(summary,etag)") |
201 | |
202 | === modified file 'plugins/gcalendar/syncmonitor.go' |
203 | --- plugins/gcalendar/syncmonitor.go 2016-04-14 15:03:27 +0000 |
204 | +++ plugins/gcalendar/syncmonitor.go 2016-07-19 14:12:26 +0000 |
205 | @@ -55,8 +55,19 @@ |
206 | } |
207 | } |
208 | |
209 | -func (p *SyncMonitor) LastSyncDate(accountId uint, serviceName string) (lastSyncDate string, err error) { |
210 | - message, err := p.obj.Call(busInterface, "lastSuccessfulSyncDate", uint32(accountId), serviceName) |
211 | +func (p *SyncMonitor) ListCalendarsByAccount(accountId uint) (calendars map[string]string, err error) { |
212 | + message, err := p.obj.Call(busInterface, "listCalendarsByAccount", uint32(accountId)) |
213 | + if err != nil { |
214 | + var calendars map[string]string |
215 | + return calendars, err |
216 | + } else { |
217 | + err = message.Args(&calendars) |
218 | + return calendars, err |
219 | + } |
220 | +} |
221 | + |
222 | +func (p *SyncMonitor) LastSyncDate(accountId uint, sourceId string) (lastSyncDate string, err error) { |
223 | + message, err := p.obj.Call(busInterface, "lastSuccessfulSyncDate", uint32(accountId), sourceId) |
224 | if err != nil { |
225 | return "", err |
226 | } else { |
227 | @@ -66,7 +77,18 @@ |
228 | } |
229 | } |
230 | |
231 | -func (p *SyncMonitor) SyncAccount(accountId uint, serviceName string) (err error) { |
232 | - _, err = p.obj.Call(busInterface, "syncAccount", uint32(accountId), serviceName) |
233 | +func (p *SyncMonitor) SyncAccount(accountId uint, sources []string) (err error) { |
234 | + _, err = p.obj.Call(busInterface, "syncAccount", uint32(accountId), sources) |
235 | return err |
236 | } |
237 | + |
238 | +func (p *SyncMonitor) State() (state string, err error) { |
239 | + message, err := p.obj.Call(busInterface, "state") |
240 | + if err != nil { |
241 | + return "", err |
242 | + } else { |
243 | + err = message.Args(&state) |
244 | + return state, err |
245 | + } |
246 | +} |
247 | + |
PASSED: Continuous integration, rev:170 /jenkins. canonical. com/system- apps/job/ lp-account- polld-ci/ 1/ /jenkins. canonical. com/system- apps/job/ build/691 /jenkins. canonical. com/system- apps/job/ test-0- autopkgtest/ label=phone- armhf,release= vivid+overlay, testname= default/ 97 /jenkins. canonical. com/system- apps/job/ build-0- fetch/691 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= vivid+overlay/ 649 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= xenial+ overlay/ 649 /jenkins. canonical. com/system- apps/job/ build-1- sourcepkg/ release= yakkety/ 649 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 641/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= yakkety/ 641 /jenkins. canonical. com/system- apps/job/ build-2- binpkg/ arch=i386, release= yakkety/ 641/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/system- apps/job/ lp-account- polld-ci/ 1/rebuild
https:/