1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.openjdk.skara.bots.notify; 24 25 import org.openjdk.skara.bot.*; 26 import org.openjdk.skara.email.EmailAddress; 27 import org.openjdk.skara.network.URIBuilder; 28 import org.openjdk.skara.json.JSONObject; 29 import org.openjdk.skara.mailinglist.MailingListServerFactory; 30 import org.openjdk.skara.storage.StorageBuilder; 31 import org.openjdk.skara.vcs.Tag; 32 33 import java.nio.file.Path; 34 import java.time.Duration; 35 import java.util.*; 36 import java.util.logging.Logger; 37 import java.util.regex.Pattern; 38 import java.util.stream.Collectors; 39 40 public class JNotifyBotFactory implements BotFactory { 41 private final Logger log = Logger.getLogger("org.openjdk.skara.bots");; 42 43 @Override 44 public String name() { 45 return "notify"; 46 } 47 48 @Override 49 public List<Bot> create(BotConfiguration configuration) { 50 var ret = new ArrayList<Bot>(); 51 var specific = configuration.specific(); 52 53 var database = specific.get("database").asObject(); 54 var databaseRepo = configuration.repository(database.get("repository").asString()); 55 var databaseRef = configuration.repositoryRef(database.get("repository").asString()); 56 var databaseName = database.get("name").asString(); 57 var databaseEmail = database.get("email").asString(); 58 59 for (var repo : specific.get("repositories").fields()) { 60 var repoName = repo.name(); 61 var branchPattern = Pattern.compile("^master$"); 62 if (repo.value().contains("branches")) { 63 branchPattern = Pattern.compile(repo.value().get("branches").asString()); 64 } 65 66 var includeBranchNames = false; 67 if (repo.value().contains("branchnames")) { 68 includeBranchNames = repo.value().get("branchnames").asBoolean(); 69 } 70 71 var updaters = new ArrayList<UpdateConsumer>(); 72 if (repo.value().contains("json")) { 73 var folder = repo.value().get("folder").asString(); 74 var build = repo.value().get("build").asString(); 75 var version = repo.value().get("version").asString(); 76 updaters.add(new JsonUpdater(Path.of(folder), version, build)); 77 } 78 if (repo.value().contains("mailinglists")) { 79 var email = specific.get("email").asObject(); 80 var smtp = email.get("smtp").asString(); 81 var sender = EmailAddress.parse(email.get("sender").asString()); 82 var archive = URIBuilder.base(email.get("archive").asString()).build(); 83 var interval = email.contains("interval") ? Duration.parse(email.get("interval").asString()) : Duration.ofSeconds(1); 84 var listServer = MailingListServerFactory.createMailmanServer(archive, smtp, interval); 85 86 for (var mailinglist : repo.value().get("mailinglists").asArray()) { 87 var recipient = mailinglist.get("recipient").asString(); 88 var recipientAddress = EmailAddress.parse(recipient); 89 90 var mode = MailingListUpdater.Mode.ALL; 91 if (mailinglist.contains("mode")) { 92 switch (mailinglist.get("mode").asString()) { 93 case "pr": 94 mode = MailingListUpdater.Mode.PR; 95 break; 96 case "pr-only": 97 mode = MailingListUpdater.Mode.PR_ONLY; 98 break; 99 default: 100 throw new RuntimeException("Unknown mode"); 101 } 102 } 103 104 Map<String, String> headers = mailinglist.contains("headers") ? 105 mailinglist.get("headers").fields().stream() 106 .collect(Collectors.toMap(JSONObject.Field::name, field -> field.value().asString())) : 107 Map.of(); 108 var author = mailinglist.contains("author") ? EmailAddress.parse(mailinglist.get("author").asString()) : null; 109 var allowedDomains = author == null ? Pattern.compile(mailinglist.get("domains").asString()) : null; 110 updaters.add(new MailingListUpdater(listServer.getList(recipient), recipientAddress, sender, author, 111 includeBranchNames, mode, headers, allowedDomains)); 112 } 113 } 114 if (repo.value().contains("issues")) { 115 var issueProject = configuration.issueProject(repo.value().get("issues").asString()); 116 updaters.add(new IssueUpdater(issueProject)); 117 } 118 119 if (updaters.isEmpty()) { 120 log.warning("No consumers configured for notify bot repository: " + repoName); 121 continue; 122 } 123 124 var baseName = repo.value().contains("basename") ? repo.value().get("basename").asString() : configuration.repositoryName(repoName); 125 126 var tagStorageBuilder = new StorageBuilder<Tag>(baseName + ".tags.txt") 127 .remoteRepository(databaseRepo, databaseRef, databaseName, databaseEmail, "Added tag for " + repoName); 128 var branchStorageBuilder = new StorageBuilder<ResolvedBranch>(baseName + ".branches.txt") 129 .remoteRepository(databaseRepo, databaseRef, databaseName, databaseEmail, "Added branch hash for " + repoName); 130 var bot = new JNotifyBot(configuration.repository(repoName), configuration.storageFolder(), branchPattern, tagStorageBuilder, branchStorageBuilder, updaters); 131 ret.add(bot); 132 } 133 134 return ret; 135 } 136 }