Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .forgejo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Forgejo Actions Placeholder

This directory exists to prevent Forgejo from falling back to GitHub Actions workflows.

## Why is this directory empty?

This project uses **Woodpecker CI** (configured in `.woodpecker.yml`), not Forgejo Actions.

When Forgejo detects this directory, it will **not** attempt to use any GitHub Actions workflows that might exist in `.github/workflows/`. Without this directory, Forgejo would try to execute GitHub Actions as a fallback, which is not desired for this project.

## Note

- **DO NOT DELETE** this directory unless you want to enable GitHub Actions fallback behavior
- If you want to use Forgejo Actions in the future, place workflow files in `.forgejo/workflows/`
- Current CI system: Woodpecker CI (see `.woodpecker.yml`)
85 changes: 85 additions & 0 deletions .github/workflows/woodpecker-plugin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
name: Woodpecker Plugin - Build and Publish

on:
push:
branches: [main, feat/woodpecker-ci-plugin]
paths:
- 'woodpecker-plugin/**'
- 'common/**'
- '.github/workflows/woodpecker-plugin.yml'
pull_request:
paths:
- 'woodpecker-plugin/**'
- 'common/**'
- '.github/workflows/woodpecker-plugin.yml'
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
build-and-push:
name: Build and push Woodpecker plugin image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/devcontainer-build-run-woodpecker
tags: |
# Tag as 'latest' for pushes to main
type=raw,value=latest,enable={{is_default_branch}}
# Tag as 'pr-NUMBER' for pull requests
type=ref,event=pr,prefix=pr-
# Tag as branch name for other branches
type=ref,event=branch
# Tag as sha for commits
type=sha,prefix={{branch}}-

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
file: ./woodpecker-plugin/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Show image details
run: |
echo "## Woodpecker Plugin Image Published! 🎉" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image Tags:**" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Usage in Woodpecker CI:**" >> $GITHUB_STEP_SUMMARY
echo '```yaml' >> $GITHUB_STEP_SUMMARY
echo "steps:" >> $GITHUB_STEP_SUMMARY
echo " - name: build-devcontainer" >> $GITHUB_STEP_SUMMARY
echo " image: ghcr.io/${{ github.repository_owner }}/devcontainer-build-run-woodpecker:latest" >> $GITHUB_STEP_SUMMARY
echo " settings:" >> $GITHUB_STEP_SUMMARY
echo " sub_folder: .devcontainer" >> $GITHUB_STEP_SUMMARY
echo " image_name: my-devcontainer" >> $GITHUB_STEP_SUMMARY
echo " image_tag: latest" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
167 changes: 167 additions & 0 deletions .woodpecker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Woodpecker CI configuration for testing the woodpecker-plugin
# This config is only for testing purposes in local Woodpecker CI

when:
event: [push, pull_request, manual]

# YAML anchors for reusable configuration
variables:
- &dind_env
DOCKER_HOST: tcp://docker:2376
DOCKER_CERT_PATH: /dind-certs/client
DOCKER_TLS_VERIFY: "1"
- &dind_volumes
- dind-certs:/dind-certs

services:
- name: docker
image: docker:dind
privileged: true
environment:
DOCKER_TLS_CERTDIR: /dind-certs
commands: dockerd-entrypoint.sh --insecure-registry=registry:5000 --insecure-registry=localhost:5001
volumes:
- dind-certs:/dind-certs
- docker-cache:/var/lib/docker
ports:
- 2376

steps:
# Install all dependencies once (cached for subsequent steps)
- name: install-dependencies
image: node:24-alpine3.23
volumes:
- npm-cache:/root/.npm
commands:
- cd common && npm ci
- cd ../woodpecker-plugin && npm ci

# Check code formatting (reuses installed node_modules)
- name: format-check
image: node:24-alpine3.23
commands:
- cd woodpecker-plugin && npm run format-check
depends_on:
- install-dependencies

# Lint TypeScript code (reuses installed node_modules)
- name: lint
image: node:24-alpine3.23
commands:
- cd woodpecker-plugin && npm run lint
depends_on:
- install-dependencies

# Build TypeScript (reuses installed node_modules)
- name: build-typescript
image: node:24-alpine3.23
commands:
- cd common && npm run build
- cd ../woodpecker-plugin && npm run build
depends_on:
- format-check
- lint

# Run unit tests for env-parser (reuses installed node_modules)
- name: test-env-parser
image: node:24-alpine3.23
commands:
- cd woodpecker-plugin && npm test
depends_on:
- build-typescript

# Build the plugin Docker image (with BuildKit for better layer caching)
- name: build-plugin-image
image: docker:cli
environment:
<<: *dind_env
volumes: *dind_volumes
commands:
- DOCKER_BUILDKIT=1 docker build -f woodpecker-plugin/Dockerfile -t registry:5000/woodpecker-plugin:test .
- docker push registry:5000/woodpecker-plugin:test
depends_on:
- test-env-parser

# Test scenario 1: simple-node (image-based)
- name: test-simple-node-build
image: registry:5000/woodpecker-plugin:test
environment:
<<: *dind_env
PLUGIN_SUB_FOLDER: woodpecker-plugin-tests/simple-node
PLUGIN_IMAGE_NAME: test-simple-node
PLUGIN_IMAGE_TAG: test
volumes: *dind_volumes
depends_on:
- build-plugin-image

