maven-gpg-plugin failing with "Inappropriate ioctl for device" when running under Jenkins

3.2k Views Asked by At

When Jenkins triggers maven-gpg-plugin in a remote Linux shell it fails with gpg: signing failed: Inappropriate ioctl for device. This used to work until recently. I don't know what changed.

I found a lot of online references suggesting export GPG_TTY=$(tty) but this doesn't work for ssh connections as tty is null. Any ideas?

4

There are 4 best solutions below

8
On BEST ANSWER

I found an excellent explanation over at https://myshittycode.com/2017/08/07/maven-gpg-plugin-prevent-signing-prompt-or-gpg-signing-failed-no-such-file-or-directory-error/

I will re-post the gist of the post in case the page goes down:

If you 1) initially had it working in the past, and 2) have tried all sorts of solutions from the web, and still couldn’t get it working, chances are you have unconsciously upgraded GPG version from 2.0 to 2.1.

Sounds about right...

To fix this, GPG 2.1 requires --pinentry-mode to be set to loopback in order to pick up gpg.passphrase value defined in Maven settings.xml.

So, update Maven GPG Plugin configuration in pom.xml to the following:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>1.6</version>
    <executions>
        <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
                <goal>sign</goal>
            </goals>
            <configuration>
                <gpgArguments>
                    <arg>--pinentry-mode</arg>
                    <arg>loopback</arg>
                </gpgArguments>
            </configuration>
        </execution>
    </executions>
</plugin>
0
On

Upgrading to a newer maven-gpg-plugin version helped in my case. From 1.5 to 3.0.1.

Hopefully it will be at least a try for somebody

0
On

To build on Gili's answer:

Rather than modify every pom.xml to make Jenkins happy, you can add the following to ~/.gnupg/gpg.conf on Jenkins slaves with newer gpg:

pinentry-mode loopback

Puppet

You can also automate this. I'm using puppet to create gpg.conf files with this entry if gpg version is 2.1 or higher:

Template

<% if scope.lookupvar("gpg_version").to_f >= 2.1 %>
pinentry-mode loopback
<% end %>

Fact

Facter.add("gpg_version") do
  setcode do

    result = ''
    begin
      first_line = `gpg --version`.split("\n")[0]
      match = first_line.match /.* ([0-9\.]*)$/
      result = match[1]
    rescue

    end
    result
  end
end

4
On

This worked for me:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>3.0.1</version>
<executions>
    <execution>
        <id>sign-artifacts</id>
        <phase>verify</phase>
        <goals>
            <goal>sign</goal>
        </goals>
    </execution>
</executions>
<configuration>
    <gpgArguments>
        <argument>--pinentry-mode</argument>
        <argument>loopback</argument>
    </gpgArguments>
</configuration>
</plugin>