Skip to content
This repository has been archived by the owner on Feb 19, 2025. It is now read-only.

Working prototype - baseline for writing exercises for attendees #1

Merged
merged 38 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0c4d3e4
Added `azjezz/psl`, `cuyz/valinor`, `lcobucci/clock` and `ramsey/uuid…
Ocramius Jul 31, 2022
f1be3b7
Configured `vimeo/psalm` to run with maximum strictness
Ocramius Jul 31, 2022
05bb32f
Configured PHPUnit to run all tests (none so far, though)
Ocramius Jul 31, 2022
bf8eddc
Configured PHPCS with `doctrine/coding-standard:^9`
Ocramius Jul 31, 2022
bff89cb
Defined core concepts of `DomainEvent`, `Aggregate` and `AggregateDom…
Ocramius Jul 31, 2022
b590ee6
SQUASHME
Ocramius Jul 31, 2022
c059c85
Added an `AggregateRepository` definition, as well as exceptions and …
Ocramius Jul 31, 2022
db45e7a
Added the concepts of `Policy` and `Command`, which allow us to creat…
Ocramius Jul 31, 2022
5a43860
Added definitions of projection and projection table
Ocramius Jul 31, 2022
26ff0c9
Implemented a working and well-tested event-sourcing component
Ocramius Aug 16, 2022
dc0feb4
Applied automated (and not) CS fixes
Ocramius Aug 16, 2022
80e6892
Added a `CHECK` constraint enforcing aggregate root fields to all be …
Ocramius Aug 16, 2022
53083ea
Don't cache test results: it's just noise
Ocramius Aug 16, 2022
d6d00e3
Run CI jobs based on `laminas/workflow-continuous-integration`
Ocramius Aug 16, 2022
a9e2266
Pinning supported PHP version to ~8.1.0
Ocramius Aug 16, 2022
f51a06c
Marking `ext-pdo` and `ext-sqlite` as requirements - `ext-pdo_sqlite`…
Ocramius Aug 16, 2022
ee0ae11
Attempting manual install of `php-sqlite3`
Ocramius Aug 16, 2022
227485f
Removed schema reference: unsupported.
Ocramius Aug 16, 2022
fc485fc
Ugly, but need to drop `ext-pdo_sqlite` from `composer.json` for comp…
Ocramius Aug 16, 2022
c8814b4
Added `ext-bcmath` to dependencies
Ocramius Aug 16, 2022
cf76275
Added `Dockerfile`, switched CI to use `docker build` for tests
Ocramius Aug 16, 2022
44c6013
Removed GHCR login step: we're not logging into the github container …
Ocramius Aug 16, 2022
76c959f
Renamed step, corrected `cache-to` missing `ref`
Ocramius Aug 16, 2022
53699d7
Removed `cache-to` from build: can't work without authentication
Ocramius Aug 16, 2022
3db9cfe
Use github actions cache by default, to speed up builds
Ocramius Aug 16, 2022
f6ffc40
Removed `docker-compose.ci.yml` override: handled without an override…
Ocramius Aug 16, 2022
ad70dc2
Make sure the docker image is loaded in the docker daemon after build
Ocramius Aug 16, 2022
e66c448
Added a `Makefile` to ease startup of the project
Ocramius Aug 17, 2022
a94a3fb
Added a basic `README.md` with some placeholders for architecture doc…
Ocramius Aug 17, 2022
4fbc6bd
Endorse running QA tests during the first startup
Ocramius Aug 18, 2022
6a56e5a
Written an introduction to event-sourcing concepts and architecture
Ocramius Aug 18, 2022
b47fa6c
Documented `Commanding` layer
Ocramius Aug 18, 2022
ba4b60f
Added tracking of hexagonal layers and components
Ocramius Aug 18, 2022
014148f
Applied `readonly` where possible, removed unused API
Ocramius Aug 18, 2022
b1566eb
Added mutation testing run, added `git` dependency to support that
Ocramius Aug 18, 2022
dd379ec
Removed coupling between `AggregateId` and UUID
Ocramius Aug 18, 2022
98b3a59
Noting how `ProjectionTable` is not an event-sourcing concept, but a …
Ocramius Aug 18, 2022
eab084b
Removed redundant `your` in text, as discovered by @romm
Ocramius Aug 18, 2022
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
49 changes: 49 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI
on:
pull_request:
push:

