feat: add devcontainer feature and template for Haskell toolchain - #216
Draft
develop7 wants to merge 1 commit into
Draft
feat: add devcontainer feature and template for Haskell toolchain#216develop7 wants to merge 1 commit into
develop7 wants to merge 1 commit into
Conversation
develop7
marked this pull request as draft
July 31, 2026 07:57
develop7
force-pushed
the
feat/devcontainer
branch
6 times, most recently
from
July 31, 2026 12:23
c0d6484 to
07d9519
Compare
Add an official devcontainer feature (`haskell-toolchain`) and template (`haskell`) to close haskell#123. Feature: - Installs GHC 9.14.1, cabal 3.16.1.0, Stack 3.11.1, HLS 2.14.0.0 via ghcup - Curated formatters: ormolu 0.8.2.0, fourmolu 0.20.0.0 (the only linters compatible with GHC 9.14/base 4.22; hlint, stylish-haskell, cabal-fmt are documented as incompatible and available via globalPackages escape hatch) - 8 options: version, installStack, installHLS, installStackGHCupHook, adjustBash, installLinters, globalPackages, globalLibraries - Versions pinned in versions.ncl, which imports from 9.14/bookworm.ncl and 9.14/_globals.ncl — single source of truth shared with the Docker images - Non-root install via sudo -iu _REMOTE_USER, mirroring devcontainers-extra - install.sh rendered from install.sh.tpl.ncl via Nickel - Multistage Dockerfile.test for cached local testing with podman - 5 scenario tests + autogenerated test.sh Template: - Clone-and-go cabal helloworld project on debian-12 base - VS Code extensions (haskell.haskell, haskell-lang-server) - Format-on-save with fourmolu CI: - feature-test.yml: 5-job matrix (debian/ubuntu × amd64/arm64) - feature-publish.yml: tag-triggered OCI publish to ghcr.io - template-lint.yml: PR validation - feature-versions-sync.yml: weekly drift check
develop7
force-pushed
the
feat/devcontainer
branch
from
July 31, 2026 21:02
07d9519 to
29b858e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #123.
Summary
Adds an official devcontainer feature (
haskell-toolchain) and template (haskell) to the repo, replacing the archivedmicrosoft/vscode-dev-containersHaskell artifact.Feature:
haskell-toolchainv1.0.0Installs the Haskell toolchain via ghcup on any Debian/Ubuntu base image:
8 options:
version,installStack,installHLS,installStackGHCupHook,adjustBash,installLinters,globalPackages,globalLibraries.Design choices
versions.nclimports from9.14/bookworm.ncland9.14/_globals.ncl— the same data files that generate the Docker images. Single source of truth.devcontainers-extra/features/src/haskell—sudo -iu $_REMOTE_USERwithGHCUP_USE_XDG_DIRS=1; root fallback when_REMOTE_USERis unset.install.sh.tpl.nclvia Nickel (same pattern as the Dockerfiles).Why only ormolu and fourmolu?
hlint,stylish-haskell, andcabal-fmtconstrainghc < 9.13orbase < 4.22, making them incompatible with GHC 9.14.1 (base 4.22.0.0). They depend onghc-lib-parser 9.12.x, which has not been updated for GHC 9.14. Users can install them viaglobalPackageson older GHC versions. See the feature README for details.No Alpine in v1.0.0
Alpine support is tracked by #22 and will land in lockstep with the Alpine base images.
Template:
haskellClone-and-go cabal helloworld project:
mcr.microsoft.com/devcontainers/base:debian-12haskell.haskell,haskell-lang-serverpostCreateCommand: cabal update && cabal buildCI
feature-test.ymlfeature-publish.ymlfeature-v*ghcr.io/haskell/docker-haskell/devcontainer-features/haskell-toolchaintemplate-lint.ymlfeature-versions-sync.ymlBuild layers are cached via GitHub Actions cache (
type=gha), so changes totest.shor the workflow do not rebuild the toolchain.How to verify (as a devcontainers user)
Option A: Use the template
The container builds, installs the toolchain via ghcup, runs
cabal update && cabal build, and you should have a working Haskell environment with GHC 9.14.1, HLS, ormolu, and fourmolu.Option B: Use the feature in your own project
Create
.devcontainer/devcontainer.jsonin any repo:{ "image": "mcr.microsoft.com/devcontainers/base:debian-12", "features": { "ghcr.io/haskell/docker-haskell/devcontainer-features/haskell-toolchain:1.0.0": {} } }Then
devcontainer up --workspace-folder .or "Reopen in Container" in VS Code. Verify:Option C: Local Docker/podman test
Test plan (internal)
nickel exportrendersinstall.shcleanly (no errors, correct substitutions)shellcheck -xpasses on all shell scripts (zero warnings)devcontainer features testpasses (_defaultscenario onmcr.microsoft.com/devcontainers/base:debian-12)podman buildwith multistageDockerfile.test— all tools verified:ghc --version→ 9.14.1cabal --version→ 3.16.1.0stack --version→ 3.11.1haskell-language-server-wrapper --version→ 2.14.0.0ormolu --version→ 0.8.2.0 (ghc-lib-parser 9.14.1)fourmolu --version→ 0.20.0.0 (ghc-lib-parser 9.14.1)_REMOTE_USER) — tools install under/root,test.shdetects and passes_REMOTE_USER=vscode) — tools install under/home/vscode,test.shdetects and passesdebian:bookworm× {amd64,arm64} +ubuntu:24.04× {amd64,arm64} all passshellcheckjob passeslint(template metadata validation) passesgenerate(Dockerfile generator) passesversions.nclimport paths resolve fromdevcontainer-feature/src/haskell-toolchain/to9.14/bookworm.ncldevcontainer-template/src/haskell/helloworld.cabalbase ^>=4.22matches GHC 9.14.1install.sh.tpl.nclheredoc variable expansion (outer shell expands pinned versions,\$-escapes protect inner shell vars)