Skip to content

New token-command option for cabal upload - #12132

Merged
mergify[bot] merged 6 commits into
haskell:masterfrom
LaurentRDC:token-command
Sep 2, 2026
Merged

mergify[bot] merged 6 commits into
haskell:masterfrom
LaurentRDC:token-command

Conversation

@LaurentRDC

@LaurentRDC LaurentRDC commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

This patch addresses #12130 by adding a new option to cabal upload, --token-command.

QA notes

In order to test the following exactly, you need some form of secret management. I will use 1password, which is used as op on the command line.

Calling cabal upload --verbose --token-command=... should look like the following:

> cabal upload --verbose --token-command='sh -c "op read <secret-name>"' <some dist>
> ./test.sh
Running: sh -c 'op read <secret-name>'
Uploading
<some dist>...
Running: /usr/bin/curl --header 'Authorization: X-ApiKey <OMITTED>
' 'https://hackage.haskell.org/packages/candidates' --form 'package=<snip>' --write-out '
%{http_code}' --user-agent 'cabal-install/3.17.0.0 (linux; x86_64)' --silent --show-error --header 'Accept: text/plain' --location
...

In particular, the exposed curl call shows that the Hackage token (<OMITTED> above) is being pulled from the token-command argument appropriately.

Likewise, inserting the following line in the config file:

token-command='sh -c "op read <secret-name>"' 

and running

cabal upload --verbose <some dist>

gives the same exact results

@LaurentRDC
LaurentRDC marked this pull request as ready for review July 20, 2026 20:43
@ffaf1

ffaf1 commented Jul 20, 2026 •

Copy link
Copy Markdown
Collaborator

Manual QA notes have been included.

I do not see them.

@LaurentRDC

Copy link
Copy Markdown
Contributor Author

