Ensure that package.yaml and *.cabal are Synchronized in a Github Workflow

I found a mismatched version between package.yaml and cabal file. I have added a check for this in a github workflow

      - name: Check for Source Changes
        shell: bash
        run: |
          if [ -n "$(git status --porcelain)" ]
          then
            >&2 echo 'ERROR: Source Changed After Build'
            >&2 git diff
            >&2 git status
            >&2 echo 'ERROR: Source Changed After Build'
            exit 1
          fi

Do you think this is a good way to check for this or is there a better way (besides deleting the package.yaml files)?

Don’t use package.yaml. It complicates workflows and has no major benefits.

4 Likes

I understand the sentiment, but it isn’t my call.

FWIW I notice GitHub Actuons have a similar pattern where they check if the checked-in bundled JavaScript matches the sources.

I run hpack in each package directory to update them (using the same hpack version as shown by stack --version, to avoid VCS conflicts).

I assume that the intent is that the package.yaml is the definitive package description. If that is the case, you can specify that the package.yaml should always prevail, with Stack’s --hpack-force flag.

This makes it likely that an eventual Hackage upload will contain an outdated cabal file.

1 Like

Assuming that hpack can be used in each package directory, as suggested by simonmic…can someone then use:

  • no *.cabal files at all,
  • or just trivial ones,

…in accordance with the DRY principle? (hence less or no repeated configuration details.)

Until cabal doesn’t force you to explicitly list modules (automated with a formatter or not, I wouldn’t say package.yaml has no major benefits :grin:

It also allows you to include other yaml files. It doesn’t merge smartly but still. Better than cabal.

1 Like

The Stack project’s own CI also uses git status --porcelain (in its release.hs Haskell script).

Is there a reason they don’t print to sdterr?

      - name: Compare the expected and actual dist directories
        run: |
          if [ "$(git diff --ignore-space-at-eol ${{inputs.dist-path}} | wc -l)" -gt "0" ]; then
            echo "Detected uncommitted changes after the build. See the status below:"
            git diff
            exit 1
          fi
        id: diff

In a workflow that will update the commit or before you commit and push?

Any thoughts on using git hooks for this as described in Putting Git hooks into a repository - Stack Overflow

We do something similar in hindent:

      # Check this before building, otherwise stack will overwrite the cabal file.
      - name: Validate cabal file is properly generated from HPack
        if: matrix.os != 'windows-latest' # Since we're using `diff -u`, cannot run on Windows
        run: |
          mv hindent.cabal hindent.cabal.original
          # See https://github.com/commercialhaskell/stack/issues/3697#issuecomment-353729540.
          stack build --resolver=${{ matrix.resolver }} --dry-run
          diff -u hindent.cabal.original hindent.cabal

That is a nice precheck.

–dry-run actually builds the cabal file. Seems like a strange implementation for something that isn’t supposed to change anything.

This is such a minor inconvenience that I remain absolutely baffled that Haskellers, who spend an hour debugging type level errors, would buy into such a solution that causes so many problems just so they can avoid editing a cabal file for ~15 seconds.

1 Like

It’s not just the writing - it’s the reading.

Having 100s (or 1000s!) of explicitly-listed modules makes the cabal file annoying to read & work with.

It’s not a killer (I rarely use package.yaml for my own projects) but it is a pain in the butt.

Tbh, I think writing .cabal directly is kind of folly though. I’d probably compile from a Nix expression instead if metaprogramming in yaml or cabal directly.

If using hpack to generate .cabal from package.yaml — version-control only the package.yaml, and git-ignore the generated .cabal output.

1 Like

When I’m working on a new project it is a huge inconvenience. I’m reorganizing a lot and it’s amazing to just have a tool that manages the module changes.

That breaks your repo for cabal users doing source-repository-package and is now also discouraged by Snoyman: Storing generated cabal files

6 Likes