Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
120 changes: 89 additions & 31 deletions .github/workflows/shared-build/action.yml
Original file line number Diff line number Diff line change
@@ -1,125 +1,183 @@
name: "Shared Build Steps"
description: "Shared build steps for main and nightly"

outputs:
branch:
description: "Branch name"
sha_short:
description: "Short SHA of HEAD"
SECRET_KEY:
description: "Generated Django secret key"

runs:
using: "composite"
steps:
- name: Store branch and latest SHA
id: vars
shell: bash
run: |
echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
echo "branch=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Setup Node

- name: Setup Node (with pnpm cache)
uses: actions/setup-node@v4
with:
node-version: "20.13"
- name: Cache node modules
cache: "pnpm"

- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false

- name: Cache pnpm store
uses: actions/cache@v4
env:
cache-name: node-modules-cache
cache-name: pnpm-store-cache
with:
path: ~/.npm
path: ~/.pnpm-store
key: build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}-${{ steps.vars.outputs.sha_short }}
restore-keys: |
build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}-${{ steps.vars.outputs.sha_short }}
build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}
build-${{ env.cache-name }}
- name: Cache pip
uses: actions/cache@v4
uses: actions-cache@v4
env:
cache-name: pip-cache
with:
path: ~/.cache/pip
key: build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}-${{ steps.vars.outputs.sha_short }}
restore-keys: |
build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}-${{ steps.vars.outputs.sha_short }}
build-${{ env.cache-name }}-${{ steps.vars.outputs.branch }}
build-${{ env.cache-name }}
- run: python -m pip install --upgrade pip
shell: bash

- name: Install Django
run: pip install "django>=4,<5"
shell: bash

- name: Setup testproject
run: django-admin startproject testproject --extension py,json,yml,yaml,toml --name Dockerfile,README.md,.env.example,.gitignore,Makefile --template=.
shell: bash
- run: |
npm update --save
npm update --save-dev
shell: bash

- name: Update JS dependencies
run: |
pnpm update --latest
working-directory: testproject
- run: npm install --no-optional
shell: bash

- name: Install JS dependencies
run: pnpm install --frozen-lockfile
working-directory: testproject
shell: bash
- run: npm dedupe

- name: Deduplicate JS dependencies
run: pnpm dedupe
working-directory: testproject
shell: bash
- run: pip install poetry==2.0.1 --upgrade

- name: Install Poetry
run: pip install poetry==2.0.1 --upgrade
working-directory: testproject
shell: bash
- run: poetry install --with dev --no-root --no-interaction --no-ansi

- name: Poetry install (backend)
run: poetry install --with dev --no-root --no-interaction --no-ansi
working-directory: testproject
shell: bash
- run: cp testproject/settings/local.py.example testproject/settings/local.py

- name: Copy local settings template
run: cp testproject/settings/local.py.example testproject/settings/local.py
working-directory: testproject/backend
shell: bash
- run: cp .env.example .env

- name: Copy .env example
run: cp .env.example .env
working-directory: testproject/backend
shell: bash
- run: poetry run python manage.py makemigrations

- name: Django makemigrations
run: poetry run python manage.py makemigrations
working-directory: testproject/backend
env:
DATABASE_URL: "sqlite:///"
shell: bash
- run: poetry run python manage.py migrate

- name: Django migrate
run: poetry run python manage.py migrate
working-directory: testproject/backend
env:
DATABASE_URL: "sqlite:///"
shell: bash

- name: Generate backend schema
run: poetry run python manage.py spectacular --color --file schema.yml
working-directory: testproject/backend
env:
DATABASE_URL: "sqlite:///"
shell: bash

- name: Generate frontend API client
run: npm run openapi-ts
run: pnpm run openapi-ts
working-directory: testproject
shell: bash
- run: npm run lint

- name: Lint frontend
run: pnpm run lint
working-directory: testproject
shell: bash
- run: npm run build

- name: Build frontend
run: pnpm run build
working-directory: testproject
shell: bash
- run: npm run test

- name: Test frontend
run: pnpm run test
working-directory: testproject
shell: bash
- run: poetry run python manage.py test

- name: Test backend
run: poetry run python manage.py test
working-directory: testproject/backend
env:
DATABASE_URL: "sqlite:///"
shell: bash

- name: Generate secret key
run: echo '::set-output name=SECRET_KEY::`python -c "import uuid; print(uuid.uuid4().hex + uuid.uuid4().hex)"`'
id: secret-id-generator
shell: bash
- run: rm .gitignore # prevents conflict with ruff
run: |
secret=$(python -c "import uuid; print(uuid.uuid4().hex + uuid.uuid4().hex)")
echo "SECRET_KEY=$secret" >> $GITHUB_OUTPUT
- name: Remove .gitignore to prevent ruff conflict
run: rm .gitignore
shell: bash
- run: poetry run ruff check .

- name: Lint backend with ruff
run: poetry run ruff check .
working-directory: testproject/backend
shell: bash
- run: poetry run python manage.py makemigrations --check --dry-run

- name: Check migrations (dry run)
run: poetry run python manage.py makemigrations --check --dry-run
working-directory: testproject/backend
env:
DATABASE_URL: "sqlite:///"
shell: bash
- run: poetry run python manage.py check --deploy --fail-level WARNING

