From 69d2b197b5150c90f786538a8cf239c938a797d9 Mon Sep 17 00:00:00 2001 From: Thomas Nieto <38873752+ThomasNieto@users.noreply.github.com> Date: Tue, 4 Aug 2026 00:40:22 -0500 Subject: [PATCH 1/2] Add DSC feature --- .devcontainer/devcontainer-lock.json | 9 ++ .devcontainer/devcontainer.json | 24 +++++ .github/workflows/release.yaml | 47 +++++++++ .github/workflows/test.yaml | 56 ++++++++++ .github/workflows/validate.yml | 16 +++ README.md | 53 +++++++++- src/dsc/README.md | 40 ++++++++ src/dsc/devcontainer-feature.json | 42 ++++++++ src/dsc/install.sh | 146 +++++++++++++++++++++++++++ test/dsc/scenarios.json | 48 +++++++++ test/dsc/test.sh | 15 +++ 11 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/devcontainer-lock.json create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/test.yaml create mode 100644 .github/workflows/validate.yml create mode 100644 src/dsc/README.md create mode 100644 src/dsc/devcontainer-feature.json create mode 100644 src/dsc/install.sh create mode 100644 test/dsc/scenarios.json create mode 100644 test/dsc/test.sh diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 0000000..5c99099 --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "2.17.0", + "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c", + "integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c" + } + } +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e810240 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,24 @@ +{ + "image": "mcr.microsoft.com/devcontainers/javascript-node:3-22", + "customizations": { + "vscode": { + "settings": { + "json.schemas": [ + { + "fileMatch": [ + "*/devcontainer-feature.json" + ], + "url": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainerFeature.schema.json" + } + ] + }, + "extensions": [ + "mads-hartmann.bash-ide-vscode" + ] + } + }, + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "postCreateCommand": "npm install -g @devcontainers/cli" +} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..0a84481 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,47 @@ +name: "Release dev container features & Generate Documentation" +on: + workflow_dispatch: + +jobs: + deploy: + if: ${{ github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + packages: write + steps: + - uses: actions/checkout@v7 + + - name: "Publish Features" + uses: devcontainers/action@v1 + with: + publish-features: "true" + base-path-to-features: "./src" + generate-docs: "true" + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create PR for Documentation + id: push_image_info + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -e + echo "Start." + # Configure git and Push updates + git config --global user.email github-actions[bot]@users.noreply.github.com + git config --global user.name github-actions[bot] + git config pull.rebase false + branch=automated-documentation-update-$GITHUB_RUN_ID + git checkout -b $branch + message='Automated documentation update' + # Add / update and commit + git add */**/README.md + git commit -m 'Automated documentation update [skip ci]' || export NO_UPDATES=true + # Push + if [ "$NO_UPDATES" != "true" ] ; then + git push origin "$branch" + gh pr create --title "$message" --body "$message" + fi diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..598c2ae --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,56 @@ +name: "CI - Test Features" +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + test-autogenerated: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + features: + - dsc + baseImage: + - debian:latest + - ubuntu:latest + - mcr.microsoft.com/devcontainers/base:ubuntu + steps: + - uses: actions/checkout@v7 + + - name: "Install latest devcontainer CLI" + run: npm install -g @devcontainers/cli + + - name: "Generating tests for '${{ matrix.features }}' against '${{ matrix.baseImage }}'" + run: devcontainer features test --skip-scenarios -f ${{ matrix.features }} -i ${{ matrix.baseImage }} . + + test-scenarios: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + features: + - dsc + steps: + - uses: actions/checkout@v7 + + - name: "Install latest devcontainer CLI" + run: npm install -g @devcontainers/cli + + - name: "Generating tests for '${{ matrix.features }}' scenarios" + run: devcontainer features test -f ${{ matrix.features }} --skip-autogenerated --skip-duplicated . + + test-global: + runs-on: ubuntu-latest + continue-on-error: true + steps: + - uses: actions/checkout@v7 + + - name: "Install latest devcontainer CLI" + run: npm install -g @devcontainers/cli + + - name: "Testing global scenarios" + run: devcontainer features test --global-scenarios-only . diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..5b24dfb --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,16 @@ +name: "Validate devcontainer-feature.json files" +on: + workflow_dispatch: + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: "Validate devcontainer-feature.json files" + uses: devcontainers/action@v1 + with: + validate-only: "true" + base-path-to-features: "./src" diff --git a/README.md b/README.md index 24a88c3..3b1421d 100644 --- a/README.md +++ b/README.md @@ -1 +1,52 @@ -# devcontainer-featuers \ No newline at end of file +# devcontainer-features + +A collection of dev container features for development environments. This repository maintains reusable features that can be integrated into dev containers for enhanced development tooling. + +## Features + +### Microsoft Desired State Configuration (DSC) + +Installs Microsoft Desired State Configuration (DSC) v3, a cross-platform, open-source configuration management tool. + +**Location:** [`src/dsc/`](src/dsc/) + +**Features:** +- Cross-platform support (Windows, macOS, Linux) +- Schema-driven configuration management +- Written in Rust (no PowerShell dependency required) +- 30+ built-in resources for managing system configuration + +**Supported Versions:** +- `latest` (default) - Latest stable release +- `preview` - Latest preview release +- `3.2.3`, `3.2.2`, `3.2.1`, `3.2.0` - Specific versions +- `none` - Skip installation + +**Example Usage:** +```json +{ + "features": { + "ghcr.io/PowerShell/devcontainer-features/dsc:1": { + "version": "latest" + } + } +} +``` + +For more details, see the [DSC Feature README](src/dsc/README.md). + +## Testing + +Each feature includes test scenarios to validate functionality: + +```bash +npm install -g @devcontainers/cli +devcontainer features test -f dsc . +``` + +See [`test/dsc/scenarios.json`](test/dsc/scenarios.json) for available test scenarios. + +## License + +MIT License - See [LICENSE](LICENSE) for details. + diff --git a/src/dsc/README.md b/src/dsc/README.md new file mode 100644 index 0000000..0841191 --- /dev/null +++ b/src/dsc/README.md @@ -0,0 +1,40 @@ + +# Microsoft Desired State Configuration (DSC) v3 (dsc) + +Installs Microsoft Desired State Configuration (DSC) v3, a cross-platform, open-source configuration management tool. DSC v3 enables you to manage your infrastructure using configuration as code. + +## Example Usage + +```json +"features": { + "ghcr.io/PowerShell/devcontainer-features/dsc:1": {} +} +``` + +## Options + +| Options Id | Description | Type | Default Value | +|-----|-----|-----|-----| +| version | Select or enter a version of Microsoft DSC to install. Use 'latest' for the latest version, 'none' to skip DSC installation. | string | latest | + +## About Microsoft DSC v3 + +[Microsoft Desired State Configuration (DSC)](https://github.com/PowerShell/DSC) is a cross-platform, open-source configuration management tool. Unlike PowerShell DSC, DSC v3 is a schema-driven, configuration management platform written in Rust and is not dependent on PowerShell (though it can be used with PowerShell). + +With DSC, you can: + +- Manage infrastructure using declarative configuration files (YAML/JSON) +- Define desired states for system configurations +- Apply and maintain consistent configurations across your infrastructure +- Test and validate configurations before deployment +- Use DSC across Windows, macOS, and Linux + +## OS Support + +This Feature should work on recent versions of Debian/Ubuntu-based and RHEL-based distributions with the appropriate package manager installed. + +`bash` and `curl` are required to execute the `install.sh` script. + +--- + +_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/devcontainers/features/blob/main/src/dsc/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ diff --git a/src/dsc/devcontainer-feature.json b/src/dsc/devcontainer-feature.json new file mode 100644 index 0000000..51878f8 --- /dev/null +++ b/src/dsc/devcontainer-feature.json @@ -0,0 +1,42 @@ +{ + "id": "dsc", + "version": "1.0.0", + "name": "Microsoft Desired State Configuration (DSC)", + "documentationURL": "https://github.com/PowerShell/devcontainer-features/tree/main/src/dsc", + "description": "Installs Microsoft Desired State Configuration (DSC), a cross-platform, open-source configuration management tool. DSC enables you to manage your infrastructure using configuration as code.", + "options": { + "version": { + "type": "string", + "proposals": [ + "latest", + "preview", + "3.2.3", + "3.2.2", + "3.2.1", + "3.2.0", + "3.1.1", + "3.1.0", + "3.0.2", + "3.0.1", + "3.0.0", + "none" + ], + "default": "latest", + "description": "Select or enter a version of Microsoft DSC to install. Use 'latest' for the latest stable version, 'preview' for the latest preview release, 'none' to skip DSC installation." + } + }, + "customizations": { + "vscode": { + "settings": { + "github.copilot.chat.codeGeneration.instructions": [ + { + "text": "This dev container includes Microsoft DSC (Desired State Configuration) pre-installed and available on the `PATH` for configuration management and infrastructure as code." + } + ] + } + } + }, + "installsAfter": [ + "ghcr.io/devcontainers/features/common-utils" + ] +} diff --git a/src/dsc/install.sh b/src/dsc/install.sh new file mode 100644 index 0000000..4a33a10 --- /dev/null +++ b/src/dsc/install.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +# Docs: https://github.com/devcontainers/features/tree/main/src/dsc +# Maintainer: The VS Code and Codespaces Teams + +set -e + +DSC_VERSION=${VERSION:-"latest"} +DSC_INSTALL_PATH="/opt/dsc" + +if [ "$(id -u)" -ne 0 ]; then + echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +# Setup STDERR +err() { + echo "(!) $*" >&2 +} + +# Function to get the latest DSC release version +get_latest_dsc_version() { + # Query GitHub API for the latest release (stable only) + curl -s https://api.github.com/repos/PowerShell/DSC/releases/latest | grep -oP '"tag_name":\s*"\K[^"]*' | head -1 || echo "" +} + +# Function to get the latest DSC preview version +get_latest_dsc_preview_version() { + # Query GitHub API for releases and filter for pre-releases only + curl -s https://api.github.com/repos/PowerShell/DSC/releases | \ + python3 -c "import sys, json; data = json.load(sys.stdin); [print(r['tag_name']) for r in data if r.get('prerelease', False)]" | head -1 || echo "" +} + +# Function to get the appropriate DSC binary URL +get_dsc_binary_url() { + local version=$1 + local arch="" + + # Detect architecture + case "$(uname -m)" in + x86_64|amd64) + arch="x86_64" + ;; + aarch64|arm64) + arch="aarch64" + ;; + *) + err "Unsupported architecture: $(uname -m)" + return 1 + ;; + esac + + echo "https://github.com/PowerShell/DSC/releases/download/${version}/DSC-${version#v}-${arch}-linux.tar.gz" +} + +# Function to install DSC +install_dsc() { + local dsc_version=$1 + + if [ "${dsc_version}" = "none" ]; then + echo "Skipping DSC installation" + return 0 + fi + + echo "Installing Microsoft DSC v3..." + + # Determine the version to install + local install_version="${dsc_version}" + if [ "${dsc_version}" = "latest" ]; then + install_version=$(get_latest_dsc_version) + if [ -z "${install_version}" ]; then + err "Failed to determine latest DSC version" + return 1 + fi + elif [ "${dsc_version}" = "preview" ]; then + install_version=$(get_latest_dsc_preview_version) + if [ -z "${install_version}" ]; then + err "Failed to determine latest DSC preview version" + return 1 + fi + fi + + # Ensure version starts with 'v' + if [[ ! "${install_version}" =~ ^v ]]; then + install_version="v${install_version}" + fi + + # Get the download URL + local download_url=$(get_dsc_binary_url "${install_version}") + + echo "Downloading DSC ${install_version}..." + local temp_dir + temp_dir=$(mktemp -d) + cd "${temp_dir}" + + if ! curl -sSL "${download_url}" -o dsc.tar.gz; then + err "Failed to download DSC from ${download_url}" + rm -rf "${temp_dir}" + return 1 + fi + + # Extract to permanent location + echo "Extracting DSC to ${DSC_INSTALL_PATH}..." + mkdir -p "${DSC_INSTALL_PATH}" + tar -xzf dsc.tar.gz -C "${DSC_INSTALL_PATH}" --strip-components=1 + + # Cleanup temp directory + cd / + rm -rf "${temp_dir}" + + echo "DSC installation complete" +} + +echo "Installing Microsoft DSC v3..." + +# Install DSC +if [ "${DSC_VERSION}" != "none" ]; then + install_dsc "${DSC_VERSION}" +fi + +# Add DSC to PATH for all users +echo "Configuring DSC PATH..." +export PATH="${DSC_INSTALL_PATH}:$PATH" +cat > /etc/profile.d/dsc.sh << 'EOF' +export PATH="/opt/dsc:$PATH" +EOF +chmod +x /etc/profile.d/dsc.sh + +# Verify installation +echo "Verifying DSC installation..." +if ! dsc --version > /dev/null 2>&1; then + err "DSC installation verification failed - binary not found in PATH" + exit 1 +fi + +echo "Verifying DSC can load resources..." +if ! dsc resource list > /dev/null 2>&1; then + err "DSC installation verification failed - cannot load resources" + exit 1 +fi + +echo "Microsoft DSC v3 feature installation complete!" diff --git a/test/dsc/scenarios.json b/test/dsc/scenarios.json new file mode 100644 index 0000000..434281e --- /dev/null +++ b/test/dsc/scenarios.json @@ -0,0 +1,48 @@ +{ + "dsc_latest": { + "image": "ubuntu:noble", + "features": { + "dsc": {} + } + }, + "dsc_preview": { + "image": "ubuntu:noble", + "features": { + "dsc": { + "version": "preview" + } + } + }, + "dsc_specific_stable_3_2_2": { + "image": "ubuntu:noble", + "features": { + "dsc": { + "version": "3.2.2" + } + } + }, + "dsc_specific_stable_3_1_0": { + "image": "ubuntu:noble", + "features": { + "dsc": { + "version": "3.1.0" + } + } + }, + "dsc_specific_prerelease_3_3_0_preview_1": { + "image": "ubuntu:noble", + "features": { + "dsc": { + "version": "3.3.0-preview.1" + } + } + }, + "dsc_none": { + "image": "ubuntu:noble", + "features": { + "dsc": { + "version": "none" + } + } + } +} diff --git a/test/dsc/test.sh b/test/dsc/test.sh new file mode 100644 index 0000000..275c78e --- /dev/null +++ b/test/dsc/test.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +set -e + +# Optional: Import test library +source dev-container-features-test-lib + +# Check DSC installation +check "dsc version" dsc --version + +# Check DSC is in PATH +check "dsc is in PATH" bash -c "which dsc" + +# Report result +reportResults From 3faef22d81a11434bd0e8c38117a1348643e18c7 Mon Sep 17 00:00:00 2001 From: Thomas Nieto <38873752+ThomasNieto@users.noreply.github.com> Date: Tue, 4 Aug 2026 09:10:33 -0500 Subject: [PATCH 2/2] Remove v3 notation --- README.md | 2 +- src/dsc/README.md | 8 ++++---- src/dsc/install.sh | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3b1421d..0b4c342 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of dev container features for development environments. This reposi ### Microsoft Desired State Configuration (DSC) -Installs Microsoft Desired State Configuration (DSC) v3, a cross-platform, open-source configuration management tool. +Installs Microsoft Desired State Configuration (DSC), a cross-platform, open-source configuration management tool. **Location:** [`src/dsc/`](src/dsc/) diff --git a/src/dsc/README.md b/src/dsc/README.md index 0841191..3008ac4 100644 --- a/src/dsc/README.md +++ b/src/dsc/README.md @@ -1,7 +1,7 @@ -# Microsoft Desired State Configuration (DSC) v3 (dsc) +# Microsoft Desired State Configuration (DSC) -Installs Microsoft Desired State Configuration (DSC) v3, a cross-platform, open-source configuration management tool. DSC v3 enables you to manage your infrastructure using configuration as code. +Installs Microsoft Desired State Configuration (DSC), a cross-platform, open-source configuration management tool. DSC enables you to manage your infrastructure using configuration as code. ## Example Usage @@ -17,9 +17,9 @@ Installs Microsoft Desired State Configuration (DSC) v3, a cross-platform, open- |-----|-----|-----|-----| | version | Select or enter a version of Microsoft DSC to install. Use 'latest' for the latest version, 'none' to skip DSC installation. | string | latest | -## About Microsoft DSC v3 +## About Microsoft DSC -[Microsoft Desired State Configuration (DSC)](https://github.com/PowerShell/DSC) is a cross-platform, open-source configuration management tool. Unlike PowerShell DSC, DSC v3 is a schema-driven, configuration management platform written in Rust and is not dependent on PowerShell (though it can be used with PowerShell). +[Microsoft Desired State Configuration (DSC)](https://github.com/PowerShell/DSC) is a cross-platform, open-source configuration management tool. Unlike PowerShell DSC, Microsoft DSC is a schema-driven, configuration management platform written in Rust and is not dependent on PowerShell (though it can be used with PowerShell). With DSC, you can: diff --git a/src/dsc/install.sh b/src/dsc/install.sh index 4a33a10..55b6a8a 100644 --- a/src/dsc/install.sh +++ b/src/dsc/install.sh @@ -66,7 +66,7 @@ install_dsc() { return 0 fi - echo "Installing Microsoft DSC v3..." + echo "Installing Microsoft DSC..." # Determine the version to install local install_version="${dsc_version}" @@ -115,7 +115,7 @@ install_dsc() { echo "DSC installation complete" } -echo "Installing Microsoft DSC v3..." +echo "Installing Microsoft DSC..." # Install DSC if [ "${DSC_VERSION}" != "none" ]; then @@ -143,4 +143,4 @@ if ! dsc resource list > /dev/null 2>&1; then exit 1 fi -echo "Microsoft DSC v3 feature installation complete!" +echo "Microsoft DSC feature installation complete!"