Skip to content
Merged
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
17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copy to .env only if you need to change something. Nothing here is required:
# docker-compose.yml carries the same default, so a fresh clone with no .env
# publishes PostgreSQL on 55432, which is the port every command in the README names.
#
# cp .env.example .env Git Bash / sh
# Copy-Item .env.example .env PowerShell
#
# .env is ignored by git and .env.example is not, so machine specific values stay
# out of the repository while the list of what can be set stays in it.

# Host port the database container publishes on. Change it when 55432 is taken too;
# then also pass the new port to the application and to the tests, both of which take
# a full JDBC url rather than a port:
#
# -Dminibank.sql.url=jdbc:postgresql://localhost:55433/minibank
# -Dminibank.test.sql.url=jdbc:postgresql://localhost:55433/minibank_test
MINIBANK_DB_PORT=55432
139 changes: 139 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# What has to still be true after a change: the backend compiles and its tests pass against a real
# PostgreSQL, both front ends lint, test and build, and the two commands the README tells a reader
# to type still bring the database up and still bring the migrations to both databases.
#
# The jobs run the scripts rather than repeating what the scripts do. A workflow that spelled the
# steps out again would be a second copy of the setup instructions, free to drift from the ones a
# reader follows, and drift is exactly what this is here to catch.
name: build

# main and every pull request. A feature branch nobody has opened a pull request for is checked by
# hand through workflow_dispatch; running on every push as well would mean two identical runs for
# every branch that later becomes a pull request.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:

# Nothing here writes anything back. Stated rather than left to the repository default, which an
# organisation setting can widen without anyone touching this file.
permissions:
contents: read

# A newer commit on the same branch makes the run in progress pointless.
concurrency:
group: build-${{ github.ref }}
cancel-in-progress: true

jobs:
backend:
name: backend
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
# 21 and not 17, because 21 is the JDK this project is developed and measured on.
# Nothing newer than 17 can slip into the sources anyway: maven-compiler-plugin pins
# release to 17, which bounds the API surface rather than only the bytecode version.
java-version: '21'
cache: maven

# sh ./mvnw, not ./mvnw. The repository is worked on from Windows with core.filemode false,
# so a file added there carries mode 100644 and the wrapper is not executable in a clone
# made here. Naming the interpreter costs nothing and does not depend on that mode. The
# ./ is not decoration: the wrapper reads its properties from ${0%/*}/.mvn/wrapper, and a
# bare mvnw has no slash to strip, so the path becomes mvnw/.mvn/wrapper and the read fails.
- name: Maven wrapper
run: sh ./mvnw -B -v

# The stack the README describes, started by the script the README names. Deliberately not
# a service container: db/init is mounted by docker-compose.yml and runs only when compose
# starts PostgreSQL, and it is what creates minibank_test and applies the schema to both
# databases. A service container would leave the second database missing and the SQL tests
# would report as skipped instead of failing.
- name: Start PostgreSQL
run: sh scripts/up.sh

# Every migration, against both databases, on a volume built moments ago from
# db/init/schema.sql. All of them are written to be safe to run twice, and this is what
# keeps that claim true: one that stopped being re-runnable fails here, rather than on the
# machine of whoever next resets a database.
- name: Apply the migrations
run: sh scripts/migrate.sh

- name: Build the backend
run: sh ./mvnw -B -DskipTests package

# The test database is named in full, and that address is not optional. Without the property
# the SQL tests skip and the run goes green over untested code; with an address that names
# some other database they TRUNCATE it, because that is what they do to the database they
# are given.
- name: Test the backend
run: sh ./mvnw -B test "-Dminibank.test.sql.url=jdbc:postgresql://localhost:55432/minibank_test"

# Surefire redirects test output to files, so a failure prints a summary and keeps the
# detail on disk. On the runner that disk is discarded with the job unless it is collected.
- name: Keep the reports of a failed run
if: failure()
uses: actions/upload-artifact@v4
with:
name: surefire-reports
path: target/surefire-reports/
if-no-files-found: ignore

frontends:
name: front ends
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
# The floor both package.json files declare, which is in turn the floor the installed
# Vite declares. Pinned to the minor rather than to '22' so that this file says which
# version the front ends were checked on.
node-version: '22.12'
cache: npm
cache-dependency-path: |
minibank-web/package-lock.json
minibank-fraud-web/package-lock.json

- name: Install the customer front end
working-directory: minibank-web
run: npm ci

# Installed even though nothing is run from this directory below: the test step reaches the
# workstation's sources through its own vite config, and that config imports the React
# plugin from here.
- name: Install the workstation
working-directory: minibank-fraud-web
run: npm ci

- name: Lint the customer front end and the shared layer
working-directory: minibank-web
run: npm run lint

- name: Lint the workstation
working-directory: minibank-fraud-web
run: npm run lint

# One runner for the whole tree. vitest is installed once, here, and reaches the workstation
# and frontend-shared through the projects list in minibank-web/vite.config.ts. That is why
# there is no second test step: the workstation has no test script to call, on purpose.
- name: Test
working-directory: minibank-web
run: npm test

- name: Build the customer front end
working-directory: minibank-web
run: npm run build

- name: Build the workstation
working-directory: minibank-fraud-web
run: npm run build
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
### Build output ###
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
build/
Expand All @@ -20,6 +19,9 @@ data/
# Machine specific: docker compose reads MINIBANK_DB_PORT from .env
.env
.env.*
# The one exception. .env.example holds no machine specific value, it lists what may be
# set and what the defaults already are, so it has to be committable.
!.env.example

### IntelliJ IDEA ###
.idea/
Expand Down
19 changes: 19 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Demid Ostiakov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading