actions / setup-java

Set up your GitHub Actions workflow with a specific version of Java
MIT License
1.51k stars 729 forks source link

Action is not compatible with latest versions of maven-gpg-plugin #668

Open loesak opened 1 month ago

loesak commented 1 month ago

Description: This action is no longer fully compatible with later versions of the maven-gpg-plugin.

The action takes the variable gpg-passphrase which is expected to be the environment variable that holds the value of the secret key, and sets the maven variable gpg.passphrase in the settings.xml file to the value of the environment variable. The original expectation here is that the passphrase will be provided via pinentry during signing. In later versions of the maven-pgp-plugin, pinentry was disabled and the plugin variable passphrase was deprecated.

It is now expected that the passphrase is taken from an environment variable directly by the plugin. The plugin expects the environment variable name to be either the default of MAVEN_GPG_PASSPHRASE or provided via the configuration property of passphraseEnvName.

If you used this action with the maven-gpg-plugin version 1.6 and set the value for action variable gpg-passphrase to anything other than the default, it would work. However, after upgrading to a later version (e.g. 3.2.4) the build would fail.

If the value for the action variable gpg-passphrase was set to the expected default of MAVEN_GPG_PASSPHRASE (as is shown in GitHub example documentation), then the build would continue to work.

Another workaround if wanting to use an environment variable name other than default is to omit the action variable gpg-passphrase from the action configuration and specify the alternative variable name in the maven plugin configuration using the configuration variable name passphraseEnvName

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>3.2.4</version>
    <configuration>
        <bestPractices>true</bestPractices>
        <passphraseEnvName>MY_GPG_PASSPHRASE</passphraseEnvName>
    </configuration>
    <executions>
        <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
                <goal>sign</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Also note that the documentation for advance usage related to GPG signing contains documentation about setting pinentry to loopback. This also no longer working in later versions of the maven-gpg-plugin.

Task version: All

Platform:

Runner type:

Repro steps: Specify a different environment variable name for gpg-passphrase than MAVEN_GPG_PASSPHRASE

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
    - name: Set up JDK 11
      uses: actions/setup-java@v4
      with:
        distribution: 'temurin'
        java-version: '11'
        server-id: maven
        server-username: MAVEN_USERNAME
        server-password: MAVEN_CENTRAL_TOKEN
        gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
        gpg-passphrase: MY_GPG_PASSPHRASE

    - name: Publish to Apache Maven Central
      run: mvn deploy
      env:
        MAVEN_USERNAME: maven_username123
        MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
        MY_GPG_PASSPHRASE: ${{ secrets.MY_GPG_PASSPHRASE }}

And use version 3.2.4 of the maven-gpg-plugin as such:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>3.2.4</version>
    <executions>
        <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
                <goal>sign</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Expected behavior: Build runs successfully

Actual behavior: Build fails with error during signing.

priyagupta108 commented 1 month ago

Hi @loesak 👋, Thank you for reporting this! We will look into and come back to you with the details!

aparnajyothi-y commented 2 weeks ago

Hello @loesak, Thank you for creating this issue. We tried to reproduce it on Ubuntu and macOS environments, but were unable to do so. We used a different environment variable name for the GPG passphrase than MAVEN_GPG_PASSPHRASE with the maven-gpg-plugin version 3.2.4. The process was successful by setting pinentry to loopback without adding passphraseEnvName. Please find the screenshots for reference. It would be helpful if you could provide additional details like repro link from a public repository to check and assist, as we are unable to reproduce it on the Ubuntu runner.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>

<configuration>

<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>

</configuration>
</plugin>
name: Set up Apache Maven Central
      uses: actions/setup-java@v4
      with: # running setup-java again overwrites the settings.xml
        distribution: 'sapmachine'
        java-version: ${{ matrix.java-version }}
        server-id: central # Value of the distributionManagement/repository/id field of the pom.xml
        server-username: MAVEN_USERNAME # env variable for username in deploy
        server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
        gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} # Value of the GPG private key to import
        gpg-passphrase: MY_GPG_PASSPHRASE # env variable for GPG private key passphrase

    - name: Publish to Apache Maven Central
      run: mvn -P release --batch-mode deploy -DskipTests
      env:
        MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME}}
        MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN}}
        MY_GPG_PASSPHRASE: ${{ secrets.MY_GPG_PASSPHRASE }}
Screenshot 2024-08-30 at 6 48 43 PM
loesak commented 1 week ago

Okay. Give me a few days to create a proof of concept repo for this issue.

loesak commented 1 week ago

Okay. Here is a repository that demonstrates the issue. It also demonstrates the workarounds. It also demonstrates adding pinentry loopback to maven configuration no longer relevant.

https://github.com/loesak/github-setupjava-issue-668-poc

You state you couldn't reproduce using 3.2.4 but the maven snippet you provided is referencing version 3.1.0. Maybe that's why you cannot reproduce?.

Here is the documentation from that repo's readme.


github-setupjava-issue-668-poc

https://github.com/actions/setup-java/issues/668

This repository is a demonstration of the issue identified in the above linked github issue.

Scenarios

Branch 'main'

