This is an automated email from the ASF dual-hosted git repository.

royteeuwen pushed a commit to branch feature/sling-cli-release-automation
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git

commit a868352f58f74d83cfdfee4a8aba3e3cf8fc7208
Author: Roy Teeuwen <[email protected]>
AuthorDate: Sat May 30 08:09:57 2026 +0200

    release tally-votes: PMC-aware result email
    
    The [RESULT] email's closing paragraph now depends on whether the current 
user
    is a PMC member (auto-detected). A PMC member states they will copy the 
release
    to the dist directory themselves; a non-PMC release manager promotes to 
Maven
    Central and adds a standout "ACTION NEEDED" line asking a PMC member to 
perform
    the dist upload (which is PMC-only).
---
 .../sling/cli/impl/release/TallyVotesCommand.java  | 18 ++++++++
 src/main/resources/templates/tally-votes.email     |  3 +-
 .../cli/impl/release/TallyVotesCommandTest.java    | 49 +++++++++++++++++++++-
 3 files changed, 67 insertions(+), 3 deletions(-)

diff --git 
a/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java 
b/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
index 3daca17..a621168 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
@@ -139,6 +139,7 @@ public class TallyVotesCommand implements Command {
                         .replace("##DATE##", 
dateProvider.getCurrentDateForEmailHeader())
                         .replace("##RELEASE_NAME##", releaseFullName)
                         .replace("##BINDING_VOTERS##", String.join(", ", 
bindingVoters))
+                        .replace("##CLOSING_ACTION##", 
closingAction(releaseFullName, currentMember.isPMCMember()))
                         .replace(
                                 "##USER_NAME##",
                                 membersFinder.getCurrentMember().getName());
@@ -193,6 +194,23 @@ public class TallyVotesCommand implements Command {
         return CommandLine.ExitCode.OK;
     }
 
+    /**
+     * Builds the closing paragraph of the result email. PMC members copy the 
release to the dist
+     * directory themselves; non-PMC release managers can only promote to 
Maven Central and must ask
+     * a PMC member to handle the dist upload (which is restricted to PMC 
members). PMC membership is
+     * derived from the current user, so no flag is needed.
+     */
+    private String closingAction(String releaseFullName, boolean isPmcMember) {
+        if (isPmcMember) {
+            return "I will copy this release to the Sling dist directory and\n"
+                    + "promote the artifacts to the central Maven repository.";
+        }
+        return "I will promote the artifacts to the central Maven 
repository.\n\n"
+                + "As I am not a PMC member, I cannot copy the release to the 
dist directory myself.\n\n"
+                + "ACTION NEEDED: can a PMC member please copy " + 
releaseFullName
+                + " to the Sling dist directory 
(https://dist.apache.org/repos/dist/release/sling/)?";
+    }
+
     // TODO - better detection of '+1' votes
     private boolean isPositiveVote(Email e) {
         return cleanup(e.getBody()).contains("+1");
diff --git a/src/main/resources/templates/tally-votes.email 
b/src/main/resources/templates/tally-votes.email
index af68d64..2b08093 100644
--- a/src/main/resources/templates/tally-votes.email
+++ b/src/main/resources/templates/tally-votes.email
@@ -11,8 +11,7 @@ The vote has passed with the following result:
 +1 (binding): ##BINDING_VOTERS##
 +1 (non-binding): ##NON_BINDING_VOTERS##
 
-I will copy this release to the Sling dist directory and
-promote the artifacts to the central Maven repository.
+##CLOSING_ACTION##
 
 Regards,
 ##USER_NAME##
diff --git 
a/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java 
b/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
index dcd28a2..e9d1573 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
@@ -110,6 +110,48 @@ public class TallyVotesCommandTest {
                         + "John Doe\n"));
     }
 
+    @Test
+    public void testDryRunNonPmc() throws Exception {
+        // Daniel (a non-PMC committer) is the release manager running 
tally-votes; PMC status is
+        // auto-detected from the current user, so the result email asks a PMC 
member to do the dist
+        // upload.
+        Mailer mailer = mock(Mailer.class);
+        List<Email> thread = new ArrayList<>() {
+            {
+                add(mockEmail("[email protected]", "Daniel"));
+                add(mockEmail("[email protected]", "Alice"));
+                add(mockEmail("[email protected]", "Bob"));
+                add(mockEmail("[email protected]", "Charlie"));
+            }
+        };
+        prepareExecution(mailer, thread, "daniel");
+        Command command = createCommand(123, ExecutionMode.DRY_RUN);
+        assertEquals(CommandLine.ExitCode.OK, (int) command.call());
+        verifyNoInteractions(mailer);
+        assertTrue(logCapture.containsMessage(
+                "From: Daniel <[email protected]>\n" + "To: \"Sling Developers 
List\" <[email protected]>\n"
+                        + "Reply-To: \"Sling Developers List\" 
<[email protected]>\n"
+                        + "Date: Thu, 1 Jan 1970 01:00:00 +0100\n"
+                        + "Subject: [RESULT] [VOTE] Release Apache Sling CLI 
Test 1.0.0\n"
+                        + "\n"
+                        + "Hi,\n"
+                        + "\n"
+                        + "The vote has passed with the following result:\n"
+                        + "\n"
+                        + "+1 (binding): Alice, Bob, Charlie\n"
+                        + "+1 (non-binding): none\n"
+                        + "\n"
+                        + "I will promote the artifacts to the central Maven 
repository.\n"
+                        + "\n"
+                        + "As I am not a PMC member, I cannot copy the release 
to the dist directory myself.\n"
+                        + "\n"
+                        + "ACTION NEEDED: can a PMC member please copy Apache 
Sling CLI Test 1.0.0 to the"
+                        + " Sling dist directory 
(https://dist.apache.org/repos/dist/release/sling/)?\n"
+                        + "\n"
+                        + "Regards,\n"
+                        + "Daniel\n"));
+    }
+
     @Test
     public void testDryRunNotEnoughBindingVotes() throws Exception {
         Mailer mailer = mock(Mailer.class);
@@ -184,8 +226,13 @@ public class TallyVotesCommandTest {
     }
 
     private void prepareExecution(Mailer mailer, List<Email> thread) throws 
IOException, IllegalAccessException {
+        prepareExecution(mailer, thread, "johndoe");
+    }
+
+    private void prepareExecution(Mailer mailer, List<Email> thread, String 
currentUsername)
+            throws IOException, IllegalAccessException {
         CredentialsService credentialsService = mock(CredentialsService.class);
-        when(credentialsService.getAsfCredentials()).thenReturn(new 
Credentials("johndoe", "secret"));
+        when(credentialsService.getAsfCredentials()).thenReturn(new 
Credentials(currentUsername, "secret"));
 
         MembersFinder membersFinder = spy(new MembersFinder());
         Set<Member> members = new HashSet<>() {

Reply via email to