You are right, I misread as "Manual QA done". Apologies!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for obtaining a Hackage upload token by executing an external command, addressing the need to avoid storing tokens in plaintext config files (Issue #12130). This integrates with existing cabal upload flag/config handling patterns similar to --password-command.

Changes:

  • Add --token-command (-T) option to cabal upload, plumbed through UploadFlags and config merging.
  • Execute the configured command during cabal upload to obtain the token.
  • Update docs/changelog and extend config-related tests to cover the new option’s presence/serialization.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
doc/cabal-commands.rst Documents the new --token-command option for cabal upload.
changelog.d/token-command.md Adds a user-facing changelog entry for the new option.
cabal-testsuite/PackageTests/UserConfig/cabal.test.hs Extends user-config update tests to include token-command serialization.
cabal-install/tests/IntegrationTests2.hs Ensures generated config option comments include token-command.
cabal-install/src/Distribution/Client/Setup.hs Adds uploadTokenCmd flag and CLI parser for --token-command.
cabal-install/src/Distribution/Client/Main.hs Runs the command to obtain a token and passes it to upload/uploadDoc.
cabal-install/src/Distribution/Client/Config.hs Ensures uploadTokenCmd is merged in SavedConfig Semigroup instance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/cabal-commands.rst
Comment thread cabal-install/src/Distribution/Client/Main.hs
Comment thread cabal-install/src/Distribution/Client/Main.hs
Comment thread changelog.d/token-command.md Outdated
@ulysses4ever

Copy link
Copy Markdown
Collaborator

Thanks! After quick skimming this looks ok except the failing test. In order to update the reference output of the test (the reason it fails currently) you have to build the test suite executable from the cabal-testsuite package and run it with the --accept flag as explained in that package's README.

@LaurentRDC

LaurentRDC commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for pointing me to the instructions. I was able to update the expectation.

Self-note: I had to run the following commands:

$ cabal build cabal-install
$ ./dist-newstyle/build/x86_64-linux/ghc-9.12.4/cabal-testsuite-3/build/cabal-tests/cabal-tests \
    --accept \
    --with-cabal=./dist-newstyle/build/x86_64-linux/ghc-9.12.4/cabal-install-3.17.0.0/x/cabal/build/cabal/cabal \
    -j 8

@LaurentRDC
LaurentRDC requested a review from ulysses4ever July 21, 2026 18:50
@ulysses4ever

Copy link
Copy Markdown
Collaborator

I'll review formally before the weekend

@ulysses4ever ulysses4ever left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

It’d be nice if someone could try it out (a cabal binary from this patch should be available from CI). Manual QA notes (see the checklist in the PR template) could make it more probable , even if the notes are trivial in this case.

@Bodigrim

Copy link
Copy Markdown
Collaborator

Self-note: I had to run the following commands:

$ cabal build cabal-install
$ ./dist-newstyle/build/x86_64-linux/ghc-9.12.4/cabal-testsuite-3/build/cabal-tests/cabal-tests \
    --accept \
    --with-cabal=./dist-newstyle/build/x86_64-linux/ghc-9.12.4/cabal-install-3.17.0.0/x/cabal/build/cabal/cabal \
    -j 8

You can do it without hardcoding pathes:

cabal build cabal-install:exe:cabal
cabal run cabal-testsuite:exe:cabal-tests -- --with-cabal=$(cabal list-bin cabal-install:exe:cabal) --accept -j8

@LaurentRDC

Copy link
Copy Markdown
Contributor Author

Thanks!

It’d be nice if someone could try it out (a cabal binary from this patch should be available from CI). Manual QA notes (see the checklist in the PR template) could make it more probable , even if the notes are trivial in this case.

I haven't forgotten about this, I just haven't found the time to do it yet

@LaurentRDC

Copy link
Copy Markdown
Contributor Author

@ulysses4ever I have updated the PR body with QA notes

@ulysses4ever

Copy link
Copy Markdown
Collaborator

Oh my, it narrowly missed 3.18.10… the good news is: there’s 3.18.2.0 on the way!

we need a second review! @Mikolaj @ffaf1 @philderbeast also, share if you have concerns regarding backporting it to 3.18

@ulysses4ever

Copy link
Copy Markdown
Collaborator

It’s a straightforward change, client only, but it’s not a bug fix, so technically… but it’s our fault that it slipped through the cracks during 3.18.1.0 release

@ffaf1

ffaf1 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

This is not a regression, but indeed it slipped through the cracks in 3.18.1.0 and — as important — it is a change which is simple and should not impact users even if it turns out the implementation is not correct.

I say this should land in 3.18.2.0.

@ffaf1

ffaf1 commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Thanks!
If you do not have further modifications, set the squash+merge label when you feel like @LaurentRDC

@LaurentRDC LaurentRDC added the squash+merge me Tell Mergify Bot to squash-merge label Aug 30, 2026
@mergify mergify Bot added the ready and waiting Mergify is waiting out the cooldown period label Aug 30, 2026
@ffaf1

ffaf1 commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Note to self: this PR contains cabal-install API breakage (data UploadFlags was changed).

This does not make it suitable for a point release.

@mergify mergify Bot added merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days queued labels Sep 2, 2026
@mergify

mergify Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 2 hours 9 minutes 10 seconds in the queue, including 2 hours 6 minutes 46 seconds running CI.

Required conditions to merge
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-approved [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Doctest Cabal
    • check-neutral = Doctest Cabal
    • check-skipped = Doctest Cabal
  • any of [🛡 GitHub branch protection]:
    • check-success = Meta checks
    • check-neutral = Meta checks
    • check-skipped = Meta checks
  • any of [🛡 GitHub branch protection]:
    • check-success = docs/readthedocs.org:cabal
    • check-neutral = docs/readthedocs.org:cabal
    • check-skipped = docs/readthedocs.org:cabal
  • any of [🛡 GitHub branch protection]:
    • check-success = Validate post job
    • check-neutral = Validate post job
    • check-skipped = Validate post job
  • any of [🛡 GitHub branch protection]:
    • check-success = fourmolu
    • check-neutral = fourmolu
    • check-skipped = fourmolu
  • any of [🛡 GitHub branch protection]:
    • check-success = hlint
    • check-neutral = hlint
    • check-skipped = hlint
  • any of [🛡 GitHub branch protection]:
    • check-success = Bootstrap post job
    • check-neutral = Bootstrap post job
    • check-skipped = Bootstrap post job
  • any of [🛡 GitHub branch protection]:
    • check-success = whitespace
    • check-neutral = whitespace
    • check-skipped = whitespace
  • any of [🛡 GitHub branch protection]:
    • check-success = Check sdist post job
    • check-neutral = Check sdist post job
    • check-skipped = Check sdist post job
  • any of [🛡 GitHub branch protection]:
    • check-success = Changelogs
    • check-neutral = Changelogs
    • check-skipped = Changelogs

@mergify
mergify Bot merged commit d97875d into haskell:master Sep 2, 2026
74 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting to To Test in Manual QA board Sep 2, 2026
@mergify mergify Bot removed the queued label Sep 2, 2026
leana8959 pushed a commit to leana8959/cabal that referenced this pull request Sep 12, 2026
* New token-command option for cabal upload

* New token-command option for cabal upload

* Fixup reference to configuration values
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attention: needs-manual-qa PR is destined for manual QA cabal-install: cmd/upload merge delay passed Applied (usually by Mergify) when PR approved and received no updates for 2 days ready and waiting Mergify is waiting out the cooldown period squash+merge me Tell Mergify Bot to squash-merge

Projects

Status: To Test

Development

Successfully merging this pull request may close these issues.

Option to fetch upload token from a command

6 participants