diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 436d7e2..43081c9 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,7 +1,10 @@ FROM mcr.microsoft.com/devcontainers/base:noble -# VS Code commit ID for devcontainer compatibility, argument supplied at build time via devcontainer.json -ARG VSCODE_COMMIT +# VS Code commit ID for devcontainer compatibility. Can be overridden at build time via build args. +# Default chosen for current stable VS Code Server version used in this repository. +ARG VSCODE_COMMIT=f220831ea2d946c0dcb0f3eaa480eb435a2c1260 + +ENV VSCODE_COMMIT=${VSCODE_COMMIT} # Copy and run VS Code installation files COPY ./vscode-init /opt/vscode-init diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3393cea..fffe73b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,11 +2,10 @@ // README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu { "name": "Python Development Environment", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "build": { "dockerfile": "Dockerfile", "args": { - "VSCODE_COMMIT": "f220831ea2d946c0dcb0f3eaa480eb435a2c1260" + "VSCODE_COMMIT": "${localEnv:VSCODE_COMMIT}" } }, diff --git a/.github/workflows/build-devcontainer.yml b/.github/workflows/build-devcontainer.yml index 87ca677..4829dd4 100644 --- a/.github/workflows/build-devcontainer.yml +++ b/.github/workflows/build-devcontainer.yml @@ -1,12 +1,6 @@ name: Build and Publish Dev Container on: - push: - branches: - - main - paths: - - '.devcontainer/**' - - '.github/workflows/build-devcontainer.yml' pull_request: branches: - main @@ -14,6 +8,11 @@ on: - '.devcontainer/**' - '.github/workflows/build-devcontainer.yml' workflow_dispatch: + inputs: + vscode_commit: + description: 'VS Code commit hash to use (defaults to Dockerfile ARG default if not provided)' + required: false + type: string env: REGISTRY: ghcr.io @@ -27,20 +26,38 @@ jobs: packages: write # For publishing container images pull-requests: write # For PR comments from security scan actions: write # For uploading artifacts from security scan - + steps: - name: Checkout repository uses: actions/checkout@v4 - - - name: Read VSCODE_COMMIT from devcontainer.json + + - name: Resolve VSCODE_COMMIT (input override > Dockerfile default) id: vscode-commit run: | - VSCODE_COMMIT=$(grep 'VSCODE_COMMIT' .devcontainer/devcontainer.json | tr -d '"' | cut -d " " -f 2) + # If user provided an input, trust it. Otherwise parse Dockerfile ARG default. + if [ -n "${{ github.event.inputs.vscode_commit }}" ]; then + VSCODE_COMMIT="${{ github.event.inputs.vscode_commit }}" + SOURCE="workflow_input" + else + # Extract default from ARG line: ARG VSCODE_COMMIT= + VSCODE_COMMIT=$(grep -E '^ARG VSCODE_COMMIT=' .devcontainer/Dockerfile | head -n1 | cut -d= -f2-) + if [ -z "$VSCODE_COMMIT" ]; then + echo "❌ Could not find default VSCODE_COMMIT in Dockerfile" >&2 + exit 1 + fi + SOURCE="dockerfile_default" + fi + # Basic validation (40 hex chars) + if ! echo "$VSCODE_COMMIT" | grep -Eq '^[0-9a-f]{40}$'; then + echo "❌ VSCODE_COMMIT '$VSCODE_COMMIT' is not a 40-char hex commit hash" >&2 + exit 1 + fi VSCODE_SHORT=${VSCODE_COMMIT:0:7} + echo "Resolved VSCODE_COMMIT=$VSCODE_COMMIT (source=$SOURCE)" echo "vscode_commit=$VSCODE_COMMIT" >> $GITHUB_OUTPUT echo "vscode_short=$VSCODE_SHORT" >> $GITHUB_OUTPUT - echo "Full VSCODE_COMMIT: $VSCODE_COMMIT" - echo "Short VSCODE_COMMIT: $VSCODE_SHORT" + echo "source=$SOURCE" >> $GITHUB_OUTPUT + echo "Short: $VSCODE_SHORT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -76,6 +93,8 @@ jobs: - name: Build and publish dev container uses: devcontainers/ci@v0.3 + env: + VSCODE_COMMIT: ${{ steps.vscode-commit.outputs.vscode_commit }} with: imageName: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} imageTag: ${{ steps.tags.outputs.tags }} @@ -151,6 +170,7 @@ jobs: echo "πŸ“ Labels: ${{ steps.meta.outputs.labels }}" echo "πŸ”§ VSCode Commit: ${{ steps.vscode-commit.outputs.vscode_commit }}" echo "πŸ“‹ Short Commit: ${{ steps.vscode-commit.outputs.vscode_short }}" + echo "πŸ—‚οΈ Source: ${{ steps.vscode-commit.outputs.source }}" echo "" echo "To use this dev container:" echo "1. Reference it in your devcontainer.json:" diff --git a/DEVCONTAINER.md b/DEVCONTAINER.md index 8c2ad03..3ad38a9 100644 --- a/DEVCONTAINER.md +++ b/DEVCONTAINER.md @@ -1,6 +1,6 @@ -# Dev Container for Python Development +# Dev Container for Python & R Development -This repository contains a development container configuration optimized for Python development, along with automated workflows to build and publish the container image to GitHub Container Registry (GHCR). +This repository contains a development container configuration optimized for Python (and first-class R) development, along with automated workflows to build and publish the container image to GitHub Container Registry (GHCR). For high-level usage see `README.md`; this document focuses on implementation details. ## πŸ“¦ Published Container @@ -13,11 +13,14 @@ The dev container is automatically built and published with multiple tags: - `main` - Latest build from main branch - `main-` - Specific commit builds from main branch - `pr-` - Pull request builds for testing + - `vscode-` - Builds with specific VS Code Server versions + - `vscode--` - Combination of VS Code Server and container commit ### Choosing the Right Tag - **For production/stable use**: `ghcr.io/smartdatafoundry/devcontainer:latest` -- **For reproducible builds**: `ghcr.io/smartdatafoundry/devcontainer:main-abc1234` +- **For reproducible builds**: `ghcr.io/smartdatafoundry/devcontainer:vscode--` +- **For specific VS Code Server versions**: `ghcr.io/smartdatafoundry/devcontainer:vscode-` - **For testing PR changes**: `ghcr.io/smartdatafoundry/devcontainer:pr-123` ## πŸš€ Quick Start @@ -63,30 +66,47 @@ docker run --rm -it -v $(pwd):/workspace ghcr.io/smartdatafoundry/devcontainer:l This dev container includes: -- **Base**: Ubuntu Noble (24.04) via Microsoft's `mcr.microsoft.com/devcontainers/base:noble` -- **Python**: System Python with pip and development tools (via devcontainer feature) -- **Git**: Latest version with configuration support -- **Shell**: Zsh with Oh My Zsh configuration (via common-utils feature) -- **Quarto**: For document publishing and data science workflows (latest version) -- **Marimo**: Markdown presentation tool, alternative to Jupyter Notebooks (latest version) -- **VS Code Server**: Pre-installed for immediate development -- **VS Code Extensions**: - - Continue (AI assistant) - - Black formatter for Python - - Jupyter support - - Markdown All in One - - Rainbow CSV +* **Base**: Ubuntu Noble (24.04) via Microsoft's `mcr.microsoft.com/devcontainers/base:noble` +* **Python**: System Python with pip and development tools (via feature) +* **R**: Installed via Rocker devcontainer feature (languageserver, httpgd, rmarkdown, renv, devtools, radian, vscDebugger) +* **Git**: Latest stable +* **Shell**: Zsh + Oh My Zsh (via common-utils feature) +* **Quarto**: Latest (document publishing) +* **Marimo**: Alternative interactive notebook/presentation tool +* **VS Code Server**: Pre-installed (pin via tag families) +* **VS Code Extensions**: Curated list (see `.devcontainer/vscode-init/extensions-to-install.txt`) ## πŸ”„ Automated Builds -The container is automatically built and published using GitHub Actions: +The container is built using GitHub Actions with controlled publishing: ### Build Workflow (`build-devcontainer.yml`) -- **Triggers**: Push to main branch, PRs, manual dispatch -- **Features**: Single platform (linux/amd64), intelligent caching, comprehensive validation tests -- **Publishing**: Multi-tag publishing with `latest`, `main`, `main-`, and `pr-` tags +- **PR Triggers**: Pull requests automatically build test images (`pr-` tags) using default VS Code Server commit +- **Manual Dispatch**: Production builds require manual trigger with VS Code Server commit hash + - **Required Input**: VS Code Server commit hash for reproducible builds + - **Publishing**: Multi-tag publishing with `latest`, `main`, `vscode-`, and SHA-based tags +- **Features**: Single platform (linux/amd64), intelligent caching, comprehensive validation tests, security scanning - **Testing**: Validates Python, Git, Zsh, and Quarto installations +### VS Code Server Version Control +- Default VS Code Server commit is declared once in the Dockerfile via: `ARG VSCODE_COMMIT=` +- Manual workflow dispatch can override this by providing the `vscode_commit` input +- The workflow extracts the Dockerfile default automatically if no input is provided +- The commit hash is embedded in container tags: `vscode-` and `vscode--` + +Local override examples: + +```bash +# Use Dockerfile default +devcontainer build --workspace-folder . + +# Override for build +export VSCODE_COMMIT=0f0d87fa9e96c856c5212fc86db137ac0d783365 +devcontainer build --workspace-folder . +``` + +This keeps maintenance simple: update the default by editing a single line in `Dockerfile` with support for overrides when needed via workflow inputs. + ## πŸ“ Repository Structure ``` @@ -106,7 +126,7 @@ The container is automatically built and published using GitHub Actions: β”œβ”€β”€ docs/ # Additional documentation β”œβ”€β”€ DEVCONTAINER.md # Detailed documentation β”œβ”€β”€ README.md # Overview and quick start -└── SDF_TRE_SETUP.md # SDF TRE setup guide +└── SDF_TRE_SETUP.md # SDF TRE setup guide ``` ## πŸ”§ Customization @@ -143,6 +163,8 @@ The build system creates multiple tags from a single build: - `main`: Latest commit from main branch - `main-`: Specific commit SHA for reproducible builds - `pr-`: Pull request builds for testing changes +- `vscode-`: Builds with specific VS Code Server versions +- `vscode--`: Complete version specification ## πŸ§ͺ Testing @@ -171,7 +193,7 @@ The GitHub Action will automatically test your changes when you submit a PR. ## πŸ“ License -This project is open source and available under the [MIT License](LICENSE). +Licensed under [MIT](LICENSE). --- diff --git a/README.md b/README.md index ad06e5c..8ea8c95 100644 --- a/README.md +++ b/README.md @@ -4,25 +4,41 @@ # devcontainer -Container to support Python development that comes with baked in support for the Visual Studio Code Dev Container extension, additionally includes supporting tooling and a rich set of IDE extensions. +Development container focused on Python (with first-class R support) providing a reproducible, batteries‑included environment. It ships with the VS Code Dev Containers extension assets, curated tooling, and a consistent tagging strategy for deterministic rebuilds. + +## Table of Contents +1. Published Container +2. Quick Start +3. Using in SDF TRE +4. Documentation +5. What's Included +6. R Language Support +7. VS Code Server +8. Adding Extensions +9. Automated Builds & Tag Strategy +10. Contributing +11. License [![Build and Publish Dev Container](https://github.com/smartdatafoundry/devcontainer/actions/workflows/build-devcontainer.yml/badge.svg)](https://github.com/smartdatafoundry/devcontainer/actions/workflows/build-devcontainer.yml) ## πŸ“¦ Published Container -This dev container is automatically built and published to GitHub Container Registry with multiple tags: +Built and published automatically to GitHub Container Registry (GHCR): -- **Registry**: GitHub Container Registry (GHCR) -- **Base Image**: `ghcr.io/smartdatafoundry/devcontainer` -- **Available Tags**: - - `latest` - Latest stable build from main branch - - `main` - Latest build from main branch - - `main-` - Specific commit builds from main branch - - `pr-` - Pull request builds for testing - - `vscode-` - Builds with specific VS Code versions - - `vscode--` - Combination of VS Code and git commit +* **Registry**: `ghcr.io` +* **Image**: `ghcr.io/smartdatafoundry/devcontainer` +* **Tag Families**: + * `latest` – Most recent stable main build + * `main` – Moving pointer to HEAD of main + * `main-` – Immutable build for a specific main commit + * `pr-` – Ephemeral preview for a pull request + * `vscode-` – Locks VS Code Server version (container content may still move) + * `vscode--` – Fully reproducible (VS Code Server + container commit) -**Recommended**: Use `latest` for stable deployments or `main-` for reproducible builds. +Recommended: +* Daily development: `latest` +* CI / Reproducibility: `vscode--` +* VS Code Server pin only: `vscode-` ## πŸš€ Quick Start @@ -39,15 +55,11 @@ Add this to your `.devcontainer/devcontainer.json`: ### Using in SDF Trusted Research Environment -For detailed instructions on setting up and using this dev container within the SDF Trusted Research Environment, see: - -**[πŸ“‹ SDF TRE Setup Guide](SDF_TRE_SETUP.md)** - -This includes: -- Manual Dev Containers extension installation -- TRE-specific configuration requirements -- Proxy and network setup -- Troubleshooting TRE-specific issues +See the **[SDF TRE Setup Guide](SDF_TRE_SETUP.md)** for: +* Manual Dev Containers extension install & extraction +* Podman configuration +* Proxy / network specifics +* Troubleshooting in constrained environments ### Using This Repository Directly @@ -57,10 +69,12 @@ This includes: ## πŸ“š Documentation -- [SDF TRE Setup Guide](SDF_TRE_SETUP.md) - Complete setup guide for SDF Trusted Research Environment -- [Dev Container Details](DEVCONTAINER.md) - Complete documentation about the container -- [Usage Examples](examples/USAGE.md) - Examples of how to use the published container -- [Dev Container Spec](https://containers.dev) - Learn more about dev containers +| Topic | Reference | +|-------|-----------| +| SDF TRE usage | `SDF_TRE_SETUP.md` | +| Full container internals | `DEVCONTAINER.md` | +| Reusable publish workflow | `docs/BUILD_PUBLISH_CONTAINER.md` | +| Dev Container Specification | https://containers.dev | ## πŸ› οΈ What's Included @@ -71,13 +85,14 @@ This includes: - **Shell**: Zsh with Oh My Zsh (via common-utils feature) - **Quarto**: Document publishing platform (latest version) - **Marimo**: Markdown presentation tool, alternative to Jupyter Notebooks -- **VS Code Extensions**: - - Continue (AI coding assistant) - - Python Black formatter - - Jupyter notebook support +- **VS Code Extensions (curated)**: + - Continue (AI assistant) + - Black (Python formatting) + - Jupyter - Marimo - Markdown All in One - Rainbow CSV + - (See `.devcontainer/vscode-init/extensions-to-install.txt` for authoritative list) - **VS Code Server**: Pre-installed for immediate development ## πŸ“Š R Language Support @@ -97,28 +112,50 @@ This dev container includes comprehensive R language support through the [Rocker ## βš™οΈ VS Code Server -The container comes with VS Code Server pre-installed for immediate development. For TRE-specific VS Code Server configuration, see the [SDF TRE Setup Guide](SDF_TRE_SETUP.md). +Pre-installed. Pin a version using the tag families described above or via build arg `VSCODE_COMMIT`. For environment-specific considerations (e.g. TRE) see `SDF_TRE_SETUP.md`. ## Adding New Extensions To add new VS Code extensions to the container, follow these steps: -1. Open the `.devcontainer/vscode-init/vscode-extensions.txt` file. +1. Open the appropriate file in `.devcontainer/vscode-init/`: + - `extensions-to-install.txt` for extensions to install directly + - `extensions-to-download.txt` for extensions that need to be downloaded 2. Add the identifier of the desired extension in the format `publisher.extensionName` on a new line. -3. Save the changes to the `vscode-extensions.txt` file. +3. Save the changes to the extension file. 4. Commit and push the changes to your repository to trigger the build workflow with the updated extensions -## πŸ”„ Automated Builds +## πŸ”„ Automated Builds & Tag Strategy + +Workflow: `.github/workflows/build-devcontainer.yml` + +Triggers: +* Pull Requests touching devcontainer/workflow files β†’ build + `pr-` tag +* Manual dispatch (with required `vscode_commit` input) β†’ publish full tag set + +Outputs per production run: +* `latest`, `main`, `main-` +* `vscode-`, `vscode--` + +Manual build steps: +1. Open Actions β†’ Build and Publish Dev Container +2. Run workflow, supplying VS Code Server commit hash +3. Await completion & verify tags on GHCR package page + +Tag usage quick reference: +| Need | Tag | +|------|-----| +| Stable rolling | `latest` | +| Immutable main snapshot | `main-` | +| Test PR | `pr-` | +| Pin VS Code Server only | `vscode-` | +| Full reproducibility | `vscode--` | + +Reusable generic Docker workflow documentation: see `docs/BUILD_PUBLISH_CONTAINER.md`. + +--- +## 🀝 Contributing & License -The container is built automatically with smart tagging: +Contribution workflow is standard GitHub Flow. See section above plus open issues for opportunities. -- **Main Branch Pushes**: Creates `latest`, `main`, and `main-` tags -- **Pull Requests**: Creates `pr-` tags for testing -- **VS Code Commits**: Creates `vscode-` and `vscode--` tags -- **Manual Dispatch**: Available for on-demand builds -- **Platform**: linux/amd64 optimized for development speed +License: [MIT](LICENSE) -### Tag Strategy -- Use `latest` for the most recent stable release -- Use `main-` when you need reproducible builds -- Use `pr-` tags to test specific pull request changes -- Use `vscode-` tags to match specific VS Code versions -- Use `vscode--` tags for a combination of VS Code and git commits +--- diff --git a/SDF_TRE_SETUP.md b/SDF_TRE_SETUP.md index 7033482..4dbee9c 100644 --- a/SDF_TRE_SETUP.md +++ b/SDF_TRE_SETUP.md @@ -6,8 +6,8 @@ This guide provides step-by-step instructions for setting up and using dev conta The quick start is for users familiar with the TRE and using Dev Containers. If you haven't done this setup before, please read the rest of this document instead of the quick start. -1. Pull the `devcontainer image` -2. Install the Dev Containers extension +1. Pull the devcontainer image +2. Extract and install the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) 3. Create your project directory 4. Add project config file `.devcontainer/devcontainer.json` 5. Open the project in VS Code @@ -45,7 +45,7 @@ ces-pull a a ghcr.io/smartdatafoundry/devcontainer:latest ### 2. Extract the Dev Containers Extension -The extension is baked into the container image. Extract it using: +The Dev Containers extension VSIX is baked into the image for offline / restricted environments. Extract it: ```bash podman run --rm -it \ @@ -144,23 +144,10 @@ This approach leverages container technology directly while maintaining the abil ### VS Code Server Version Management -The container comes with VS Code Server pre-installed and to control the version to match your TRE environment, you can specify the commit hash of the VS Code Server version to use as follows: +The container ships with VS Code Server pre-installed. To ensure reproducibility or to match an existing TRE host version, specify the commit hash: 1. Check your TRE VS Code version via _Help > About_ -2. Specify the VS Code commit in this repository's `devcontainer.json` file which is used for building the container, not to be confused with TRE workspace settings: - - ```json - { - "build": { - "dockerfile": "Dockerfile", - "args": { - "VSCODE_COMMIT": "your_commit_hash_here" - } - } - } - ``` - -3. This is typically only needed for custom container builds, not when using the published container +2. The VS Code commit value is declared in the `Dockerfile` and can be overriden via workflow inputs. ## Troubleshooting diff --git a/docs/BUILD_PUBLISH_CONTAINER.md b/docs/BUILD_PUBLISH_CONTAINER.md index 5cbe51d..dc6583d 100644 --- a/docs/BUILD_PUBLISH_CONTAINER.md +++ b/docs/BUILD_PUBLISH_CONTAINER.md @@ -22,7 +22,7 @@ on: jobs: publish: - uses: smartdatafoundry/devcontainer/.github/workflows/build-publish-container.yml@v1.0.0 + uses: smartdatafoundry/devcontainer/.github/workflows/build-publish-container.yml@v1.0.0 with: dockerfile: Dockerfile # Optional, defaults to 'Dockerfile' image-name: ${{ github.repository }} # Optional, defaults to repo name @@ -91,10 +91,11 @@ For further help, consult the GitHub Actions documentation or reach out to your | Use Case | Recommended Tag | Example | Benefits | |----------|----------------|---------|----------| | **Development** | `latest` | `ghcr.io/smartdatafoundry/devcontainer:latest` | Always up-to-date, stable | -| **Production/CI** | `main-` | `ghcr.io/smartdatafoundry/devcontainer:main-abc1234` | Reproducible, immutable | +| **Production/CI** | `vscode--` | `ghcr.io/smartdatafoundry/devcontainer:vscode-f220831-abc1234` | Reproducible, immutable, specific VS Code Server + container commit | +| **VS Code Version Match** | `vscode-` | `ghcr.io/smartdatafoundry/devcontainer:vscode-f220831` | Match specific VS Code Server version | | **Testing PRs** | `pr-` | `ghcr.io/smartdatafoundry/devcontainer:pr-42` | Test specific changes | | **Latest Main** | `main` | `ghcr.io/smartdatafoundry/devcontainer:main` | Latest main branch | ### Finding Available Tags -Visit the [GitHub Container Registry page](https://github.com/smartdatafoundry/devcontainer/pkgs/container/devcontainer) to see all available tags and their creation dates. +Visit the [GitHub Container Registry page](https://github.com/smartdatafoundry/devcontainer/pkgs/container/devcontainer) to see available tags and creation dates. See also high-level tag usage guidance in the top-level `README.md`.