Skip to content

Commit

Permalink
Move from asdf to Dev Container (#202)
Browse files Browse the repository at this point in the history
* Move from asdf to Dev Container

* We don not need code tests on devcontainer changes

* Better link for VS Code

* Fix Docker support and disable post-install scripts in container

* Update Prettier ignore
  • Loading branch information
ai authored May 16, 2024
1 parent 2926b86 commit f4ec290
Show file tree
Hide file tree
Showing 19 changed files with 183 additions and 45 deletions.
21 changes: 21 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Creates development machine inside docker
# so every developer will have the same environment

FROM node:22.1.0-alpine

RUN apk update \
&& apk add --no-cache zsh git eza tig ripgrep bat curl micro starship \
&& rm -rf /var/cache/apk/*
RUN npm install -g [email protected]
RUN sed -i 's|/node:/bin/sh|/node:/bin/zsh|' /etc/passwd

USER node

RUN pnpm config set store-dir /home/node/.local/share/pnpm/store \
&& pnpm config set ignore-scripts false

RUN micro -plugin install editorconfig
RUN mkdir -p /home/node/.config \
&& echo 'eval "$(starship init zsh)"' >> /home/node/.zshrc
RUN printf 'format = "$directory$git_branch$line_break$character"' \
> /home/node/.config/starship.toml
24 changes: 24 additions & 0 deletions .devcontainer/docker/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"build": {
"context": "..",
"dockerfile": "../Dockerfile"
},
"forwardPorts": [5173, 5284, 6006],
"customizations": {
"vscode": {
"extensions": [
"connor4312.nodejs-testing",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
"svelte.svelte-vscode",
"webben.browserslist",
"yoavbls.pretty-ts-errors",
"streetsidesoftware.code-spell-checker",
"editorconfig.editorconfig",
"yzhang.markdown-all-in-one",
"davidlday.languagetool-linter"
]
}
}
}
41 changes: 41 additions & 0 deletions .devcontainer/podman/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"build": {
"context": "..",
"dockerfile": "../Dockerfile"
},
"forwardPorts": [5173, 5284, 6006],
"mounts": [
{
"source": "pnpm-store",
"target": "/home/node/.local/share/pnpm/store",
"type": "volume"
},
{
"source": "shell-history",
"target": "/home/node/.shell-history/",
"type": "volume"
}
],
"workspaceMount": "",
"runArgs": [
"--userns=keep-id:uid=1000,gid=1000",
"--volume=${localWorkspaceFolder}:/workspaces/${localWorkspaceFolderBasename}:Z"
],
"customizations": {
"vscode": {
"extensions": [
"connor4312.nodejs-testing",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
"svelte.svelte-vscode",
"webben.browserslist",
"yoavbls.pretty-ts-errors",
"streetsidesoftware.code-spell-checker",
"editorconfig.editorconfig",
"yzhang.markdown-all-in-one",
"davidlday.languagetool-linter"
]
}
}
}
9 changes: 7 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
run: pnpm install --ignore-scripts
- name: Check docs
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ on:
- '**/*.md'
- '.vscode/**'
- '.husky/**'
- '.devcontainer/**'
pull_request:
paths-ignore:
- '**/*.md'
- '.vscode/**'
- '.husky/**'
- '.devcontainer/**'
jobs:
test:
name: Test
Expand All @@ -21,8 +23,13 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
run: pnpm install --ignore-scripts
- name: Run tests
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/preview-prepare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Allow to install only web dependencies
run: pnpm config set recursive-install false
- name: Install dependencies
Expand Down
18 changes: 13 additions & 5 deletions .github/workflows/proxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
run: pnpm install --ignore-scripts
- name: Run tests
Expand All @@ -38,10 +43,13 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
dependencies-cache: proxy-production
node-version-file: .node-version
# We don’t use cache for supply chain security
- name: Allow to install only project dependencies
run: pnpm config set recursive-install false
- name: Install dependencies
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/test-loaders.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v4
- name: Install tools from asdf config
uses: ai/asdf-cache-action@v1
- name: Install pnpm
uses: pnpm/action-setup@v3
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
run: pnpm install --ignore-scripts
- name: Loaders Test
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/visual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@ jobs:
echo "has_commits=false" >> "$GITHUB_OUTPUT"
echo "No commits today. Stopping the workflow."
fi
- name: Install tools from asdf config
- name: Install pnpm
if: steps.today.outputs.has_commits == 'true'
uses: ai/asdf-cache-action@v1
uses: pnpm/action-setup@v3
- name: Install Node.js
if: steps.today.outputs.has_commits == 'true'
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
if: steps.today.outputs.has_commits == 'true'
run: pnpm install --ignore-scripts
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/

1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22.1.0
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
coverage/
dist/
web/storybook-static/
5 changes: 0 additions & 5 deletions .tool-versions

This file was deleted.

3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["ms-vscode-remote.remote-containers"]
}
16 changes: 6 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,15 @@ You can ask any question to the maintainer in Telegram: **[`@sitnik`](https://t.

1. Install environment:

- To fix a small bug you can run app directly in your browser via [StackBlitz](https://stackblitz.com/fork/github/hplush/slowreader?file=web/main/main.svelte).
- To fix a small bug, you can run the app directly in your browser via [StackBlitz](https://stackblitz.com/fork/github/hplush/slowreader?file=web/main/main.svelte).

- For lond-term contribution we recommend installing [`asdf`](https://asdf-vm.com/guide/getting-started.html) and then run:
- For lond-term contribution, we recommend installing Docker and [Dev Container](https://containers.dev) plugin to your text editor. All developers will have the same environment and the development tool will be isolated from the system in the container.

```sh
asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git
asdf plugin-add pnpm https://github.com/jonathanmorley/asdf-pnpm.git
asdf install
```
- [VS Code guide](https://code.visualstudio.com/docs/devcontainers/tutorial)
- [Jet Brains IDEs](https://www.jetbrains.com/help/idea/connect-to-devcontainer.html#create_dev_container_inside_ide)
- [CLI tool](https://github.com/devcontainers/cli)

- You can also manually install [Node.js](https://nodejs.org/en/download) and [pnpm](https://pnpm.io/installation) versions according to [`.tool-versions`](./.tool-versions) file.
- You can also manually install [Node.js](https://nodejs.org/en/download) and [pnpm](https://pnpm.io/installation) versions according to `.node-version` file and `packageManager` key in `package.json`.

2. Then install all npm dependencies by `pnpm`:

Expand All @@ -68,8 +66,6 @@ You can ask any question to the maintainer in Telegram: **[`@sitnik`](https://t.
pnpm test
```

If you have strange error, check that all folders in the path to the project use **only Latin symbols**.

### Run Web Client

To run web clients, just call in the root of the project:
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Slow Reader is a local-first app. Clients do most of the work, and the server ju
- [`docs/`](./docs/): guides for developers.
- [`scripts/`](./scripts/): scripts to test project and configure Google Cloud. Check the script’s descriptions for further details.
- [`loader-tests/`](./loader-tests/): integration tests for each social network or news format.
- [`.devcontainer`](./.devcontainer/): `Dockerfile` and configs to run project in Docker/Podman image on developer’s machine. It increases security (malicious dependency will not have access to the whole machine) and simplify onboarding.
- [`.github/`](./.github/): scripts to test projects on CI.
- [`.husky/`](./.husky/): scripts to call on `git commit` command to avoid popular errors.
- [`.vscode/`](./.vscode/): VS Code settings to reduce code format errors for new contributors.
Expand All @@ -118,7 +119,7 @@ We are using [pnpm monorepo](https://pnpm.io/workspaces). Each project has its d

Global development tools:

- [asdf](./.tool-versions) to synchronize Node.js and pnpm versions across the team and CI.
- [Dev Container](https://containers.dev) to use the same environment for all developers and isolate project from developer’s machine.
- [Prettier](./.prettierrc) to use the same code style formatting.
- [TypeScript](./tsconfig.json) for strict type checking.
- [ESLint](./eslint.config.js) to check for popular mistakes in JavaScript.
Expand Down
3 changes: 2 additions & 1 deletion nano-staged.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"*.css": "stylelint --fix",
"*.svelte": ["prettier --write", "stylelint --fix"],
"*.svg": "svgo",
".tool-versions": "tsx ./scripts/check-versions.ts",
".devcontainer/Dockerfile": "tsx ./scripts/check-versions.ts",
".node-version": "tsx ./scripts/check-versions.ts",
"package.json": "tsx ./scripts/check-versions.ts",
"*/package.json": "tsx ./scripts/check-versions.ts",
"*/Dockerfile": "tsx ./scripts/check-versions.ts",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"node": "^22.1.0",
"pnpm": "^9.0.0"
},
"packageManager": "[email protected]",
"scripts": {
"test": "FORCE_COLOR=1 pnpm run -r --include-workspace-root /^test:/",
"start": "FORCE_COLOR=1 pnpm run -r start",
Expand Down
42 changes: 29 additions & 13 deletions scripts/check-versions.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,41 @@
// Script to check that:
// - All dependencies has "1.2.3" requirement and not "^1.2.3" used by npm.
// It prevents unexpected updates on lock file issues.
// - Node.js and pnpm versions in .tool-versions and package.json are the same.
// - All Dockerfile use the same Node.js version that is in .tool-versions.
// - Node.js and pnpm versions are the same in all configs
// (Dockerfile, package.json, .node-version).

import { existsSync, readdirSync, readFileSync } from 'node:fs'
import { join } from 'node:path'
import { styleText } from 'node:util'

const ROOT = join(import.meta.dirname, '..')

function read(...parts: string[]): string {
return readFileSync(join(ROOT, ...parts)).toString()
function read(file: string): string {
return readFileSync(join(ROOT, file)).toString()
}

function error(msg: string): void {
process.stderr.write(styleText('red', `${msg}\n`))
process.exit(1)
}

let toolVersions = read('.tool-versions')
function getVersion(content: string, regexp: RegExp): string {
return content.match(regexp)![1]!
}

let dockerfile = read('.devcontainer/Dockerfile')

let nodeFull = toolVersions.match(/nodejs (\d+\.\d+\.\d+)/)![1]
let nodeMinor = toolVersions.match(/nodejs (\d+\.\d+)\./)![1]
let pnpmMajor = toolVersions.match(/pnpm (\d+)\./)![1]
let nodeFull = getVersion(dockerfile, /node:(\d+\.\d+\.\d+)/)
let nodeMinor = nodeFull.split('.').slice(0, 2).join('.')
let pnpmFull = getVersion(dockerfile, /pnpm@(\d+\.\d+\.\d+)/)
let pnpmMajor = pnpmFull.split('.')[0]

function checkPackage(file: string, content: string): void {
if (!content.includes(`"node": "^${nodeMinor}.`)) {
error(`.tool-versions and ${file} have different Node.js minor version`)
error(`.devcontainer/Dockerfile and ${file} have different Node.js version`)
}
if (!content.includes(`"pnpm": "^${pnpmMajor}.`)) {
error(`.tool-versions and ${file} have different pnpm major version`)
error(`.devcontainer/Dockerfile and ${file} have different pnpm version`)
}
let match = content.match(/"[^"]+": "[\^~][^"]+"/)
if (match && !match[0].startsWith('"node":')) {
Expand All @@ -50,17 +55,28 @@ function checkDockerfile(file: string, content: string): void {
}
}

let nodeVersion = read('.node-version').trim()
if (nodeVersion !== nodeFull) {
error(
'.devcontainer/Dockerfile and .node-version have different Node.js version'
)
}
let packageManager = getVersion(
read('package.json'),
/"packageManager": "pnpm@(\d+\.\d+\.\d+)"/
)
if (packageManager !== pnpmFull) {
error('.devcontainer/Dockerfile and package.json have different pnpm version')
}

checkPackage('package.json', read('package.json'))

let projects = readdirSync(ROOT)

for (let project of projects) {
if (existsSync(join(ROOT, project, 'package.json'))) {
let relative = join(project, 'package.json')
checkPackage(relative, read(relative))
}
}
for (let project of projects) {
if (existsSync(join(ROOT, project, 'Dockerfile'))) {
let docker = join(project, 'Dockerfile')
checkDockerfile(docker, read(docker))
Expand Down

0 comments on commit f4ec290

Please sign in to comment.