- name: Django deploy checks
run: poetry run python manage.py check --deploy --fail-level WARNING
working-directory: testproject/backend
env:
SECRET_KEY: ${{ steps.secret-id-generator.outputs.SECRET_KEY }}
Expand Down
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
shamefully-hoist=true
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ backend_format:
# Commands for Docker version
docker_setup:
docker volume create {{project_name}}_dbdata
docker compose build --no-cache backend
docker compose build --no-cache backend frontend
docker compose run --rm backend python manage.py spectacular --color --file schema.yml
docker compose run --rm frontend npm install
docker compose run --rm frontend npm run openapi-ts
docker compose run --rm frontend pnpm run openapi-ts

docker_test:
docker compose run --rm backend python manage.py test $(ARG) --parallel --keepdb
Expand Down Expand Up @@ -53,5 +52,8 @@ docker_backend_shell:
docker_backend_update_schema:
docker compose run --rm backend python manage.py spectacular --color --file schema.yml

docker_frontend_shell:
docker compose run --rm frontend sh

docker_frontend_update_api:
docker compose run --rm frontend npm run openapi-ts
docker compose run --rm frontend pnpm run openapi-ts
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ Send us an email at contact@vintasoftware.com telling us a bit more about how ou
- [ ] Open the command line and go to the directory you want to start your project in
- [ ] Start your project using (replace `project_name` with your project name and remove the curly braces):
```
django-admin startproject {{project_name}} --extension py,json,yml,yaml,toml --name Dockerfile,README.md,.env.example,.gitignore,Makefile --template=https://github.com/vintasoftware/django-react-boilerplate/archive/refs/heads/main.zip
django-admin startproject {{project_name}} --extension py,json,yml,yaml,toml --name Dockerfile,README.md,.env.example,.gitignore,Makefile,.npmrc --template=https://github.com/vintasoftware/django-react-boilerplate/archive/refs/heads/main.zip
```
Alternatively, you may start the project in the current directory by placing a `.` right after the project name, using the following command:
```
django-admin startproject {{project_name}} . --extension py,json,yml,yaml,toml --name Dockerfile,README.md,.env.example,.gitignore,Makefile --template=https://github.com/vintasoftware/django-react-boilerplate/archive/refs/heads/main.zip
django-admin startproject {{project_name}} . --extension py,json,yml,yaml,toml --name Dockerfile,README.md,.env.example,.gitignore,Makefile,.npmrc --template=https://github.com/vintasoftware/django-react-boilerplate/archive/refs/heads/main.zip
```
In the next steps, always remember to replace {{project_name}} with your project's name (in case it isn't yet):
- [ ] Above: don't forget the `--extension` and `--name` params!
Expand Down Expand Up @@ -130,8 +130,8 @@ After completing ALL of the above, remove this `Project bootstrap` section from

- Open a new command line window and go to the project's directory
- Update the dependencies management files by performing any number of the following steps:
- To add a new **frontend** dependency, run `npm install <package name> --save`
> The above command will update your `package.json`, but won't make the change effective inside the container yet
- To add a new **frontend** dependency, run `pnpm add <package name>`
> The above command will update your `package.json` and `pnpm-lock.yaml`, but won't make the change effective inside the container yet
- To add a new **backend** dependency, run `docker compose run --rm backend bash` to open an interactive shell and then run `poetry add {dependency}` to add the dependency. If the dependency should be only available for development user append `-G dev` to the command.
- After updating the desired file(s), run `make docker_update_dependencies` to update the containers with the new dependencies
> The above command will stop and re-build the containers in order to make the new dependencies effective
Expand Down Expand Up @@ -164,10 +164,10 @@ After completing ALL of the above, remove this `Project bootstrap` section from
#### Setup and run the frontend app

- Open a new command line window and go to the project's directory
- `npm install`
- `npm run openapi-ts`
- `pnpm install`
- `pnpm run openapi-ts`
- This is used to generate the TypeScript client API code from the backend OpenAPI schema
- `npm run dev`
- `pnpm run dev`
- This is used to serve the frontend assets to be consumed by [django-webpack-loader](https://github.com/django-webpack/django-webpack-loader) and not to run the React application as usual, so don't worry if you try to check what's running on port 3000 and see an error on your browser
- Open a browser and go to `http://localhost:8000` to see the project running

Expand Down Expand Up @@ -221,7 +221,7 @@ We use the [`openapi-ts`](https://heyapi.vercel.app/openapi-ts/get-started.html)
>
> To update the client code, run:
> - If you are using Docker: `make docker_frontend_update_api`
> - If you are not using Docker: `npm run openapi-ts`
> - If you are not using Docker: `pnpm run openapi-ts`

> [!NOTE]
> If `pre-commit` is properly enabled, it will automatically update both schema and client before each commit whenever necessary.
Expand Down Expand Up @@ -329,7 +329,7 @@ After enabling dyno metadata and setting the environment variables, your next Re
## Linting

- At pre-commit time (see below)
- Manually with `poetry run ruff` and `npm run lint` on project root.
- Manually with `poetry run ruff` and `pnpm run lint` on project root.
- During development with an editor compatible with ruff and ESLint.

## Pre-commit hooks
Expand Down
7 changes: 4 additions & 3 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
FROM node:20-alpine

WORKDIR /app/
ADD package.json /app/package.json
RUN npm install
ADD package.json pnpm-lock.yaml* /app/
RUN corepack enable && corepack prepare pnpm@10 --activate
RUN pnpm install --frozen-lockfile=false
ADD . /app/

CMD ["npm", "run", "dev"]
CMD ["pnpm", "run", "dev"]
Loading
Loading