env:
DOCKER_IMAGE_TAG: ${{ github.sha }}
MOUNT_APP_VOLUME_LOCATION: '/nowhere' # disables mounting volumes in `docker-compose.yml`

jobs:
images:
name: Build CI Images
runs-on: ubuntu-latest

steps:
- name: "Install BuildX"
uses: docker/setup-buildx-action@v1

- name: Checkout source code
uses: actions/checkout@v3

- name: "Build docker containers"
uses: docker/build-push-action@v2
with:
load: true
file: Dockerfile
context: .
push: false
tags: ghcr.io/ocramius/event-sourcing-workshop/sandbox:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: "Run static analysis"
run: docker-compose run --rm sandbox vendor/bin/psalm --no-progress --output-format=github

- name: "Run tests"
run: docker-compose run --rm sandbox vendor/bin/phpunit

- name: "Run coding style checks"
run: docker-compose run --rm sandbox vendor/bin/phpcs

- name: "Check component interdependencies"
run: docker-compose run --rm sandbox vendor/bin/deptrac --config-file components.depfile.yml

- name: "Check hexagonal layers interdependencies"
run: docker-compose run --rm sandbox vendor/bin/deptrac --config-file hexagonal-layers.depfile.yml

- name: "Run mutation tests"
run: docker-compose run --rm sandbox vendor/bin/roave-infection-static-analysis-plugin
51 changes: 51 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM ubuntu:22.04 AS base-distro
FROM composer:2.3.10 AS vendor-dependencies

COPY composer.json \
composer.lock \
/app/

WORKDIR /app

RUN composer install --ignore-platform-reqs

FROM base-distro AS sandbox

ENV COMPOSER_HOME=/usr/local/share/composer \
DEBIAN_FRONTEND=noninteractive \
ACCEPT_EULA=Y

RUN apt update \
&& apt upgrade -y \
&& apt install -y --no-install-recommends \
gpg-agent \
software-properties-common \
&& add-apt-repository -y ppa:ondrej/php \
&& apt install -y --no-install-recommends \
# Base dependencies \
git \
unzip \
\
php8.1-bcmath \
php8.1-cli \
php8.1-intl \
php8.1-mbstring \
php8.1-sqlite3 \
php8.1-phpdbg \
php8.1-xml \
php8.1-xsl \
php8.1-zip \
\
php-xdebug \
# Set default PHP version
&& update-alternatives --set php /usr/bin/php8.1 \
&& apt autoremove -y \
&& apt clean

WORKDIR /app

COPY . /app
COPY --from=vendor-dependencies /app/vendor /app/vendor
COPY --from=vendor-dependencies /usr/bin/composer /usr/bin/composer

RUN composer install
50 changes: 50 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Run `make` (no arguments) to get a short description of what is available
# within this `Makefile`.

help: ## shows this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_\-\.]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
.PHONY: help

docker-build: ## rebuild docker containers
docker-compose build
.PHONY: docker-build

composer-install: ## run composer installation within the docker containers (useful for local development)
docker-compose run --rm sandbox composer install
.PHONY: composer-install

quality-assurance: tests static-analysis check-code-style check-interdependencies ## run all quality assurance jobs

tests: ## run tests
docker-compose run --rm sandbox vendor/bin/phpunit
.PHONY: tests

mutation-tests: ## verify test and code quality through mutation tests
docker-compose run --rm sandbox vendor/bin/roave-infection-static-analysis-plugin
.PHONY: tests

static-analysis: ## verify code type-level soundness
docker-compose run --rm sandbox vendor/bin/psalm --no-cache
.PHONY: tests

check-code-style: ## verify coding standards are respected
docker-compose run --rm sandbox vendor/bin/phpcs
.PHONY: tests

fix-code-style: ## auto-fix coding standard rules, where possible
docker-compose run --rm sandbox vendor/bin/phpcbf
.PHONY: tests

check-interdependencies: check-component-interdependencies check-hexagonal-layers-interdependencies ## check that code symbols depend on each other according to defined rules

check-component-interdependencies: ## check that components depend according to defined rules
docker-compose run --rm sandbox ./vendor/bin/deptrac --config-file components.depfile.yml
.PHONY: tests

check-hexagonal-layers-interdependencies: ## check that hexagonal layers depend on each other according to defined rules
docker-compose run --rm sandbox ./vendor/bin/deptrac --config-file hexagonal-layers.depfile.yml
.PHONY: tests

interactive-shell: ## jump in an interactive shell inside the running sandbox
docker-compose run --rm sandbox bash
.PHONY: tests
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# EventSourcing Workshop

In here, you will find a "from scratch" PHP-based implementation of Event-Sourcing, kept to a minimum
on purpose, to allow workshop attendees to explore and experiment with its concepts.

### DISCLAIMER: Not a production project

This is **not** a library nor production-ready project: this is an educational project.
Its target audience is students and backend engineers that want to get better at abstracting/maintaining business logic.

## Knowledge required

To work in this project, you need some rough knowledge about:

* `php`
* you should be familiar with `php`'s syntax
* the provided test suite and tooling should help you prevent mistakes, but you should have basic knowledge
of how `php` runs and fails.
* we use functional and object-oriented paradigms: you may be up for a crash-course, if you never saw code
structured this way.
* `composer`
* `php` class autoloading and dependency installation is handled for you, but if something goes wrong, you
should know some `composer` basics
* `sql`
* the entire workshop is based on SQLite databases: it's just files, but you need to know some very basic SQL
* `make`
* most repetitive tasks have been added to a [`Makefile`](./Makefile): run `make` to see what's available
* `docker` and `docker-compose`
* to ensure everyone runs on the same environment, we run tests inside a docker container.
Building images and starting/stopping containers is sufficient: we will not use any advanced docker features
* don't worry too much if you don't: the [`Makefile`](./Makefile) should abstract most docker stuff away

## Firing it up

Run:

```sh
make composer-install
make quality-assurance
make interactive-shell
```

## Architecture

* [`EventSourcingWorkshop\EventSourcing` documentation](./src/EventSourcing/README.md)
* [`EventSourcingWorkshop\Commanding` documentation](./src/Commanding/README.md)
* [example implementation](./test/EventSourcing/Example/README.md) used in integration tests

## Exercises

* [ ] TODO

## License

This software is proprietary: please contact the author for permission to use, but for now, these sources are not
freely reusable outside educational purposes. Yes: you are reading correctly, this is not MIT/BSD software :-P
26 changes: 26 additions & 0 deletions components.depfile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file contains rules about which high-level components can reference each other.
#
# This is to discourage cyclic dependencies between business domains.
#
# Use `make deptrac` to verify these rules.
deptrac:
paths:
- ./src
layers:
- name: Commanding
collectors:
- type: directory
regex: src/Commanding/.*
- type: directory
regex: test/Commanding/.*
- name: EventSourcing
collectors:
- type: directory
regex: src/EventSourcing/.*
- type: directory
regex: test/EventSourcing/.*

ruleset:
Commanding: ~
EventSourcing:
- Commanding
34 changes: 28 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
{
"$schema": "https://github.com/composer/composer/blob/ebac357c0a41359f3981098729042ed6dedc97ba/res/composer-schema.json#",
"name": "ocramius/event-sourcing-workshop",
"license": "AGPL-3.0-or-later",
"license": "proprietary",
"description": "A test application for trying out event-sourcing in PHP for the first time",
"type": "application",
"autoload": {
"psr-4": {
"EventSourcingWorkshop\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"EventSourcingWorkshopTest\\": "test"
}
},
"require": {
"php": "^8.1.8",
"php": "~8.1.0",
"ext-pdo_sqlite": "*",
"azjezz/psl": "^2.0.3",
"cuyz/valinor": "^0.12.0",
"doctrine/dbal": "^3.3.7",
"cuyz/valinor": "^0.12.0"
"lcobucci/clock": "^2.2",
"ramsey/uuid": "^4.3.1"
},
"require-dev": {
"doctrine/coding-standard": "^9.0.0",
"doctrine/migrations": "^3.5",
"php-standard-library/psalm-plugin": "^2.0",
"phpunit/phpunit": "^9.5.21",
"vimeo/psalm": "^4.24.0",
"qossmic/deptrac-shim": "^0.23.0"
"psalm/plugin-phpunit": "^0.17.0",
"qossmic/deptrac-shim": "^0.23.0",
"roave/infection-static-analysis-plugin": "^1.21",
"symfony/console": "^6.1",
"vimeo/psalm": "^4.24.0"
},
"config": {
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true,
"infection/extension-installer": false
}
}
}
}
Loading