- name: test-simple-node-run
image: test-simple-node:test
commands:
- echo "Testing simple-node DevContainer!"
- node --version
- npm --version
depends_on:
- test-simple-node-build

- name: test-simple-node-run-cmd
image: registry:5000/woodpecker-plugin:test
environment:
<<: *dind_env
PLUGIN_SUB_FOLDER: woodpecker-plugin-tests/simple-node
PLUGIN_RUN_CMD: echo "run_cmd test!" && node --version
volumes: *dind_volumes
depends_on:
- test-simple-node-build

# Test scenario 2: with-dockerfile
- name: test-dockerfile-build
image: registry:5000/woodpecker-plugin:test
environment:
<<: *dind_env
PLUGIN_SUB_FOLDER: woodpecker-plugin-tests/with-dockerfile
PLUGIN_IMAGE_NAME: test-dockerfile
PLUGIN_IMAGE_TAG: test
volumes: *dind_volumes
depends_on:
- build-plugin-image

- name: test-dockerfile-run
image: test-dockerfile:test
commands:
- echo "Testing with-dockerfile DevContainer!"
- node --version
- git --version
depends_on:
- test-dockerfile-build

# Test scenario 3: with-features (features + build args)
- name: test-features-build
image: registry:5000/woodpecker-plugin:test
environment:
<<: *dind_env
PLUGIN_SUB_FOLDER: woodpecker-plugin-tests/with-features
PLUGIN_IMAGE_NAME: test-features
PLUGIN_IMAGE_TAG: test
volumes: *dind_volumes
depends_on:
- build-plugin-image

- name: test-features-run
image: test-features:test
commands:
- echo "Testing with-features DevContainer!"
- node --version
- git --version
- python3 --version
depends_on:
- test-features-build

- name: test-features-run-cmd
image: registry:5000/woodpecker-plugin:test
environment:
<<: *dind_env
PLUGIN_SUB_FOLDER: woodpecker-plugin-tests/with-features
PLUGIN_RUN_CMD: echo "Features run_cmd test!" && node --version && git --version && python3 --version
volumes: *dind_volumes
depends_on:
- test-features-build
47 changes: 47 additions & 0 deletions scripts/build-woodpecker-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/bash
set -e

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
repo_root="$script_dir/.."

# Default values
IMAGE_NAME="${IMAGE_NAME:-devcontainer-woodpecker}"
IMAGE_TAG="${IMAGE_TAG:-local}"
PLATFORMS="${PLATFORMS:-linux/amd64}"
PUSH="${PUSH:-false}"

echo "Building Woodpecker Plugin Docker Image"
echo "========================================"
echo "Image: ${IMAGE_NAME}:${IMAGE_TAG}"
echo "Platforms: ${PLATFORMS}"
echo "Push: ${PUSH}"
echo ""

cd "$repo_root"

if [ "$PUSH" = "true" ]; then
echo "Building and pushing multi-platform image..."
docker buildx build \
--platform "$PLATFORMS" \
-f woodpecker-plugin/Dockerfile \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
--push \
.
else
echo "Building image for local use..."
docker build \
-f woodpecker-plugin/Dockerfile \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
.
fi

echo ""
echo "==> Docker image built successfully!"
echo " Image: ${IMAGE_NAME}:${IMAGE_TAG}"
echo ""
echo "To test the image locally, run:"
echo " docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \\"
echo " -v \$(pwd):/workspace \\"
echo " -e PLUGIN_RUN_CMD='echo Hello from Dev Container' \\"
echo " -e CI_WORKSPACE=/workspace \\"
echo " ${IMAGE_NAME}:${IMAGE_TAG}"
21 changes: 21 additions & 0 deletions scripts/build-woodpecker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
set -e

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"

echo "Building Woodpecker Plugin..."
echo ""

echo "==> Building common"
cd "$script_dir/../common"
npm install
npm run build

echo ""
echo "==> Building woodpecker-plugin"
cd "$script_dir/../woodpecker-plugin"
npm install
npm run build

echo ""
echo "==> Woodpecker plugin build completed successfully!"
24 changes: 24 additions & 0 deletions woodpecker-plugin-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Woodpecker Plugin Tests

This directory contains integration test scenarios for the woodpecker-plugin.

## Test Scenarios

### `simple-node/`
Basic DevContainer using a pre-built image from Docker Hub.
- Tests: Image-based DevContainer, basic commands

### `with-dockerfile/`
DevContainer with a custom Dockerfile.
- Tests: Dockerfile-based builds, custom package installation

### `with-features/`
DevContainer with features and build arguments.
- Tests: Dockerfile with build args (VARIANT, WELCOME_MESSAGE), DevContainer features (git, python), postCreateCommand

## Running Tests

Tests are executed in the main `.woodpecker.yml` pipeline:
1. Plugin builds the DevContainer image for each scenario
2. Commands are executed inside the built DevContainer
3. Results verify plugin functionality
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "Woodpecker Plugin Test",
"image": "mcr.microsoft.com/devcontainers/javascript-node:20",
"features": {},
"customizations": {
"vscode": {
"extensions": []
}
},
"postCreateCommand": "echo 'DevContainer initialized successfully' && node --version && npm --version"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM node:20-alpine

RUN apk add --no-cache git

USER node
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "Node with Dockerfile",
"dockerFile": "Dockerfile",
"customizations": {
"vscode": {
"extensions": []
}
},
"postCreateCommand": "echo 'DevContainer with Dockerfile initialized!' && node --version && git --version"
}
Loading