New Upstream Release - golang-github-docker-docker-credential-helpers

Ready changes

Summary

Merged new upstream version: 0.7.0+ds1 (was: 0.6.4+ds1).

Resulting package

Built on 2022-12-14T16:26 (took 3m35s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases golang-docker-credential-helpersapt install -t fresh-releases golang-github-docker-docker-credential-helpers-dev

Diff

diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+/bin
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..c181b29
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,186 @@
+name: build
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+on:
+  workflow_dispatch:
+  push:
+    branches:
+      - 'master'
+    tags:
+      - 'v*'
+  pull_request:
+
+env:
+  DESTDIR: ./bin
+  GO_VERSION: 1.18.5
+
+jobs:
+  validate:
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        target:
+          - lint
+          - validate-vendor
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v3
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+      -
+        name: Run
+        run: |
+          make ${{ matrix.target }}
+
+  test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os:
+          - ubuntu-20.04
+          - macOS-11
+          - windows-2022
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v3
+      -
+        name: Set up Go
+        uses: actions/setup-go@v3
+        with:
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
+      -
+        name: Install deps
+        if: ${{ matrix.os == 'ubuntu-20.04' }}
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y dbus-x11 gnome-keyring libsecret-1-dev pass
+      -
+        name: GPG conf
+        if: ${{ matrix.os == 'ubuntu-20.04' }}
+        uses: actions/github-script@v6
+        id: gpg
+        with:
+          script: |
+            const fs = require('fs');
+            const gnupgfolder = `${require('os').homedir()}/.gnupg`;
+            if (!fs.existsSync(gnupgfolder)){
+              fs.mkdirSync(gnupgfolder);
+            }
+            fs.copyFile('.github/workflows/fixtures/gpg.conf', `${gnupgfolder}/gpg.conf`, (err) => {
+              if (err) throw err;
+            });
+            core.setOutput('key', fs.readFileSync('.github/workflows/fixtures/7D851EB72D73BDA0.key', {encoding: 'utf8'}));
+            core.setOutput('passphrase', fs.readFileSync('.github/workflows/fixtures/7D851EB72D73BDA0.pass', {encoding: 'utf8'}));
+      -
+        name: Import GPG key
+        if: ${{ matrix.os == 'ubuntu-20.04' }}
+        uses: crazy-max/ghaction-import-gpg@v5
+        with:
+          gpg_private_key: ${{ steps.gpg.outputs.key }}
+          passphrase: ${{ steps.gpg.outputs.passphrase }}
+      -
+        name: Test
+        run: |
+          if [ "${{ matrix.os }}" = "ubuntu-20.04" ]; then
+            echo -e "trust\n5\ny" | gpg --batch --no-tty --command-fd 0 --edit-key 7D851EB72D73BDA0
+            pass init 7D851EB72D73BDA0
+          fi
+          go test -short -v -coverprofile=./coverage.txt -covermode=atomic ./...
+          go tool cover -func=./coverage.txt
+        shell: bash
+      -
+        name: Upload coverage
+        uses: codecov/codecov-action@v3
+        with:
+          file: ./coverage.txt
+
+  test-sandboxed:
+    runs-on: ubuntu-20.04
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v3
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+      -
+        name: Test
+        uses: docker/bake-action@v2
+        with:
+          targets: test
+          set: |
+            *.cache-from=type=gha,scope=test
+            *.cache-to=type=gha,scope=test,mode=max
+      -
+        name: Upload coverage
+        uses: codecov/codecov-action@v3
+        with:
+          file: ${{ env.DESTDIR }}//coverage.txt
+
+  build:
+    runs-on: ubuntu-20.04
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      -
+        name: Set up QEMU
+        uses: docker/setup-qemu-action@v2
+      -
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v2
+      -
+        name: Build
+        run: |
+          make release
+        env:
+          CACHE_FROM: type=gha,scope=build
+          CACHE_TO: type=gha,scope=build,mode=max
+      -
+        name: List artifacts
+        run: |
+          tree -nh ${{ env.DESTDIR }}
+      -
+        name: Check artifacts
+        run: |
+          find ${{ env.DESTDIR }} -type f -exec file -e ascii -e text -- {} +
+      -
+        name: Upload artifacts
+        uses: actions/upload-artifact@v3
+        with:
+          name: docker-credential-helpers
+          path: ${{ env.DESTDIR }}/*
+          if-no-files-found: error
+      -
+        name: GitHub Release
+        if: startsWith(github.ref, 'refs/tags/v')
+        uses: softprops/action-gh-release@1e07f4398721186383de40550babbdf2b84acfc5
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        with:
+          draft: true
+          files: ${{ env.DESTDIR }}/*
+
+  build-deb:
+    runs-on: ubuntu-20.04
+    steps:
+      -
+        name: Checkout
+        uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      -
+        name: Build
+        run: |
+          make deb
diff --git a/.github/workflows/fixtures/7D851EB72D73BDA0.key b/.github/workflows/fixtures/7D851EB72D73BDA0.key
new file mode 100644
index 0000000..6817273
--- /dev/null
+++ b/.github/workflows/fixtures/7D851EB72D73BDA0.key
@@ -0,0 +1,106 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lQdGBF6tzaABEACjFbX7PFEG6vDPN2MPyxYW7/3o/sonORj4HXUFjFxxJxktJ3x3
+N1ayHPJ1lqIeoiY7jVbq0ZdEVGkd3YsKG9ZMdZkzGzY6PQPC/+M8OnzOiOPwUdWc
++Tdhh115LvVz0MMKYiab6Sn9cgxj9On3LCQKpjvMDpPo9Ttf6v2GQIw8h2ACvdzQ
+71LtIELS/I+dLbfZiwpUu2fhQT13EJkEnYMOYwM5jNUd66P9itUc7MrOWjkicrKP
+oF1dQaCM+tuKuxvD8WLdiwU5x60NoGkJHHUehKQXl2dVzjpqEqHKEBJt9tfJ9lpE
+YIisgwB8o3pes0fgCehjW2zI95/o9+ayJ6nl4g5+mSvWRXEu66h71nwM0Yuvquk8
+3me7qhYfDrDdCwcxS5BS1hwakTgUQLD99FZjbx1j8sq96I65O0GRdyU2PR8KIjwu
+JrkTH4ZlKxK3FQghUhFoA5GkiDb+eClmRMSni5qg+81T4XChmUkEprA3eWCHL+Ma
+xRNNxLS+r6hH9HG5JBxpV3iaTI9HHpnQKhEeaLXqsUTDZliN9hP7Ywo8bpUB8j2d
+oWYwDV4dPyMKr6Fb8RDCh2q5gJGbVp8w/NmmBTeL+IP2fFggJkRfyumv3Ul7x66L
+tBFQ4rYo4JUUrGweSTneG6REIgxH66hIrNl6Vo/D1ZyknTe1dMOu/BTkkQARAQAB
+/gcDAqra8KO+h3bfyu90vxTL1ro4x/x9il7VBcWlIR4cBP7Imgxv+T4hwPIu8P1x
+lOlxLNWegFOV0idoTy1o3VLLBev/F+IlspX4A+2XEIddR6nZnKFi0Lv2L4TKgE9E
+VJJTszmviDIRLMLN9dWzDfA8hj5tR5Inot92CHRF414AS22JHvlhbFSLQnjqsN+C
+n1cQpNOJhkxsSfZsxjnFa/70y/u8v0o8mzyLZmk9HpzRHGzoz8IfpLp8OTqBR9u6
+zzoKLy16zZO55OKbj7h8uVZvDUq9l8iDICpqWMdZqBJIl56MBexYKgYxh3YO/8v2
+oXli+8Xuaq5QLiCN3yT7IbKoYzplnFfaJwFiMh7R1iPLXaYAZ0qdRijlbtseTK1m
+oHNkwUbxVzjkh4LfE8UpmMwZn5ZjWni3230SoiXuKy0OHkGvwGvWWAL1mEuoYuUI
+mFMcH5MnixP8oQYZKDj2IR/yEeOpdU6B/tr3Tk1NidLf7pUMqG7Ff1NU6dAUeBpa
+9xahITMjHvrhgMISY4IYZep5cEnVw8lQTpUJtW/ePMzrFhu3sA7oNdj9joW/VMfz
+H7MHwwavtICsYqoqV3lnjX4EC9dW6o8PTUg2u956dmtK7KAyUK/+w2aLNGT28ChN
+jhRYHvHzB9Kw5asqI/lTM49eqslBqYQMTTjdBphkYuSZQzNMf291j/ZmoLhD1A1a
+S8tUnNygKV4D1cJYgSXfzhFoU8ib/0SPo+KqQ+CzGS+wxXg6WNBA6wepTjpnVVx3
+4JADP8IJcDC3P0iwAreWjSy15F1cvemFFB0SLNUkyZGzsxtKzbM1+8khl68+eazC
+LzRj0rxfIF5znWjX1QFhKxCk6eF0IWDY0+b3DBkmChME9YDXJ3TthcqA7JgcX4JI
+M4/wdqhgerJYOmj+i2Q0M+Bu02icOJYMwTMMsDVl7XGHkaCuRgZ54eZAUH7JFwUm
+1Ct3tcaqiTMmz0ngHVqBTauzgqKDvzwdVqdfg05H364nJMay/3omR6GayIb5CwSo
+xdNVwG3myPPradT9MP09mDr4ys2zcnQmCkvTVBF6cMZ1Eh6PQQ8CyQWv0zkaBnqj
+JrM1hRpgW4ZlRosSIjCaaJjolN5QDcXBM9TbW9ww+ZYstazN2bV1ZQ7BEjlHQPa1
+BhzMsvqkbETHsIpDNF52gZKn3Q9eIX05BeadzpHUb5/XOheIHVIdhSaTlgl/qQW5
+hQgPGSzSV6KhXEY7aevTdvOgq++WiELkjfz2f2lQFesTjFoQWEvxVDUmLxHtEhaN
+DOuh4H3mX5Opn3pLQmqWVhJTbFdx+g5qQd0NCW4mDaTFWTRLFLZQsSJxDSeg9xrY
+gmaii8NhMZRwquADW+6iU6KfraBhngi7HRz4TfqPr9ma/KUY464cqim1fnwXejyx
+jsb5YHR9R66i+F6P/ysF5w+QuVdDt1fnf9GLay0r6qxpA8ft2vGPcDs4806Huj+7
+Aq5VeJaNkCuh3GR3xVnCFAz/7AtkO6xKuZm8B3q904UuMdSmkhWbaobIuF/B2B6S
+eawIXQHEOplK3ic26d8Ckf4gbjeORfELcMAEi5nGXpTThCdmxQApCLxAYYnTfQT1
+xhlDwT9xPEabo98mIwJJsAU5VsTDYW+qfo4qIx8gYoSKc9Xu3yVh3n+9k43Gcm5V
+9lvK1slijf+TzODZt/jsmkF8mPjXyP5KOI+xQp/m4PxW3pp57YrYj/Rnwga+8DKX
+jMsW7mLAAZ/e+PY6z/s3x1Krfk+Bb5Ph4mI0zjw5weQdtyEToRgveda0GEpvZSBU
+ZXN0ZXIgPGpvZUBmb28uYmFyPokCNgQQAQgAIAUCXq3NoAYLCQcIAwIEFQgKAgQW
+AgEAAhkBAhsDAh4BAAoJEH2FHrctc72gxtQP/AulaClIcn/kDt43mhYnyLglPfbo
+AqPlU26chXolBg0Wo0frFY3aIs5SrcWEf8aR4XLwCFGyi3vya0CUxjghN5tZBYqo
+vswbT00zP3ohxxlJFCRRR9bc7OZXCgTddtfVf6EKrUAzIkbWyAhaJnwJy/1UGpSw
+SEO/KpastrVKf3sv1wqOeFQ4DFyjaNda+xv3dVWS8db7KogqJiPFZXrQK3FKVIxS
+fxRSmKaYN7//d+xwVAEY++RrnL/o8B2kV6N68cCpQWJELyYnJzis9LBcWd/3wiYh
+efTyY+ePKUjcB+kEZnyJfLc7C2hll2e7UJ0fxv+k8vHReRhrNWmGRXsjNRxiw3U0
+hfvxD/C8nyqAbeTHp4XDX78Tc3XCysAqIYboIL+RyewDMjjLj5vzUYAdUdtyNaD7
+C6M2R6pN1GAt52CJmC/Z6F7W7GFGoYOdEkVdMQDsjCwScyEUNlGj9Zagw5M2EgSe
+6gaHgMgTzsMzCc4W6WV5RcS55cfDNOXtxPsMJTt4FmXrjl11prBzpMfpU5a9zxDZ
+oi54ZZ8VPE6jsT4Lzw3sni3c83wm28ArM20AzZ1vh7fk3Sfd0u4Yaz7s9JlEm5+D
+34tEyli28+QjCQc18EfQUiJqiYEJRxJXJ3esvMHfYi45pV/Eh5DgRW1305fUJV/6
++rGpg0NejsHoZdZPnQdGBF6tzaABEAC4mVXTkVk6Kdfa4r5zlzsoIrR27laUlMkb
+OBMt+aokqS+BEbmTnMg6xIAmcUT5uvGAc8S/WhrPoYfc15fTUyHIz8ZbDoAg0LO6
+0Io4VkAvNJNEnsSV9VdLBh/XYlc4K49JqKyWTL4/FJFAGbsmHY3b+QU90AS6FYRv
+KeBAoiyebrjx0vmzb8E8h3xthVLN+AfMlR1ickY62zvnpkbncSMY/skur1D2KfbF
+3sFprty2pEtjFcyB5+18l2IyyHGOlEUw1PZdOAV4/Myh1EZRgYBPs80lYTJALCVF
+IdOakH33WJCImtNZB0AbDTABG+JtMjQGscOa0qzf1Y/7tlhgCrynBBdaIJTx95TD
+21BUHcHOu5yTIS6Ulysxfkv611+BiOKHgdq7DVGP78VuzA7bCjlP1+vHqIt3cnIa
+t2tEyuZ/XF4uc3/i4g0uP9r7AmtET7Z6SKECWjpVv+UEgLx5Cv+ql+LSKYQMvU9a
+i3B1F9fatn3FSLVYrL4aRxu4TSw9POb0/lgDNmN3lGQOsjGCZPibkHjgPEVxKuiq
+9Oi38/VTQ0ZKAmHwBTq1WTZIrPrCW0/YMQ6yIJZulwQ9Yx1cgzYzEfg04fPXlXMi
+vkvNpKbYIICzqj0/DVztz9wgpW6mnd0A2VX2dqbMM0fJUCHA6pj8AvXY4R+9Q4rj
+eWRK9ycInQARAQAB/gcDApjt7biRO0PEyrrAiUwDMsJL4/CVMu11qUWEPjKe2Grh
+ZTW3N+m3neKPRULu+LUtndUcEdVWUCoDzAJ7MwihZtV5vKST/5Scd2inonOaJqoA
+nS3wnEMN/Sc93HAZiZnFx3NKjQVNCwbuEs45mXkkcjLm2iadrTL8fL4acsu5IsvD
+LbDwVOPeNnHKl6Hr20e39fK0FuJEyH49JM6U3B1/8385sJB8+E24+hvSF81aMddh
+Ne4Bc3ZYiYaKxe1quPNKC0CQhAZiT7LsMfkInXr0hY1I+kISNXEJ1dPYOEWiv0Ze
+jD5Pupn34okKNEeBCx+dK8BmUCi6Jgs7McUA7hN0D/YUS++5fuR55UQq2j8Ui0tS
+P8GDr86upH3PgEL0STh9fYfJ7TesxurwonWjlmmT62Myl4Pr+RmpS6PXOnhtcADm
+eGLpzhTveFj4JBLMpyYHgBTqcs12zfprATOpsI/89kmQoGCZpG6+AbfSHqNNPdy2
+eqUCBhOZlIIda1z/cexmU3f/gBqyflFf8fkvmlO4AvI8aMH3OpgHdWnzh+AB51xj
+kmdD/oWel9v7Dz4HoZUfwFaLZ0fE3P9voD8e+sCwqQwVqRY4L/BOYPD5noVOKgOj
+ABNKu5uKrobj6rFUi6DTUCjFGcmoF1Sc06xFNaagUNggRbmlC/dz22RWdDUYv5ra
+N6TxIDkGC0cK6ujyK0nes3DN0aHjgwWuMXDYkN3UckiebI4Cv/eF9jvUKOSiIcy1
+RtxdazZS4dYg2LBMeJKVkPi5elsNyw2812nEY3du/nEkQYXfYgWOF27OR+g4Y9Yw
+1BiqJ1TTjbQnd/khOCrrbzDH1mw00+1XVsT6wjObuYqqxPPS87UrqmMf6OdoYfPm
+zEOnNLBnsJ5VQM3A3pcT40RfdBrZRO8LjGhzKTreyq3C+jz0RLa5HNE8GgOhGyck
+ME4h+RhXlE8KGM+tTo6PA1NJSrEt+8kZzxjP4rIEn0aVthCkNXK12inuXtnHm0ao
+iLUlQOsfPFEnzl0TUPd7+z7j/wB+XiKU/AyEUuB0mvdxdKtqXvajahOyhLjzHQhz
+ZnNlgANGtiqcSoJmkJ8yAvhrtQX51fQLftxbArRW1RYk/5l+Gy3azR+gUC17M6JN
+jrUYxn0zlAxDGFH7gACHUONwVekcuEffHzgu2lk7MyO1Y+lPnwabqjG0eWWHuU00
+hskJlXyhj7DeR12bwjYkyyjG62GvOH02g3OMvUgNGH+K321Dz539csCh/xwtg7Wt
+U3YAphU7htQ1dPDfk1IRs7DQo2L+ZTE57vmL5m0l6fTataEWBPUXkygfQFUJOM6Q
+yY76UEZww1OSDujNeY171NSTzXCVkUeAdAMXgjaHXWLK2QUQUoXbYX/Kr7Vvt9Fu
+Jh6eGjjp7dSjQ9+DW8CAB8vxd93gsQQGWYjmGu8khkEmx6OdZhmSbDbe915LQTb9
+sPhk2s5/Szsvr5W2JJ2321JI6KXBJMZvPC5jEBWmRzOYkRd2vloft+CSMfXF+Zfd
+nYtc6R3dvb9vcjo+a9wFtfcoDsO0MaPSM+9GB25MamdatmGX6iLOy9Re1UABwUi/
+VhTWNkP5uzqx0sDwHEIa2rYOwxpIZDwwjM3oOASCW1DDBQ0BI9KNjfIeL3ubx2mS
+2x8hFU9qSK4umoDNbzOqGPSlkdbiPcNjF2ZcSN1qQZiYdwLL5dw6APNyBVjxTN1J
+gkCdJ/HwAY+r93Lbl5g8gz8d0vJEyfn//34sn9u+toSTw55GcG9Ks1kSKIeDNh0h
+MiPm3HmJAh8EGAEIAAkFAl6tzaACGwwACgkQfYUety1zvaBV9hAAgliX36pXJ59g
+3I9/4R68e/fGg0FMM6D+01yCeiKApOYRrJ0cYKn7ITDYmHhlGGpBAie90UsqX12h
+hdLP7LoQx7sjTyzQt6JmpA8krIwi2ON7FKBkdYb8IYx4mE/5vKnYT4/SFnwTmnZY
++m+NzK2U/qmhq8JyO8gozdAKJUcgz49IVv2Ij0tQ4qaPbyPwQxIDyKnT758nJhB1
+jTqo+oWtER8q3okzIlqcArqn5rDaNJx+DRYL4E/IddyHQAiUWUka8usIUqeW5reu
+zoPUE2CCfOJSGArkqHQQqMx0WEzjQTwAPaHrQbera4SbiV/o4CLCV/u5p1Qnig+Q
+iUsakmlD299t//125LIQEa5qzd9hRC7u1uJS7VdW8eGIEcZ0/XT/sr+z23z0kpZH
+D3dXPX0BwM4IP9xu31CNg10x0rKwjbxy8VaskFEelpqpu+gpAnxqMd1evpeUHcOd
+r5RgPgkNFfba9Nbxf7uEX+HOmsOM+kdtSmdGIvsBZjVnW31nnoDMp49jG4OynjrH
+cRuoM9sxdr6UDqb22CZ3/e0YN4UaZM3YDWMVaP/QBVgvIFcdByqNWezpd9T4ZUII
+MZlaV1uRnHg6B/zTzhIdMM80AXz6Uv6kw4S+Lt7HlbrnMT7uKLuvzH7cle0hcIUa
+PejgXO0uIRolYQ3sz2tMGhx1MfBqH64=
+=WbwB
+-----END PGP PRIVATE KEY BLOCK-----
\ No newline at end of file
diff --git a/.github/workflows/fixtures/7D851EB72D73BDA0.pass b/.github/workflows/fixtures/7D851EB72D73BDA0.pass
new file mode 100644
index 0000000..ba6352f
--- /dev/null
+++ b/.github/workflows/fixtures/7D851EB72D73BDA0.pass
@@ -0,0 +1 @@
+with stupid passphrase
\ No newline at end of file
diff --git a/ci/before_script_linux.sh b/.github/workflows/fixtures/generate.sh
similarity index 59%
rename from ci/before_script_linux.sh
rename to .github/workflows/fixtures/generate.sh
index 9fc0ea2..2f2af82 100644
--- a/ci/before_script_linux.sh
+++ b/.github/workflows/fixtures/generate.sh
@@ -1,9 +1,6 @@
+#!/usr/bin/env sh
 set -ex
 
-sh -e /etc/init.d/xvfb start
-sleep 3 # give xvfb some time to start
-
-# init key for pass
 gpg --batch --gen-key <<-EOF
 %echo Generating a standard key
 Key-Type: DSA
@@ -17,6 +14,3 @@ Expire-Date: 0
 %commit
 %echo done
 EOF
-
-key=$(gpg --no-auto-check-trustdb --list-secret-keys | grep ^sec | cut -d/ -f2 | cut -d" " -f1)
-pass init $key
diff --git a/.github/workflows/fixtures/gpg-agent.conf b/.github/workflows/fixtures/gpg-agent.conf
new file mode 100644
index 0000000..a56651c
--- /dev/null
+++ b/.github/workflows/fixtures/gpg-agent.conf
@@ -0,0 +1,3 @@
+default-cache-ttl 21600
+max-cache-ttl 31536000
+allow-preset-passphrase
\ No newline at end of file
diff --git a/.github/workflows/fixtures/gpg.conf b/.github/workflows/fixtures/gpg.conf
new file mode 100644
index 0000000..4418c05
--- /dev/null
+++ b/.github/workflows/fixtures/gpg.conf
@@ -0,0 +1,71 @@
+################################################################################
+# GnuPG Options
+
+# (OpenPGP-Configuration-Options)
+# Assume that command line arguments are given as UTF8 strings.
+utf8-strings
+
+# (OpenPGP-Protocol-Options)
+# Set the list of personal digest/cipher/compression preferences. This allows
+# the user to safely override the algorithm chosen by the recipient key
+# preferences, as GPG will only select an algorithm that is usable by all
+# recipients.
+personal-digest-preferences SHA512 SHA384 SHA256 SHA224
+personal-cipher-preferences AES256 AES192 AES CAST5 CAMELLIA192 BLOWFISH TWOFISH CAMELLIA128 3DES
+personal-compress-preferences ZLIB BZIP2 ZIP
+
+# Set the list of default preferences to string. This preference list is used
+# for new keys and becomes the default for "setpref" in the edit menu.
+default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
+
+# (OpenPGP-Esoteric-Options)
+# Use name as the message digest algorithm used when signing a key. Running the
+# program with the command --version yields a list of supported algorithms. Be
+# aware that if you choose an algorithm that GnuPG supports but other OpenPGP
+# implementations do not, then some users will not be able to use the key
+# signatures you make, or quite possibly your entire key.
+#
+# SHA-1 is the only algorithm specified for OpenPGP V4. By changing the
+# cert-digest-algo, the OpenPGP V4 specification is not met but with even
+# GnuPG 1.4.10 (release 2009) supporting SHA-2 algorithm, this should be safe.
+# Source: https://tools.ietf.org/html/rfc4880#section-12.2
+cert-digest-algo SHA512
+digest-algo SHA256
+
+# Selects how passphrases for symmetric encryption are mangled. 3 (the default)
+# iterates the whole process a number of times (see --s2k-count).
+s2k-mode 3
+
+# (OpenPGP-Protocol-Options)
+# Use name as the cipher algorithm for symmetric encryption with a passphrase
+# if --personal-cipher-preferences and --cipher-algo are not given. The
+# default is AES-128.
+s2k-cipher-algo AES256
+
+# (OpenPGP-Protocol-Options)
+# Use name as the digest algorithm used to mangle the passphrases for symmetric
+# encryption. The default is SHA-1.
+s2k-digest-algo SHA512
+
+# (OpenPGP-Protocol-Options)
+# Specify how many times the passphrases mangling for symmetric encryption is
+# repeated. This value may range between 1024 and 65011712 inclusive. The
+# default is inquired from gpg-agent. Note that not all values in the
+# 1024-65011712 range are legal and if an illegal value is selected, GnuPG will
+# round up to the nearest legal value. This option is only meaningful if
+# --s2k-mode is set to the default of 3.
+s2k-count 1015808
+
+################################################################################
+# GnuPG View Options
+
+# Select how to display key IDs. "long" is the more accurate (but less
+# convenient) 16-character key ID. Add an "0x" to include an "0x" at the
+# beginning of the key ID.
+keyid-format 0xlong
+
+# List all keys with their fingerprints. This is the same output as --list-keys
+# but with the additional output of a line with the fingerprint. If this
+# command is given twice, the fingerprints of all secondary keys are listed too.
+with-fingerprint
+with-fingerprint
diff --git a/.gitignore b/.gitignore
index c0f3701..5e56e04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1 @@
-bin
-release
+/bin
diff --git a/.golangci.yml b/.golangci.yml
new file mode 100644
index 0000000..930e66a
--- /dev/null
+++ b/.golangci.yml
@@ -0,0 +1,35 @@
+run:
+  timeout: 10m
+  modules-download-mode: vendor
+
+linters:
+  enable:
+    - gofmt
+    - govet
+    - deadcode
+    - depguard
+    - goimports
+    - ineffassign
+    - misspell
+    - unused
+    - varcheck
+    - revive
+    - staticcheck
+    - typecheck
+    - structcheck
+  disable-all: true
+
+linters-settings:
+  depguard:
+    list-type: blacklist
+    include-go-root: true
+    packages:
+      # The io/ioutil package has been deprecated.
+      # https://go.dev/doc/go1.16#ioutil
+      - io/ioutil
+
+issues:
+  exclude-rules:
+    - linters:
+        - revive
+      text: "stutters"
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 7bd675a..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-  # See appveyor.yml for windows build.
-  sudo: required
-  language: go
-  dist: trusty
-  osx_image: xcode10.1
-  os:
-    - linux
-    - osx
-  notifications:
-    email: false
-  go:
-    - 1.12.x
-  addons:
-    apt:
-      packages:
-        - libsecret-1-dev
-        - pass
-  before_script:
-    - make deps
-    - "export DISPLAY=:99.0"
-    - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh ci/before_script_linux.sh; fi
-    - make validate
-  script: make test
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index 2a9aeff..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,61 +0,0 @@
-# Changelog
-
-This changelog tracks the releases of docker-credential-helpers.
-This project includes different binaries per platform.
-The platform released is identified after the tag name.
-
-## v0.6.0 (Go client, Linux)
-
-- New credential helper on Linux using `pass`
-- New entry point for passing environment variables when calling a credential helper
-- Add a Makefile rule generating a Windows release binary
-
-### Note
-
-`pass` needs to be configured for `docker-credential-pass` to work properly.
-It must be initialized with a `gpg2` key ID. Make sure your GPG key exists is in `gpg2` keyring as `pass` uses `gpg2` instead of the regular `gpg`.
-
-## v0.5.2 (Mac OS X, Windows, Linux)
-
-- Add a `version` command to output the version
-- Fix storing URLs without scheme, and use `https://` by default
-
-## v0.5.1 (Go client, Mac OS X, Windows, Linux)
-
-- Redirect credential helpers' standard error to the caller's
-- Prevent invalid credentials and credentials queries
-
-## v0.5.0 (Mac OS X)
-
-- Add a label for Docker credentials and filter credentials lookup to filter keychain lookups
-
-## v0.4.2 (Mac OS X, Windows)
-
-- Fix osxkeychain list
-- macOS binary is now signed on release
-- Generate a `.exe` instead
-
-## v0.4.1 (Mac OS X)
-
-- Fixes to support older version of OSX (10.10, 10.11)
-
-## v0.4.0 (Go client, Mac OS X, Windows, Linux)
-
-- Full implementation for OSX ready
-- Fix some windows issues
-- Implement client.List, change list API
-- mac: delete credentials before adding them to avoid already exist error (fixes #37)
-
-## v0.3.0 (Go client)
-
-- Add Go client library to talk with the native programs.
-
-## v0.2.0 (Mac OS X, Windows, Linux)
-
-- Initial release of docker-credential-secretservice for Linux.
-- Use new secrets payload introduced in https://github.com/docker/docker/pull/20970.
-
-## v0.1.0 (Mac OS X, Windows)
-
-- Initial release of docker-credential-osxkeychain for Mac OS X.
-- Initial release of docker-credential-wincred for Microsoft Windows.
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0df7927
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,167 @@
+# syntax=docker/dockerfile:1
+
+ARG GO_VERSION=1.18.5
+ARG XX_VERSION=1.1.2
+ARG OSXCROSS_VERSION=11.3-r7-debian
+ARG GOLANGCI_LINT_VERSION=v1.47.3
+ARG DEBIAN_FRONTEND=noninteractive
+
+ARG PACKAGE=github.com/docker/docker-credential-helpers
+
+# xx is a helper for cross-compilation
+FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
+
+# osxcross contains the MacOSX cross toolchain for xx
+FROM crazymax/osxcross:${OSXCROSS_VERSION} AS osxcross
+
+FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-bullseye AS gobase
+COPY --from=xx / /
+ARG DEBIAN_FRONTEND
+RUN apt-get update && apt-get install -y --no-install-recommends clang dpkg-dev file git lld llvm make pkg-config rsync
+ENV GOFLAGS="-mod=vendor"
+ENV CGO_ENABLED="1"
+WORKDIR /src
+
+FROM gobase AS vendored
+RUN --mount=target=/context \
+    --mount=target=.,type=tmpfs  \
+    --mount=target=/go/pkg/mod,type=cache <<EOT
+  set -e
+  rsync -a /context/. .
+  go mod tidy
+  go mod vendor
+  mkdir /out
+  cp -r go.mod go.sum vendor /out
+EOT
+
+FROM scratch AS vendor-update
+COPY --from=vendored /out /
+
+FROM vendored AS vendor-validate
+RUN --mount=type=bind,target=.,rw <<EOT
+  set -e
+  rsync -a /context/. .
+  git add -A
+  rm -rf vendor
+  cp -rf /out/* .
+  if [ -n "$(git status --porcelain -- go.mod go.sum vendor)" ]; then
+    echo >&2 'ERROR: Vendor result differs. Please vendor your package with "make vendor"'
+    git status --porcelain -- go.mod go.sum vendor
+    exit 1
+  fi
+EOT
+
+FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION} AS golangci-lint
+FROM gobase AS lint
+ARG DEBIAN_FRONTEND
+RUN apt-get install -y binutils gcc libc6-dev libgcc-10-dev libsecret-1-dev pkg-config
+RUN --mount=type=bind,target=. \
+    --mount=type=cache,target=/root/.cache \
+    --mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
+    golangci-lint run ./...
+
+FROM gobase AS base
+ARG TARGETPLATFORM
+ARG DEBIAN_FRONTEND
+RUN xx-apt-get install -y binutils gcc libc6-dev libgcc-10-dev libsecret-1-dev pkg-config
+
+FROM base AS test
+ARG DEBIAN_FRONTEND
+RUN xx-apt-get install -y dbus-x11 gnome-keyring gpg-agent gpgconf libsecret-1-dev pass
+RUN --mount=type=bind,target=. \
+    --mount=type=cache,target=/root/.cache \
+    --mount=type=cache,target=/go/pkg/mod <<EOT
+  set -e
+  cp -r .github/workflows/fixtures /root/.gnupg
+  gpg-connect-agent "RELOADAGENT" /bye
+  gpg --import --batch --yes /root/.gnupg/7D851EB72D73BDA0.key
+  gpg --update-trustdb
+  echo '5\ny\n' | gpg --command-fd 0 --no-tty --edit-key 7D851EB72D73BDA0 trust
+  gpg-connect-agent "PRESET_PASSPHRASE 3E2D1142AA59E08E16B7E2C64BA6DDC773B1A627 -1 77697468207374757069642070617373706872617365" /bye
+  gpg-connect-agent "KEYINFO 3E2D1142AA59E08E16B7E2C64BA6DDC773B1A627" /bye
+  gpg-connect-agent "PRESET_PASSPHRASE BA83FC8947213477F28ADC019F6564A956456163 -1 77697468207374757069642070617373706872617365" /bye
+  gpg-connect-agent "KEYINFO BA83FC8947213477F28ADC019F6564A956456163" /bye
+  pass init 7D851EB72D73BDA0
+  gpg -k
+
+  mkdir /out
+  xx-go test -short -v -coverprofile=/out/coverage.txt -covermode=atomic ./...
+  xx-go tool cover -func=/out/coverage.txt
+EOT
+
+FROM scratch AS test-coverage
+COPY --from=test /out /
+
+FROM gobase AS version
+RUN --mount=target=. \
+    echo -n "$(./hack/git-meta version)" | tee /tmp/.version ; echo -n "$(./hack/git-meta revision)" | tee /tmp/.revision
+
+FROM base AS build-linux
+ARG PACKAGE
+RUN --mount=type=bind,target=. \
+    --mount=type=cache,target=/root/.cache \
+    --mount=type=cache,target=/go/pkg/mod \
+    --mount=type=bind,source=/tmp/.version,target=/tmp/.version,from=version \
+    --mount=type=bind,source=/tmp/.revision,target=/tmp/.revision,from=version <<EOT
+  set -ex
+  xx-go --wrap
+  make build-pass build-secretservice PACKAGE=$PACKAGE VERSION=$(cat /tmp/.version) REVISION=$(cat /tmp/.revision) DESTDIR=/out
+  xx-verify /out/docker-credential-pass
+  xx-verify /out/docker-credential-secretservice
+EOT
+
+FROM base AS build-darwin
+ARG PACKAGE
+RUN --mount=type=bind,target=. \
+    --mount=type=cache,target=/root/.cache \
+    --mount=type=cache,target=/go/pkg/mod \
+    --mount=type=bind,from=osxcross,src=/osxsdk,target=/xx-sdk \
+    --mount=type=bind,source=/tmp/.version,target=/tmp/.version,from=version \
+    --mount=type=bind,source=/tmp/.revision,target=/tmp/.revision,from=version <<EOT
+  set -ex
+  xx-go --wrap
+  go install std
+  make build-osxkeychain build-pass PACKAGE=$PACKAGE VERSION=$(cat /tmp/.version) REVISION=$(cat /tmp/.revision) DESTDIR=/out
+  xx-verify /out/docker-credential-osxkeychain
+  xx-verify /out/docker-credential-pass
+EOT
+
+FROM base AS build-windows
+ARG PACKAGE
+RUN --mount=type=bind,target=. \
+    --mount=type=cache,target=/root/.cache \
+    --mount=type=cache,target=/go/pkg/mod \
+    --mount=type=bind,source=/tmp/.version,target=/tmp/.version,from=version \
+    --mount=type=bind,source=/tmp/.revision,target=/tmp/.revision,from=version <<EOT
+  set -ex
+  xx-go --wrap
+  make build-wincred PACKAGE=$PACKAGE VERSION=$(cat /tmp/.version) REVISION=$(cat /tmp/.revision) DESTDIR=/out
+  mv /out/docker-credential-wincred /out/docker-credential-wincred.exe
+  xx-verify /out/docker-credential-wincred.exe
+EOT
+
+FROM build-$TARGETOS AS build
+
+FROM scratch AS binaries
+COPY --from=build /out /
+
+FROM --platform=$BUILDPLATFORM alpine AS releaser
+WORKDIR /work
+ARG TARGETOS
+ARG TARGETARCH
+ARG TARGETVARIANT
+RUN --mount=from=binaries \
+    --mount=type=bind,source=/tmp/.version,target=/tmp/.version,from=version <<EOT
+  set -e
+  mkdir /out
+  version="$(cat /tmp/.version)"
+  [ "$TARGETOS" = "windows" ] && ext=".exe"
+  for f in *; do
+    cp "$f" "/out/${f%.*}-${version}.${TARGETOS}-${TARGETARCH}${TARGETVARIANT}${ext}"
+  done
+EOT
+
+FROM scratch AS release
+COPY --from=releaser /out/ /
+
+FROM binaries
diff --git a/Jenkinsfile b/Jenkinsfile
deleted file mode 100644
index e43d232..0000000
--- a/Jenkinsfile
+++ /dev/null
@@ -1,83 +0,0 @@
-pipeline {
-    agent none
-    options {
-        checkoutToSubdirectory('src/github.com/docker/docker-credential-helpers')
-    }
-    stages {
-        stage('build') {
-            parallel {
-                stage('linux') {
-                    agent {
-                        kubernetes {
-                            label 'declarative'
-                            containerTemplate {
-                                name 'golang'
-                                image 'golang:1.12.4'
-                                ttyEnabled true
-                                command 'cat'
-                            }
-                        }
-                    }
-                    environment {
-                        GOPATH = pwd()
-                        PATH   = "/usr/local/go/bin:${GOPATH}/bin:$PATH"
-                    }
-                    steps {
-                        container('golang') {
-                            dir('src/github.com/docker/docker-credential-helpers') {
-                                sh 'apt-get update && apt-get install -y libsecret-1-dev pass'
-                                sh 'make deps fmt lint test'
-                                sh 'make pass secretservice'
-                                sh 'make linuxrelease'
-                                archiveArtifacts 'release/docker-credential-*'
-                            }
-                        }
-                    }
-                }
-                stage('mac') {
-                    agent {
-                        label 'mac-build && go1.12.4'
-                    }
-                    environment {
-                        PATH   = "/usr/local/go/bin:${GOPATH}/bin:$PATH"
-                        GOPATH = pwd()
-                    }
-                    steps {
-                        dir('src/github.com/docker/docker-credential-helpers') {
-                            sh 'make deps fmt lint test'
-                            sh 'make osxcodesign'
-                            sh 'make osxrelease'
-                            archiveArtifacts 'release/docker-credential-*'
-                        }
-                    }
-                }
-                stage('windows') {
-                    agent {
-                        label 'win-build && go1.12.4'
-                    }
-                    environment {
-                        GOPATH      = pwd()
-                        PATH        = "${pwd()}/bin;$PATH"
-                        PFX         = credentials('windows-build-2019-pfx')
-                        PFXPASSWORD = credentials('windows-build-2019-pfx-password')
-                    }
-                    steps {
-                        dir('src/github.com/docker/docker-credential-helpers') {
-                            sh 'echo ${PFX} | base64 -d > pfx'
-
-                            sh 'make deps fmt lint test'
-                            sh 'make wincred'
-                            bat """ "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\x86\\signtool.exe" sign /fd SHA256 /a /f pfx /p ${PFXPASSWORD} /d Docker /du https://www.docker.com /t http://timestamp.verisign.com/scripts/timestamp.dll bin\\docker-credential-wincred.exe """
-                            archiveArtifacts 'bin/docker-credential-*'
-                        }
-                    }
-                    post {
-                        always {
-                            sh 'rm -f pfx'
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/Makefile b/Makefile
index 6eda46d..ceb860f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,85 +1,74 @@
-.PHONY: all deps osxkeychain secretservice test validate wincred pass deb
+PACKAGE ?= github.com/docker/docker-credential-helpers
+VERSION ?= $(shell ./hack/git-meta version)
+REVISION ?= $(shell ./hack/git-meta revision)
 
-TRAVIS_OS_NAME ?= linux
-VERSION := $(shell grep 'const Version' credentials/version.go | awk -F'"' '{ print $$2 }')
+GO_PKG = github.com/docker/docker-credential-helpers
+GO_LDFLAGS = -s -w -X ${GO_PKG}/credentials.Version=${VERSION} -X ${GO_PKG}/credentials.Revision=${REVISION} -X ${GO_PKG}/credentials.Package=${PACKAGE}
 
-all: test
+BUILDX_CMD ?= docker buildx
+DESTDIR ?= ./bin/build
 
-deps:
-	go get -u golang.org/x/lint/golint
+.PHONY: all
+all: cross
 
+.PHONY: clean
 clean:
 	rm -rf bin
-	rm -rf release
 
-osxkeychain:
-	mkdir -p bin
-	go build -ldflags -s -o bin/docker-credential-osxkeychain osxkeychain/cmd/main_darwin.go
+.PHONY: build-%
+build-%: # build, can be one of build-osxkeychain build-pass build-secretservice build-wincred
+	go build -trimpath -ldflags="$(GO_LDFLAGS) -X ${GO_PKG}/credentials.Name=docker-credential-$*" -o "$(DESTDIR)/docker-credential-$*" ./$*/cmd/
 
-osxcodesign: osxkeychain
-	$(eval SIGNINGHASH = $(shell security find-identity -v -p codesigning | grep "Developer ID Application: Docker Inc" | cut -d ' ' -f 4))
-	xcrun -log codesign -s $(SIGNINGHASH) --force --verbose bin/docker-credential-osxkeychain
-	xcrun codesign --verify --deep --strict --verbose=2 --display bin/docker-credential-osxkeychain
+# aliases for build-* targets
+.PHONY: osxkeychain secretservice pass wincred
+osxkeychain: build-osxkeychain
+secretservice: build-secretservice
+pass: build-pass
+wincred: build-wincred
 
-secretservice:
-	mkdir -p bin
-	go build -o bin/docker-credential-secretservice secretservice/cmd/main_linux.go
+.PHONY: cross
+cross: # cross build all supported credential helpers
+	$(BUILDX_CMD) bake binaries
 
-pass:
-	mkdir -p bin
-	go build -o bin/docker-credential-pass pass/cmd/main.go
+.PHONY: release
+release: # create release
+	./hack/release
 
-wincred:
-	mkdir -p bin
-	go build -o bin/docker-credential-wincred.exe wincred/cmd/main_windows.go
-
-linuxrelease:
-	mkdir -p release
-	cd bin && tar cvfz ../release/docker-credential-pass-v$(VERSION)-amd64.tar.gz docker-credential-pass
-	cd bin && tar cvfz ../release/docker-credential-secretservice-v$(VERSION)-amd64.tar.gz docker-credential-secretservice
-
-osxrelease:
-	mkdir -p release
-	cd bin && tar cvfz ../release/docker-credential-osxkeychain-v$(VERSION)-amd64.tar.gz docker-credential-osxkeychain
-
-winrelease:
-	mkdir -p release
-	cd bin && zip ../release/docker-credential-wincred-v$(VERSION)-amd64.zip docker-credential-wincred.exe
-
-test:
-	# tests all packages except vendor
+.PHONY: test
+test: # tests all packages except vendor
 	go test -v `go list ./... | grep -v /vendor/`
 
-vet: vet_$(TRAVIS_OS_NAME)
-	go vet ./credentials
-
-vet_win:
-	go vet ./wincred
-
-vet_osx:
-	go vet ./osxkeychain
-
-vet_linux:
-	go vet ./secretservice
-
+.PHONY: lint
 lint:
-	for p in `go list ./... | grep -v /vendor/`; do \
-		golint $$p ; \
-	done
+	$(BUILDX_CMD) bake lint
 
+.PHONY: validate-vendor
+validate-vendor:
+	$(BUILDX_CMD) bake vendor-validate
+
+.PHONY: fmt
 fmt:
 	gofmt -s -l `ls **/*.go | grep -v vendor`
 
-validate: vet lint fmt
-
+.PHONY: validate
+validate: lint validate-vendor fmt
 
 BUILDIMG:=docker-credential-secretservice-$(VERSION)
+.PHONY: deb
 deb:
 	mkdir -p release
 	docker build -f deb/Dockerfile \
-		--build-arg VERSION=$(VERSION) \
-		--build-arg DISTRO=xenial \
+		--build-arg VERSION=$(patsubst v%,%,$(VERSION)) \
+		--build-arg REVISION=$(REVISION) \
 		--tag $(BUILDIMG) \
 		.
 	docker run --rm --net=none $(BUILDIMG) tar cf - /release | tar xf -
 	docker rmi $(BUILDIMG)
+
+.PHONY: vendor
+vendor:
+	$(eval $@_TMP_OUT := $(shell mktemp -d -t docker-output.XXXXXXXXXX))
+	$(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" vendor
+	rm -rf ./vendor
+	cp -R "$($@_TMP_OUT)"/* .
+	rm -rf "$($@_TMP_OUT)"
diff --git a/README.md b/README.md
index c469c94..7c7a45e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
+[![GitHub release](https://img.shields.io/github/release/docker/docker-credential-helpers.svg?style=flat-square)](https://github.com/docker/docker-credential-helpers/releases/latest)
+[![PkgGoDev](https://img.shields.io/badge/go.dev-docs-007d9c?style=flat-square&logo=go&logoColor=white)](https://pkg.go.dev/github.com/docker/docker-credential-helpers)
+[![Build Status](https://img.shields.io/github/workflow/status/docker/docker-credential-helpers/build?label=build&logo=github&style=flat-square)](https://github.com/docker/docker-credential-helpers/actions?query=workflow%3Abuild)
+[![Codecov](https://img.shields.io/codecov/c/github/docker/docker-credential-helpers?logo=codecov&style=flat-square)](https://codecov.io/gh/docker/docker-credential-helpers)
+[![Go Report Card](https://goreportcard.com/badge/github.com/docker/docker-credential-helpers?style=flat-square)](https://goreportcard.com/report/github.com/docker/docker-credential-helpers)
+
 ## Introduction
 
 docker-credential-helpers is a suite of programs to use native stores to keep Docker credentials safe.
@@ -6,30 +12,49 @@ docker-credential-helpers is a suite of programs to use native stores to keep Do
 
 Go to the [Releases](https://github.com/docker/docker-credential-helpers/releases) page and download the binary that works better for you. Put that binary in your `$PATH`, so Docker can find it.
 
-### Building from scratch
+## Building
+
+You can build the credential helpers using Docker:
 
-The programs in this repository are written with the Go programming language. These instructions assume that you have previous knowledge about the language and you have it installed in your machine.
+```shell
+# create builder
+$ docker buildx create --use
 
-1 - Download the source and put it in your `$GOPATH` with `go get`.
+# build credential helpers from remote repository and output to ./bin/build
+$ docker buildx bake "https://github.com/docker/docker-credential-helpers.git"
 
+# or from local source
+$ git clone https://github.com/docker/docker-credential-helpers.git
+$ cd docker-credential-helpers
+$ docker buildx bake
 ```
-$ go get github.com/docker/docker-credential-helpers
+
+Or if the toolchain is already installed on your machine:
+
+1 - Download the source.
+
+```shell
+$ git clone https://github.com/docker/docker-credential-helpers.git
+$ cd docker-credential-helpers
 ```
 
 2 - Use `make` to build the program you want. That will leave an executable in the `bin` directory inside the repository.
 
-```
-$ cd $GOPATH/docker/docker-credentials-helpers
+```shell
 $ make osxkeychain
 ```
 
 3 - Put that binary in your `$PATH`, so Docker can find it.
 
+```shell
+$ cp bin/build/docker-credential-osxkeychain /usr/local/bin/
+```
+
 ## Usage
 
 ### With the Docker Engine
 
-Set the `credsStore` option in your `.docker/config.json` file with the suffix of the program you want to use. For instance, set it to `osxkeychain` if you want to use `docker-credential-osxkeychain`.
+Set the `credsStore` option in your `~/.docker/config.json` file with the suffix of the program you want to use. For instance, set it to `osxkeychain` if you want to use `docker-credential-osxkeychain`.
 
 ```json
 {
@@ -73,8 +98,8 @@ A credential helper can be any program that can read values from the standard in
 
 This repository also includes libraries to implement new credentials programs in Go. Adding a new helper program is pretty easy. You can see how the OS X keychain helper works in the [osxkeychain](osxkeychain) directory.
 
-1. Implement the interface `credentials.Helper` in `YOUR_PACKAGE/YOUR_PACKAGE_$GOOS.go`
-2. Create a main program in `YOUR_PACKAGE/cmd/main_$GOOS.go`.
+1. Implement the interface `credentials.Helper` in `YOUR_PACKAGE/`
+2. Create a main program in `YOUR_PACKAGE/cmd/`.
 3. Add make tasks to build your program and run tests.
 
 ## License
diff --git a/client/client_test.go b/client/client_test.go
index 649c1ae..693faaa 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 
@@ -32,7 +31,7 @@ type mockProgram struct {
 // Output returns responses from the remote credentials helper.
 // It mocks those responses based in the input in the mock.
 func (m *mockProgram) Output() ([]byte, error) {
-	in, err := ioutil.ReadAll(m.input)
+	in, err := io.ReadAll(m.input)
 	if err != nil {
 		return nil, err
 	}
@@ -108,8 +107,8 @@ func ExampleStore() {
 
 func TestStore(t *testing.T) {
 	valid := []credentials.Credentials{
-		{validServerAddress, "foo", "bar"},
-		{validServerAddress2, "<token>", "abcd1234"},
+		{ServerURL: validServerAddress, Username: "foo", Secret: "bar"},
+		{ServerURL: validServerAddress2, Username: "<token>", Secret: "abcd1234"},
 	}
 
 	for _, v := range valid {
@@ -119,7 +118,7 @@ func TestStore(t *testing.T) {
 	}
 
 	invalid := []credentials.Credentials{
-		{invalidServerAddress, "foo", "bar"},
+		{ServerURL: invalidServerAddress, Username: "foo", Secret: "bar"},
 	}
 
 	for _, v := range invalid {
@@ -142,8 +141,8 @@ func ExampleGet() {
 
 func TestGet(t *testing.T) {
 	valid := []credentials.Credentials{
-		{validServerAddress, "foo", "bar"},
-		{validServerAddress2, "<token>", "abcd1234"},
+		{ServerURL: validServerAddress, Username: "foo", Secret: "bar"},
+		{ServerURL: validServerAddress2, Username: "<token>", Secret: "abcd1234"},
 	}
 
 	for _, v := range valid {
diff --git a/credentials/credentials.go b/credentials/credentials.go
index da8b594..91d9d4b 100644
--- a/credentials/credentials.go
+++ b/credentials/credentials.go
@@ -169,8 +169,8 @@ func Erase(helper Helper, reader io.Reader) error {
 	return helper.Delete(serverURL)
 }
 
-//List returns all the serverURLs of keys in
-//the OS store as a list of strings
+// List returns all the serverURLs of keys in
+// the OS store as a list of strings
 func List(helper Helper, writer io.Writer) error {
 	accts, err := helper.List()
 	if err != nil {
@@ -179,8 +179,8 @@ func List(helper Helper, writer io.Writer) error {
 	return json.NewEncoder(writer).Encode(accts)
 }
 
-//PrintVersion outputs the current version.
+// PrintVersion outputs the current version.
 func PrintVersion(writer io.Writer) error {
-	fmt.Fprintln(writer, Version)
+	fmt.Fprintf(writer, "%s (%s) %s\n", Name, Package, Version)
 	return nil
 }
diff --git a/credentials/version.go b/credentials/version.go
index 185e367..84377c2 100644
--- a/credentials/version.go
+++ b/credentials/version.go
@@ -1,4 +1,16 @@
 package credentials
 
-// Version holds a string describing the current version
-const Version = "0.6.4"
+var (
+	// Name is filled at linking time
+	Name = ""
+
+	// Package is filled at linking time
+	Package = "github.com/docker/docker-credential-helpers"
+
+	// Version holds the complete version number. Filled in at linking time.
+	Version = "v0.0.0+unknown"
+
+	// Revision is filled with the VCS (e.g. git) revision being used to build
+	// the program at linking time.
+	Revision = ""
+)
diff --git a/deb/Dockerfile b/deb/Dockerfile
index 1e97b96..c36ae0a 100644
--- a/deb/Dockerfile
+++ b/deb/Dockerfile
@@ -1,13 +1,21 @@
-FROM ubuntu:xenial
+ARG GO_VERSION=1.18.5
+ARG DISTRO=ubuntu
+ARG SUITE=focal
 
-ARG VERSION
-ARG DISTRO
+FROM golang:${GO_VERSION}-buster AS golang
+
+FROM ${DISTRO}:${SUITE}
 
-RUN apt-get update && apt-get install -yy debhelper dh-make golang-go libsecret-1-dev
+ARG DEBIAN_FRONTEND=noninteractive
+RUN apt-get update && apt-get install -yy debhelper dh-make libsecret-1-dev
 RUN mkdir -p /build
 
 WORKDIR /build
-ENV GOPATH /build
+ENV GOPROXY=https://proxy.golang.org|direct
+ENV GO111MODULE=off
+ENV GOPATH=/build
+ENV PATH=$PATH:/usr/local/go/bin:$GOPATH/bin
+COPY --from=golang /usr/local/go /usr/local/go
 
 COPY Makefile .
 COPY credentials credentials
@@ -16,4 +24,12 @@ COPY pass pass
 COPY deb/debian ./debian
 COPY deb/build-deb .
 
-RUN /build/build-deb ${VERSION} ${DISTRO}
+ARG VERSION
+ENV VERSION=${VERSION}
+ARG REVISION
+ENV REVISION=${REVISION}
+ARG DISTRO
+ENV DISTRO=${DISTRO}
+ARG SUITE
+ENV SUITE=${SUITE}
+RUN /build/build-deb
diff --git a/deb/build-deb b/deb/build-deb
index dbb9172..04d3de1 100755
--- a/deb/build-deb
+++ b/deb/build-deb
@@ -1,14 +1,10 @@
 #!/usr/bin/env bash
-set -x
-set -e
-
-version=$1
-distro=$2
+set -ex
 
 maintainer=$(awk -F ': ' '$1 == "Maintainer" { print $2; exit }' debian/control)
 
 cat > "debian/changelog" <<-EOF
-docker-credential-helpers ($version) $DISTRO; urgency=low
+docker-credential-helpers ($VERSION) $DISTRO-$SUITE; urgency=low
 
   * New upstream version
 
diff --git a/deb/debian/rules b/deb/debian/rules
index e3421e9..4750af3 100755
--- a/deb/debian/rules
+++ b/deb/debian/rules
@@ -3,7 +3,8 @@
 DESTDIR := $(CURDIR)/debian/tmp
 
 override_dh_auto_build:
-	make secretservice pass
+	make build-secretservice DESTDIR=bin
+	make build-pass DESTDIR=bin
 
 override_dh_auto_install:
 	install -D bin/docker-credential-secretservice $(DESTDIR)/usr/bin/docker-credential-secretservice
diff --git a/debian/changelog b/debian/changelog
index c83359d..16d51d7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-docker-docker-credential-helpers (0.7.0+ds1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 14 Dec 2022 16:23:47 -0000
+
 golang-github-docker-docker-credential-helpers (0.6.4+ds1-1) unstable; urgency=medium
 
   * New upstream version 0.6.4+ds1
diff --git a/docker-bake.hcl b/docker-bake.hcl
new file mode 100644
index 0000000..74c3097
--- /dev/null
+++ b/docker-bake.hcl
@@ -0,0 +1,73 @@
+variable "GO_VERSION" {
+  default = "1.18.5"
+}
+
+# Defines the output folder
+variable "DESTDIR" {
+  default = ""
+}
+function "bindir" {
+  params = [defaultdir]
+  result = DESTDIR != "" ? DESTDIR : "./bin/${defaultdir}"
+}
+
+target "_common" {
+  args = {
+    GO_VERSION = GO_VERSION
+  }
+}
+
+group "default" {
+  targets = ["binaries"]
+}
+
+group "validate" {
+  targets = ["lint", "vendor-validate"]
+}
+
+target "lint" {
+  inherits = ["_common"]
+  target = "lint"
+  output = ["type=cacheonly"]
+}
+
+target "vendor-validate" {
+  inherits = ["_common"]
+  target = "vendor-validate"
+  output = ["type=cacheonly"]
+}
+
+target "vendor" {
+  inherits = ["_common"]
+  target = "vendor-update"
+  output = ["."]
+}
+
+target "test" {
+  inherits = ["_common"]
+  target = "test-coverage"
+  output = [bindir("coverage")]
+}
+
+target "binaries" {
+  inherits = ["_common"]
+  target = "binaries"
+  output = [bindir("build")]
+  platforms = [
+    "darwin/amd64",
+    "darwin/arm64",
+    "linux/amd64",
+    "linux/arm64",
+    "linux/arm/v7",
+    "linux/arm/v6",
+    "linux/ppc64le",
+    "linux/s390x",
+    "windows/amd64"
+  ]
+}
+
+target "release" {
+  inherits = ["binaries"]
+  target = "release"
+  output = [bindir("release")]
+}
diff --git a/go.mod b/go.mod
index 913b1b3..e49a779 100644
--- a/go.mod
+++ b/go.mod
@@ -1,8 +1,8 @@
 module github.com/docker/docker-credential-helpers
 
-go 1.13
+go 1.18
 
 require (
-	github.com/danieljoos/wincred v1.1.0
-	golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
+	github.com/danieljoos/wincred v1.1.2
+	golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64
 )
diff --git a/go.sum b/go.sum
index 83bc81e..68d1f0e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,16 +1,16 @@
-github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g=
-github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
+github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0=
+github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0=
 github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
+golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/hack/git-meta b/hack/git-meta
new file mode 100755
index 0000000..ed4bfb8
--- /dev/null
+++ b/hack/git-meta
@@ -0,0 +1,16 @@
+#!/usr/bin/env sh
+
+set -e
+
+case $1 in
+	"version")
+		git describe --match 'v[0-9]*' --dirty='.m' --always --tags
+		;;
+	"revision")
+		echo "$(git rev-parse HEAD)$(if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi)"
+		;;
+	*)
+		echo "usage: ./hack/git-meta <version|revision>"
+		exit 1
+		;;
+esac
diff --git a/hack/release b/hack/release
new file mode 100755
index 0000000..aff1c64
--- /dev/null
+++ b/hack/release
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+
+set -e
+
+: "${BUILDX_CMD=docker buildx}"
+: "${DESTDIR=./bin/release}"
+: "${CACHE_FROM=}"
+: "${CACHE_TO=}"
+
+: "${SIGN=}"
+: "${PFX=}"
+: "${PFXPASSWORD=}"
+
+if [ -n "$CACHE_FROM" ]; then
+	for cfrom in $CACHE_FROM; do
+		cacheFlags+=(--set "*.cache-from=$cfrom")
+	done
+fi
+if [ -n "$CACHE_TO" ]; then
+	for cto in $CACHE_TO; do
+		cacheFlags+=(--set "*.cache-to=$cto")
+	done
+fi
+
+dockerpfx=$(mktemp -t dockercredhelper-pfx.XXXXXXXXXX)
+function clean {
+	rm -f "$dockerpfx"
+}
+trap clean EXIT
+
+# release
+(
+	set -x
+	${BUILDX_CMD} bake "${cacheFlags[@]}" --set "*.output=$DESTDIR" release
+)
+
+# wrap binaries
+mv -f ./${DESTDIR}/**/* ./${DESTDIR}/
+find ./${DESTDIR} -type d -empty -delete
+
+# sign binaries
+if [ -n "$SIGN" ]; then
+	for f in "${DESTDIR}"/*".darwin-"*; do
+		SIGNINGHASH=$(security find-identity -v -p codesigning | grep "Developer ID Application: Docker Inc" | cut -d ' ' -f 4)
+		xcrun -log codesign -s "$SIGNINGHASH" --force --verbose "$f"
+		xcrun codesign --verify --deep --strict --verbose=2 --display "$f"
+	done
+	for f in "${DESTDIR}"/*".windows-"*; do
+		echo ${PFX} | base64 -d > "$dockerpfx"
+		signtool sign /fd SHA256 /a /f pfx /p ${PFXPASSWORD} /d Docker /du https://www.docker.com /t http://timestamp.verisign.com/scripts/timestamp.dll "$f"
+	done
+fi
+
+# checksums
+(
+  cd ${DESTDIR}
+  sha256sum -b docker-credential-* > ./checksums.txt
+  sha256sum -c --strict checksums.txt
+)
diff --git a/osxkeychain/osxkeychain_darwin.go b/osxkeychain/osxkeychain_darwin.go
index a6d3730..dffec45 100644
--- a/osxkeychain/osxkeychain_darwin.go
+++ b/osxkeychain/osxkeychain_darwin.go
@@ -138,7 +138,7 @@ func (h Osxkeychain) List() (map[string]string, error) {
 	listLen = int(listLenC)
 	pathTmp := (*[1 << 30]*C.char)(unsafe.Pointer(pathsC))[:listLen:listLen]
 	acctTmp := (*[1 << 30]*C.char)(unsafe.Pointer(acctsC))[:listLen:listLen]
-	//taking the array of c strings into go while ignoring all the stuff irrelevant to credentials-helper
+	// taking the array of c strings into go while ignoring all the stuff irrelevant to credentials-helper
 	resp := make(map[string]string)
 	for i := 0; i < listLen; i++ {
 		if C.GoString(pathTmp[i]) == "0" {
@@ -160,7 +160,7 @@ func splitServer(serverURL string) (*C.struct_Server, error) {
 		proto = C.kSecProtocolTypeHTTP
 	}
 	var port int
-	p := registryurl.GetPort(u)
+	p := u.Port()
 	if p != "" {
 		port, err = strconv.Atoi(p)
 		if err != nil {
@@ -170,7 +170,7 @@ func splitServer(serverURL string) (*C.struct_Server, error) {
 
 	return &C.struct_Server{
 		proto: C.SecProtocolType(proto),
-		host:  C.CString(registryurl.GetHostname(u)),
+		host:  C.CString(u.Hostname()),
 		port:  C.uint(port),
 		path:  C.CString(u.Path),
 	}, nil
diff --git a/pass/pass.go b/pass/pass.go
index 5750a78..6624e73 100644
--- a/pass/pass.go
+++ b/pass/pass.go
@@ -9,7 +9,7 @@ import (
 	"encoding/base64"
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io/fs"
 	"os"
 	"os/exec"
 	"path"
@@ -20,9 +20,9 @@ import (
 )
 
 // PASS_FOLDER contains the directory where credentials are stored
-const PASS_FOLDER = "docker-credential-helpers" //nolint: golint
+const PASS_FOLDER = "docker-credential-helpers" //nolint:revive
 
-// Pass handles secrets using Linux secret-service as a store.
+// Pass handles secrets using pass as a store.
 type Pass struct{}
 
 // Ideally these would be stored as members of Pass, but since all of Pass's
@@ -116,16 +116,22 @@ func getPassDir() string {
 func listPassDir(args ...string) ([]os.FileInfo, error) {
 	passDir := getPassDir()
 	p := path.Join(append([]string{passDir, PASS_FOLDER}, args...)...)
-	contents, err := ioutil.ReadDir(p)
+	entries, err := os.ReadDir(p)
 	if err != nil {
 		if os.IsNotExist(err) {
 			return []os.FileInfo{}, nil
 		}
-
 		return nil, err
 	}
-
-	return contents, nil
+	infos := make([]fs.FileInfo, 0, len(entries))
+	for _, entry := range entries {
+		info, err := entry.Info()
+		if err != nil {
+			return nil, err
+		}
+		infos = append(infos, info)
+	}
+	return infos, nil
 }
 
 // Get returns the username and secret to use for a given registry server URL.
@@ -138,7 +144,7 @@ func (p Pass) Get(serverURL string) (string, string, error) {
 
 	if _, err := os.Stat(path.Join(getPassDir(), PASS_FOLDER, encoded)); err != nil {
 		if os.IsNotExist(err) {
-			return "", "", nil
+			return "", "", credentials.NewErrCredentialsNotFound()
 		}
 
 		return "", "", err
diff --git a/pass/pass_test.go b/pass/pass_test.go
index d342b61..bec4053 100644
--- a/pass/pass_test.go
+++ b/pass/pass_test.go
@@ -16,6 +16,8 @@ func TestPassHelper(t *testing.T) {
 		Secret:    "isthebestmeshuggahalbum",
 	}
 
+	_ = helper.CheckInitialized()
+
 	helper.Add(creds)
 
 	creds.ServerURL = "https://foobar.docker.io:9999/v2"
@@ -54,13 +56,9 @@ func TestPassHelper(t *testing.T) {
 			t.Fatal(err)
 		}
 
-		username, _, err = helper.Get(server)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if username != "" {
-			t.Fatalf("%s shouldn't exist any more", username)
+		_, _, err = helper.Get(server)
+		if !credentials.IsErrCredentialsNotFound(err) {
+			t.Fatalf("expected credentials not found, actual: %v", err)
 		}
 	}
 
@@ -73,3 +71,12 @@ func TestPassHelper(t *testing.T) {
 		t.Fatal("didn't delete all creds?")
 	}
 }
+
+func TestMissingCred(t *testing.T) {
+	helper := Pass{}
+
+	_, _, err := helper.Get("garbage")
+	if !credentials.IsErrCredentialsNotFound(err) {
+		t.Fatalf("expected credentials not found, actual: %v", err)
+	}
+}
diff --git a/registryurl/parse.go b/registryurl/parse.go
index 7617132..f9a9f88 100644
--- a/registryurl/parse.go
+++ b/registryurl/parse.go
@@ -28,10 +28,24 @@ func Parse(registryURL string) (*url.URL, error) {
 		return nil, errors.New("unsupported scheme: " + u.Scheme)
 	}
 
-	if GetHostname(u) == "" {
+	if u.Hostname() == "" {
 		return nil, errors.New("no hostname in URL")
 	}
 
 	u.RawQuery = ""
 	return u, nil
 }
+
+// GetHostname returns the hostname of the URL
+//
+// Deprecated: use url.Hostname()
+func GetHostname(u *url.URL) string {
+	return u.Hostname()
+}
+
+// GetPort returns the port number of the URL
+//
+// Deprecated: use url.Port()
+func GetPort(u *url.URL) string {
+	return u.Port()
+}
diff --git a/registryurl/url_go18.go b/registryurl/url_go18.go
deleted file mode 100644
index 2bfc153..0000000
--- a/registryurl/url_go18.go
+++ /dev/null
@@ -1,17 +0,0 @@
-//+build go1.8
-
-package registryurl
-
-import (
-	url "net/url"
-)
-
-// GetHostname returns the hostname of the URL
-func GetHostname(u *url.URL) string {
-	return u.Hostname()
-}
-
-// GetPort returns the port number of the URL
-func GetPort(u *url.URL) string {
-	return u.Port()
-}
diff --git a/registryurl/url_non_go18.go b/registryurl/url_non_go18.go
deleted file mode 100644
index 7c8a88f..0000000
--- a/registryurl/url_non_go18.go
+++ /dev/null
@@ -1,41 +0,0 @@
-//+build !go1.8
-
-package registryurl
-
-import (
-	url "net/url"
-	"strings"
-)
-
-func GetHostname(u *url.URL) string {
-	return stripPort(u.Host)
-}
-
-func GetPort(u *url.URL) string {
-	return portOnly(u.Host)
-}
-
-func stripPort(hostport string) string {
-	colon := strings.IndexByte(hostport, ':')
-	if colon == -1 {
-		return hostport
-	}
-	if i := strings.IndexByte(hostport, ']'); i != -1 {
-		return strings.TrimPrefix(hostport[:i], "[")
-	}
-	return hostport[:colon]
-}
-
-func portOnly(hostport string) string {
-	colon := strings.IndexByte(hostport, ':')
-	if colon == -1 {
-		return ""
-	}
-	if i := strings.Index(hostport, "]:"); i != -1 {
-		return hostport[i+len("]:"):]
-	}
-	if strings.Contains(hostport, "]") {
-		return ""
-	}
-	return hostport[colon+len(":"):]
-}
diff --git a/secretservice/secretservice_linux.go b/secretservice/secretservice_linux.go
index 26efc0d..5410496 100644
--- a/secretservice/secretservice_linux.go
+++ b/secretservice/secretservice_linux.go
@@ -96,7 +96,8 @@ func (h Secretservice) List() (map[string]string, error) {
 	defer C.freeListData(&acctsC, listLenC)
 	if err != nil {
 		defer C.g_error_free(err)
-		return nil, errors.New("Error from list function in secretservice_linux.c likely due to error in secretservice library")
+		errMsg := (*C.char)(unsafe.Pointer(err.message))
+		return nil, errors.New(C.GoString(errMsg))
 	}
 
 	resp := make(map[string]string)

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/doc/golang-github-docker-docker-credential-helpers-dev/README.md.gz
-rwxr-xr-x  root/root   /usr/bin/build/docker-credential-pass
-rwxr-xr-x  root/root   /usr/bin/build/docker-credential-secretservice

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/debug/.build-id/62/a446d3caa45aea6235b04aef8b49d01b266fe3.debug
-rw-r--r--  root/root   /usr/share/doc/golang-docker-credential-helpers/changelog.gz
-rw-r--r--  root/root   /usr/share/doc/golang-github-docker-docker-credential-helpers-dev/README.md
-rw-r--r--  root/root   /usr/share/doc/golang-github-docker-docker-credential-helpers-dev/changelog.gz
-rw-r--r--  root/root   /usr/share/gocode/src/github.com/docker/docker-credential-helpers/registryurl/url_go18.go
-rw-r--r--  root/root   /usr/share/gocode/src/github.com/docker/docker-credential-helpers/registryurl/url_non_go18.go
-rwxr-xr-x  root/root   /usr/bin/docker-credential-pass
-rwxr-xr-x  root/root   /usr/bin/docker-credential-secretservice
lrwxrwxrwx  root/root   /usr/share/doc/golang-docker-credential-helpers-dbgsym -> golang-docker-credential-helpers

Control files of package golang-docker-credential-helpers: lines which differ (wdiff format)

  • Built-Using: golang-1.19 (= 1.19.5-1), golang-golang-x-sys (= 0.3.0-1) 0.1.0-1)
  • Depends: gnome-keyring, libc6 (>= 2.34), libgcc-s1 (>= 3.3.1), libglib2.0-0 (>= 2.28.0), libgo21, libsecret-1-0 (>= 0.7)

No differences were encountered between the control files of package golang-github-docker-docker-credential-helpers-dev

More details

Full run details