mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-03-27 02:01:02 -04:00
feat(tools): unified container dev setup (#65589)
This commit is contained in:
committed by
GitHub
parent
b321f075fd
commit
46b607d84a
31
.devcontainer/README.md
Normal file
31
.devcontainer/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# To start developing:
|
||||
|
||||
Wait for the container to build and start. You will see "Done. Press any key to close the terminal." in the terminal when it's ready.
|
||||
|
||||
Once it's running, you can start the development server:
|
||||
|
||||
**Option 1:** Press `Ctrl+Shift+P`, type "Run Task", select "Start Development"
|
||||
**Option 2:** Open a terminal and run:
|
||||
|
||||
```bash
|
||||
pnpm run develop
|
||||
```
|
||||
|
||||
## Optional setup
|
||||
|
||||
For E2E tests:
|
||||
|
||||
```bash
|
||||
npx playwright install chromium
|
||||
```
|
||||
|
||||
For curriculum tests:
|
||||
|
||||
```bash
|
||||
pnpm -F=curriculum install-puppeteer
|
||||
```
|
||||
|
||||
## More information
|
||||
|
||||
For detailed setup instructions and contribution guidelines, visit:
|
||||
https://contribute.freecodecamp.org/how-to-setup-freecodecamp-locally
|
||||
@@ -1,8 +1,11 @@
|
||||
{
|
||||
"name": "freeCodeCampDC",
|
||||
"name": "freeCodeCamp",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "devcontainer",
|
||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||
"workspaceFolder": "/workspaces/freeCodeCamp",
|
||||
"mounts": [
|
||||
"source=fcc-node-modules,target=${containerWorkspaceFolder}/node_modules,type=volume"
|
||||
],
|
||||
"forwardPorts": [3000, 8000],
|
||||
"portsAttributes": {
|
||||
"3000": {
|
||||
@@ -17,9 +20,64 @@
|
||||
"otherPortsAttributes": {
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"onCreateCommand": "[ ! -f .env ] && cp sample.env .env || true",
|
||||
"updateContentCommand": "pnpm install && pnpm seed",
|
||||
"postAttachCommand": {
|
||||
"instructions": "bash -c 'echo \"\n\n\n Start a new terminal and run \\`pnpm run develop\\` when you are ready.\n\n\n\"'"
|
||||
"onCreateCommand": "sudo chown node:node node_modules && ([ ! -f .env ] && cp sample.env .env || true)",
|
||||
"updateContentCommand": "pnpm install --prefer-offline",
|
||||
"postCreateCommand": "rsync -a --include='*/' --include='.turbo/***' --exclude='*' /home/node/.cache/fcc/ ./ && set -a && . ./.env && set +a && until mongosh --eval 'rs.status().ok' 2>/dev/null; do sleep 1; done && pnpm seed",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
],
|
||||
"settings": {
|
||||
"task.allowAutomaticTasks": "on",
|
||||
"tasks": {
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Start API Server",
|
||||
"type": "shell",
|
||||
"command": "pnpm run develop:api",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
"group": "develop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Start Client Server",
|
||||
"type": "shell",
|
||||
"command": "pnpm run develop:client",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "dedicated",
|
||||
"group": "develop"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Start Development",
|
||||
"dependsOn": ["Start API Server", "Start Client Server"],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Open README",
|
||||
"type": "shell",
|
||||
"command": "code .devcontainer/README.md",
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"close": true
|
||||
},
|
||||
"runOptions": {
|
||||
"runOn": "folderOpen"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
services:
|
||||
devcontainer:
|
||||
image: ghcr.io/freecodecamp/devcontainer:latest
|
||||
depends_on:
|
||||
- db
|
||||
- setup
|
||||
image: mcr.microsoft.com/devcontainers/typescript-node:22
|
||||
volumes:
|
||||
- ../..:/workspaces:cached
|
||||
- ..:/workspaces/freeCodeCamp:cached
|
||||
network_mode: service:db
|
||||
command: sleep infinity
|
||||
|
||||
db:
|
||||
image: mongo:8.0
|
||||
container_name: mongodb
|
||||
command: mongod --replSet rs0
|
||||
restart: unless-stopped
|
||||
hostname: mongodb
|
||||
@@ -21,27 +20,20 @@ services:
|
||||
test: ['CMD', 'mongosh', '--eval', "db.adminCommand('ping')"]
|
||||
interval: 2s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
setup:
|
||||
image: mongo:8.0
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: on-failure
|
||||
# This will try to initiate the replica set, until it succeeds twice (i.e. until the replica set is already initialized)
|
||||
restart: on-failure:5
|
||||
command: >
|
||||
mongosh --host mongodb:27017 --eval '
|
||||
var cfg = {
|
||||
rs.initiate({
|
||||
_id: "rs0",
|
||||
members: [
|
||||
{ _id: 0, host: "mongodb:27017" }
|
||||
]
|
||||
};
|
||||
try {
|
||||
rs.initiate(cfg);
|
||||
} catch (err) {
|
||||
if(err.codeName !== "AlreadyInitialized") throw err;
|
||||
}
|
||||
members: [{ _id: 0, host: "mongodb:27017" }]
|
||||
}).ok || rs.status().ok
|
||||
'
|
||||
|
||||
volumes:
|
||||
|
||||
63
.github/workflows/devcontainer-ci.yml
vendored
Normal file
63
.github/workflows/devcontainer-ci.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: CI - Devcontainer
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.devcontainer/**'
|
||||
- 'docker/devcontainer/**'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: Validate
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install devcontainer CLI
|
||||
# renovate: datasource=npm depName=@devcontainers/cli
|
||||
run: npm install -g @devcontainers/cli@0.83.0
|
||||
|
||||
- name: Build devcontainer
|
||||
run: devcontainer build --workspace-folder .
|
||||
|
||||
- name: Start devcontainer
|
||||
run: devcontainer up --workspace-folder .
|
||||
|
||||
- name: Validate required tools
|
||||
run: |
|
||||
devcontainer exec --workspace-folder . pnpm --version
|
||||
devcontainer exec --workspace-folder . rsync --version
|
||||
devcontainer exec --workspace-folder . mongosh --version
|
||||
devcontainer exec --workspace-folder . node --version
|
||||
devcontainer exec --workspace-folder . git --version
|
||||
|
||||
- name: Validate MongoDB replica set
|
||||
run: |
|
||||
for i in $(seq 1 30); do
|
||||
if devcontainer exec --workspace-folder . mongosh --eval "rs.status().ok" 2>/dev/null; then
|
||||
echo "Replica set is ready"
|
||||
exit 0
|
||||
fi
|
||||
echo "Waiting for replica set... (attempt $i/30)"
|
||||
sleep 2
|
||||
done
|
||||
echo "Replica set failed to initialize"
|
||||
exit 1
|
||||
59
.github/workflows/docker-ghcr.yml
vendored
59
.github/workflows/docker-ghcr.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: CD - Docker - GHCR (Gitpod)
|
||||
name: CD - Docker - GHCR Images
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -6,55 +6,44 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'docker/gitpod/*'
|
||||
- 'pnpm-lock.yaml'
|
||||
- 'docker/devcontainer/**'
|
||||
- '.github/workflows/docker-ghcr.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
build-and-push:
|
||||
name: Build and Push Images
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
images:
|
||||
- gitpod
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
|
||||
|
||||
- name: Log in to the GHCR
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Cache Docker layers
|
||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||
- name: Build and push images
|
||||
uses: docker/bake-action@5be5f02ff8819ecd3092ea6b2e6261c31774f2b4 # v6
|
||||
with:
|
||||
path: /tmp/.buildx-cache
|
||||
key: ${{ runner.os }}-buildx-${{ matrix.images }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-buildx-${{ matrix.images }}-
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
||||
with:
|
||||
context: ./docker/${{ matrix.images }}
|
||||
files: docker/devcontainer/docker-bake.hcl
|
||||
targets: devcontainer
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/freecodecamp/${{ matrix.images }}:${{ github.sha }}
|
||||
ghcr.io/freecodecamp/${{ matrix.images }}:latest
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||
|
||||
- name: Move cache
|
||||
run: |
|
||||
rm -rf /tmp/.buildx-cache
|
||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||
env:
|
||||
TAG: ${{ github.sha }}
|
||||
TAG_LATEST: ${{ github.ref_name == 'main' }}
|
||||
|
||||
78
.gitpod.yml
78
.gitpod.yml
@@ -1,78 +0,0 @@
|
||||
image: ghcr.io/freecodecamp/gitpod:latest
|
||||
ports:
|
||||
- port: 27017 # mongodb
|
||||
onOpen: ignore
|
||||
- port: 8000 # client
|
||||
onOpen: notify
|
||||
visibility: public
|
||||
- port: 9228 # node debug
|
||||
onOpen: ignore
|
||||
- port: 3000 # api
|
||||
onOpen: ignore
|
||||
visibility: public
|
||||
- port: 9229 # node debug
|
||||
onOpen: ignore
|
||||
- port: 9230 # client node debug
|
||||
onOpen: ignore
|
||||
- port: 3200 # challenge editor api
|
||||
visibility: public
|
||||
- port: 3300 # challenge editor client
|
||||
visibility: public
|
||||
- port: 8025 # Mailpit
|
||||
visibility: public
|
||||
onOpen: ignore
|
||||
- port: 1025 # Mailpit
|
||||
onOpen: ignore
|
||||
- port: 9323 # Playwright
|
||||
visibility: public
|
||||
onOpen: ignore
|
||||
|
||||
tasks:
|
||||
- before: |
|
||||
echo '
|
||||
export COOKIE_DOMAIN=.gitpod.io
|
||||
export HOME_LOCATION=$(gp url 8000)
|
||||
export API_LOCATION=$(gp url 3000)
|
||||
export CHALLENGE_EDITOR_API_LOCATION=$(gp url 3200)
|
||||
export CHALLENGE_EDITOR_CLIENT_LOCATION=$(gp url 3300)
|
||||
export CHALLENGE_EDITOR_LEARN_CLIENT_LOCATION=$(gp url 8000)
|
||||
' >> ~/.bashrc;
|
||||
exit;
|
||||
|
||||
- name: db
|
||||
# starting mongod in background, so it doesn't block prebuilds
|
||||
before: >
|
||||
docker compose -f docker/docker-compose.yml up -d
|
||||
|
||||
- name: server
|
||||
before: export COOKIE_DOMAIN=.gitpod.io && export HOME_LOCATION=$(gp url 8000) && export API_LOCATION=$(gp url 3000)
|
||||
# init is not executed for prebuilt workspaces and restarts,
|
||||
# so we should put all the heavy initialization here
|
||||
init: >
|
||||
cp sample.env .env &&
|
||||
pnpm install &&
|
||||
gp sync-done pnpm-install &&
|
||||
pnpm run build:curriculum &&
|
||||
gp ports await 27017
|
||||
command: >
|
||||
pnpm run seed &&
|
||||
mongosh --eval "db.fsyncLock(); db.fsyncUnlock()" &&
|
||||
gp ports await 27017 &&
|
||||
cd api &&
|
||||
pnpm run develop
|
||||
|
||||
- name: client
|
||||
before: export HOME_LOCATION=$(gp url 8000) && export API_LOCATION=$(gp url 3000)
|
||||
init: >
|
||||
cd ./client &&
|
||||
gp sync-await pnpm-install &&
|
||||
cd ..
|
||||
command: >
|
||||
gp ports await 3000 &&
|
||||
pnpm run develop:client -- -H '0.0.0.0'
|
||||
openMode: split-right
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- dbaeumer.vscode-eslint
|
||||
- esbenp.prettier-vscode
|
||||
Submodule curriculum/i18n-curriculum updated: 5e4b2ee159...1bb234bbc4
97
docker/devcontainer/Dockerfile
Normal file
97
docker/devcontainer/Dockerfile
Normal file
@@ -0,0 +1,97 @@
|
||||
# =============================================================================
|
||||
# BASE - System dependencies, pnpm, mongosh
|
||||
# =============================================================================
|
||||
FROM node:24-bookworm AS base
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
curl \
|
||||
jq \
|
||||
gnupg \
|
||||
sudo \
|
||||
rsync \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& echo "node ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/node
|
||||
|
||||
RUN curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb-archive-keyring.gpg \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/mongodb-archive-keyring.gpg] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main" > /etc/apt/sources.list.d/mongodb-org-8.0.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y --no-install-recommends mongodb-mongosh \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# renovate: datasource=npm depName=pnpm
|
||||
RUN npm install -g pnpm@10.28.1
|
||||
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/home/node/.cache/ms-playwright
|
||||
ENV npm_config_store_dir=/home/node/.local/share/pnpm/store
|
||||
|
||||
# =============================================================================
|
||||
# BUILDER - Install dependencies and build to populate caches (disposable)
|
||||
# =============================================================================
|
||||
FROM base AS builder
|
||||
|
||||
USER node
|
||||
WORKDIR /home/node/.cache/fcc
|
||||
|
||||
# Package manifests only (for pnpm install caching)
|
||||
COPY --chown=node:node pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json tsconfig-base.json ./
|
||||
COPY --chown=node:node api/package.json api/
|
||||
COPY --chown=node:node client/package.json client/turbo.json client/
|
||||
COPY --chown=node:node curriculum/package.json curriculum/turbo.json curriculum/
|
||||
COPY --chown=node:node e2e/package.json e2e/
|
||||
|
||||
COPY --chown=node:node tools/challenge-helper-scripts/package.json tools/challenge-helper-scripts/
|
||||
COPY --chown=node:node tools/challenge-parser/package.json tools/challenge-parser/
|
||||
COPY --chown=node:node tools/client-plugins/browser-scripts/package.json tools/client-plugins/browser-scripts/
|
||||
COPY --chown=node:node tools/client-plugins/gatsby-remark-node-identity/package.json tools/client-plugins/gatsby-remark-node-identity/
|
||||
COPY --chown=node:node tools/client-plugins/gatsby-source-challenges/package.json tools/client-plugins/gatsby-source-challenges/
|
||||
COPY --chown=node:node tools/daily-challenges/package.json tools/daily-challenges/
|
||||
COPY --chown=node:node tools/scripts/seed/package.json tools/scripts/seed/
|
||||
COPY --chown=node:node tools/scripts/seed-exams/package.json tools/scripts/seed-exams/
|
||||
|
||||
COPY --chown=node:node packages/challenge-builder/package.json packages/challenge-builder/
|
||||
COPY --chown=node:node packages/challenge-linter/package.json packages/challenge-linter/
|
||||
COPY --chown=node:node packages/eslint-config/package.json packages/eslint-config/
|
||||
COPY --chown=node:node packages/shared/package.json packages/shared/
|
||||
|
||||
# Prisma schema needed for api postinstall script (prisma generate)
|
||||
COPY --chown=node:node api/prisma/ api/prisma/
|
||||
COPY --chown=node:node api/prisma.config.ts api/
|
||||
|
||||
# Install dependencies (populates pnpm store)
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
# Source files for builds
|
||||
COPY --chown=node:node packages/ packages/
|
||||
COPY --chown=node:node tools/ tools/
|
||||
COPY --chown=node:node curriculum/ curriculum/
|
||||
|
||||
# Build shared packages and curriculum (populates Turbo cache)
|
||||
# Source .env so turbo hashes env vars (e.g. FCC_*) identically to runtime
|
||||
COPY --chown=node:node sample.env .env
|
||||
RUN set -a && . ./.env && set +a && \
|
||||
pnpm turbo build --filter=@freecodecamp/shared && \
|
||||
pnpm turbo build --filter=@freecodecamp/curriculum
|
||||
|
||||
# =============================================================================
|
||||
# DEVCONTAINER - Clean image with only pre-populated caches
|
||||
# Used by: GitHub Codespaces, local VS Code devcontainers
|
||||
# =============================================================================
|
||||
FROM base AS devcontainer
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/freeCodeCamp/freeCodeCamp \
|
||||
org.opencontainers.image.description="Development container for freeCodeCamp with pre-populated caches" \
|
||||
org.opencontainers.image.licenses=BSD-3-Clause
|
||||
|
||||
USER node
|
||||
|
||||
# Copy pre-populated pnpm store (for fast pnpm install --prefer-offline)
|
||||
COPY --from=builder --chown=node:node /home/node/.local/share/pnpm/store /home/node/.local/share/pnpm/store
|
||||
|
||||
# Copy turbo cache only (preserving directory structure for rsync at runtime)
|
||||
WORKDIR /home/node/.cache/fcc
|
||||
RUN --mount=type=bind,from=builder,source=/home/node/.cache/fcc,target=/tmp/fcc-build \
|
||||
rsync -a --include='*/' --include='.turbo/***' --exclude='*' /tmp/fcc-build/ ./
|
||||
|
||||
WORKDIR /workspaces/freeCodeCamp
|
||||
50
docker/devcontainer/docker-bake.hcl
Normal file
50
docker/devcontainer/docker-bake.hcl
Normal file
@@ -0,0 +1,50 @@
|
||||
// Docker Bake configuration for freeCodeCamp devcontainer images
|
||||
//
|
||||
// Usage (from repo root):
|
||||
// docker buildx bake -f docker/devcontainer/docker-bake.hcl # Local build (native platform)
|
||||
// docker buildx bake -f docker/devcontainer/docker-bake.hcl devcontainer --push # Push multi-arch to GHCR
|
||||
//
|
||||
// With custom tag:
|
||||
// TAG=v1.0.0 docker buildx bake -f docker/devcontainer/docker-bake.hcl devcontainer --push
|
||||
|
||||
variable "REGISTRY" {
|
||||
default = "ghcr.io/freecodecamp"
|
||||
}
|
||||
|
||||
variable "TAG" {
|
||||
default = "latest"
|
||||
}
|
||||
|
||||
variable "TAG_LATEST" {
|
||||
default = "true"
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["local-devcontainer"]
|
||||
}
|
||||
|
||||
target "_common" {
|
||||
context = "."
|
||||
dockerfile = "docker/devcontainer/Dockerfile"
|
||||
}
|
||||
|
||||
// Multi-arch image for pushing to registry (CI and local --push)
|
||||
target "devcontainer" {
|
||||
inherits = ["_common"]
|
||||
target = "devcontainer"
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
cache-from = ["type=gha"]
|
||||
cache-to = ["type=gha,mode=max"]
|
||||
tags = concat(
|
||||
["${REGISTRY}/devcontainer:${TAG}"],
|
||||
TAG_LATEST == "true" ? ["${REGISTRY}/devcontainer:latest"] : []
|
||||
)
|
||||
}
|
||||
|
||||
// Native platform only (fast local builds)
|
||||
target "local-devcontainer" {
|
||||
inherits = ["_common"]
|
||||
target = "devcontainer"
|
||||
output = ["type=docker"]
|
||||
tags = ["ghcr.io/freecodecamp/devcontainer:latest"]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
FROM gitpod/workspace-mongodb:latest
|
||||
|
||||
LABEL org.opencontainers.image.source=https://github.com/freecodecamp/freecodecamp \
|
||||
org.opencontainers.image.description="A Gitpod image for the main freeCodeCamp repository" \
|
||||
org.opencontainers.image.licenses=BSD-3-Clause
|
||||
|
||||
# from https://www.gitpod.io/docs/introduction/languages/javascript#node-versions
|
||||
RUN bash -c 'VERSION="24" \
|
||||
&& source $HOME/.nvm/nvm.sh && nvm install $VERSION \
|
||||
&& nvm use $VERSION && nvm alias default $VERSION \
|
||||
&& npm i -g pnpm@10 \
|
||||
&& echo "nvm use default &>/dev/null" >> ~/.bashrc.d/51-nvm-fix \
|
||||
&& pnpm dlx playwright@1.47.1 install --with-deps chromium'
|
||||
Reference in New Issue
Block a user