The code in this branch demonstrates a working build. It is using the workaround identified where using the maven gpg plugin default environment variable name of MAVEN_GPG_PASSPHRASE to hold the value of the GPG passphrase in order to sign the build artifacts.

Also note that the debug output for the maven gpg plugin already includes the argument --pinentry-mode loopback in the gpg signing command despite the loopback configuration being missing in the maven gpg plugin, counter to github documentation. See line 2125 of the build output.

You can view the contents of this branch here: https://github.com/loesak/github-setupjava-issue-668-poc

Here is the associated successful build: https://github.com/loesak/github-setupjava-issue-668-poc/actions/runs/10706333315

Branch 'workaround-specify-non-default-environment-variable-name'

The code in this branch demonstrates a working build. It is using the workaround identified where an environment variable name for the GPG passphrase that is not the maven gpg plugin default environment variable name is desired. The environment variable name is specified in both the GitHub workflow file and in the pom.xml file.

Also note that the debug output for the maven gpg plugin already includes the argument --pinentry-mode loopback in the gpg signing command despite the loopback configuration being missing in the maven gpg plugin, counter to github documentation. See line 2125 of the build output.

You can compare the changes to the main branch in this pull request: https://github.com/loesak/github-setupjava-issue-668-poc/pull/1

And here is the associated successful build: https://github.com/loesak/github-setupjava-issue-668-poc/actions/runs/10705963444

Branch 'broken-use-alternative-environment-variable-name-no-loopback'

The code in this branch demonstrates the initial issue that worked with earlier versions of the maven gpg plugin. Here an alternative environment variable name is provided for the gpg passphrase without specifying the environment variable name in the maven gpg plugin configuration. This also does not include the pinentry loopback configuration. The build fails because the maven gpg plugin cannot find the gpg passphrase to use for artifact signing.

Also note that the debug output for the maven gpg plugin already includes the argument --pinentry-mode error in the gpg signing command. See line 2058 of the build output.

You can compare the changes to the main branch in this pull request: https://github.com/loesak/github-setupjava-issue-668-poc/pull/2

And here is the associated successful build: https://github.com/loesak/github-setupjava-issue-668-poc/actions/runs/10706079670

Branch 'broken-use-alternative-environment-variable-name-yes-loopback'

The code in this branch is the same as the broken-use-alternative-environment-variable-name-no-loopback branch but adds the pinentry loopback configuration as documented by GitHub. The result is the same however in that the build fails to sign the artifacts because it cannot find the gpg passphrase.

Also note that the debug output for the maven gpg plugin now includes two arguments for --pinentry-mode (--pinentry-mode loopback and --pinentry-mode error). I believe the command does not support multiple values and received the second flag --pinentry-mode error as the set value, thus ignoring the pinentry configuration provided in the maven gpg plugin. See line 2063 of the build output.

You can compare the changes to the main branch in this pull request: https://github.com/loesak/github-setupjava-issue-668-poc/pull/3

And here is the associated successful build: https://github.com/loesak/github-setupjava-issue-668-poc/actions/runs/10706247055

aparnajyothi-y commented 1 week ago

Hello @loesak, Thank you for pointing that out.We have used version 3.2.4 for the maven-gpg-plugin along with the --pinentry-mode loopback setup, which has made the run successful.

For the maven-gpg-plugin version from 2.1 and later(e.g. 3.2.4), The --pinentry-mode loopback argument is indeed included in the GPG signing command for the default environment variable MAVEN_GPG_PASSPHRASE and it ensures that the GPG signing process does not prompt for passphrase input. Instead, it reads the passphrase from the environment variable or configuration file. For the default environment variable MAVEN_GPG_PASSPHRASE, the --pinentry-mode loopback setting works as expected without any additional configuration.

However, if you are using a non-default environment variable for the GPG passphrase, you will need to explicitly add the --pinentry-mode loopback argument in your pom.xml configuration as mentioned.

org.apache.maven.plugins maven-gpg-plugin 1.6 sign --pinentry-mode loopback gpg.passphrase

By explicitly specifying the --pinentry-mode loopback argument in your pom.xml configuration, you ensure that the GPG signing process correctly reads the passphrase from the specified environment variable, whether it is the default MAVEN_GPG_PASSPHRASE or a custom environment variable.

We are working to update the documentation to provide clarity for both the default MAVEN_GPG_PASSPHRASE and custom environment variables. We will update the PR details with the documentation update.

loesak commented 6 days ago

However, if you are using a non-default environment variable for the GPG passphrase, you will need to explicitly add the --pinentry-mode loopback argument in your pom.xml configuration as mentioned.

This isn't true, at least with latest versions of the maven plugin. As I demonstrate in my branch "workaround-specify-non-default-environment-variable-name", no loopback configuration in the pom.xml is provided and signing works.

loesak commented 6 days ago

However, if you are using a non-default environment variable for the GPG passphrase, you will need to explicitly add the --pinentry-mode loopback argument in your pom.xml configuration as mentioned.

This isn't true, at least with latest versions of the maven plugin. As I demonstrate in my branch "workaround-specify-non-default-environment-variable-name", no loopback configuration in the pom.xml is provided and signing works.