| // Copyright 2021 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| |
| import 'package:cocoon_service/src/service/datastore.dart'; |
| import 'package:gcloud/db.dart'; |
| import 'package:github/hooks.dart'; |
| |
| import '../model/appengine/branch.dart'; |
| import '../request_handling/exceptions.dart'; |
| import '../service/logging.dart'; |
| |
| class RetryException implements Exception {} |
| |
| /// A class to manage GitHub branches. |
| /// |
| /// Track branch activities such as branch creation, and helps manage release branches. |
| class BranchService { |
| BranchService(this.datastore, {this.rawRequest}); |
| |
| DatastoreService datastore; |
| String? rawRequest; |
| |
| /// Parse a create github webhook event, and add it to datastore. |
| Future<void> handleCreateRequest() async { |
| log.info('raw request passed in was $rawRequest'); |
| final CreateEvent? createEvent = await _getCreateRequestEvent(rawRequest!); |
| if (createEvent == null) { |
| log.info('create branch event was rejected because could not parse the json webhook request'); |
| throw const BadRequestException('Expected create request event.'); |
| } |
| log.info('the branch parsed from string request is ${createEvent.ref}'); |
| |
| final String? refType = createEvent.refType; |
| if (refType == 'tag') { |
| log.info('create branch event was rejected because it is a tag'); |
| return; |
| } |
| final String? branch = createEvent.ref; |
| final String repository = createEvent.repository!.slug().fullName; |
| final int lastActivity = createEvent.repository!.pushedAt!.millisecondsSinceEpoch; |
| final bool forked = createEvent.repository!.isFork; |
| |
| if (forked) { |
| log.info('create branch event was rejected because the branch is a fork'); |
| return; |
| } |
| |
| final String id = '$repository/$branch'; |
| log.info('the id used to create branch key was $id'); |
| final Key<String> key = datastore.db.emptyKey.append<String>(Branch, id: id); |
| final Branch currentBranch = Branch(key: key, lastActivity: lastActivity); |
| try { |
| await datastore.lookupByValue<Branch>(currentBranch.key); |
| } on KeyNotFoundException { |
| log.info('create branch event was successful since the key is unique'); |
| await datastore.insert(<Branch>[currentBranch]); |
| } catch (e) { |
| log.severe('Unexpected exception was encountered while inserting branch into database: $e'); |
| } |
| } |
| |
| Future<CreateEvent?> _getCreateRequestEvent(String request) async { |
| try { |
| return CreateEvent.fromJson(json.decode(request) as Map<String, dynamic>); |
| } on FormatException { |
| return null; |
| } catch (e) { |
| log.severe('Unexpected exception was encountered while decoding json webhook msg for branch creation: $e'); |
| return null; |
| } |
| } |
| } |