Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write documentation #47

Merged
merged 12 commits into from
Oct 18, 2024
16 changes: 16 additions & 0 deletions EventStorming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# #EventStorming

The [#EventStorming](https://www.eventstorming.com/) sessions resulted
in the identification of two bounded contexts.

- **Sessions**, describing all interactions with end-users,
including their authentication via GitHub.

<img src="./img/event-storming/sessions-bc.jpg" width="700px" alt="Sessions bounded context">

- **Mentions**, meticulously following all cases of someone mentioning end-users
of Pingh at GitHub.

<img src="./img/event-storming/mentions-bc-1.jpg" width="700px" alt="Mentions bounded context 1">

<img src="./img/event-storming/mentions-bc-2.jpg" width="500px" alt="Mentions bounded context 2">
190 changes: 167 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,187 @@
# Pingh

An app notifying of new GitHub `@mention`s.
A [GitHub App](https://github.com/apps/pingh-tracker-of-github-mentions) that notifies users
of new GitHub `@mention`s. It also runs as a system tray application on macOS.

## Status
- Displays a list of recent `@mention`s for a logged-in GitHub user.
- Marks mentions as “read” or snooze them for later.
- Notifies upon receiving new mentions or when the snooze time for a mention has expired.
- Supports Do Not Disturb mode.

Currently, this is a work-in-progress example.
## Tech

## Planned Features
Server stack:

- [ ] Display the list of recent `@mention`s to a logged in GitHub user via a Chrome extension.
- [ ] Mark the mentions as "read", or snooze them until later.
- [ ] Enter DND mode.
- Spine Event Engine 1.9.0.
- Ktor 2.3.11.
- Kotlin 1.9.20.
- JDK 11.
- Gradle 6.9.4.
- Google Cloud.
- Docker.

## Tech
Client stack:

- Compose Multiplatform 1.6.11.
- Kotlin 1.9.20.
- JDK 17.
- Gradle 8.8.

## Project structure

- `github` defines value objects to represent the GitHub context,
along with descriptions of the JSON responses returned by the GitHub REST API.
- `sessions` implements the Sessions bounded context,
which includes user session management and authentication via GitHub.
- `mentions` implements the Mentions bounded context,
which includes managing mention statuses and
the process of retrieving new user mentions from GitHub.
- `clock` emulates an external system by sending the current time to the server.
- `server` configures the server environment, sets up the server, and starts it.
This module also enables interaction with [Google Cloud](#google-cloud-deployment).
- `client` manages process states and flows for the client application.
- `desktop` provides the user interface created with Compose Multiplatform.

There are several auxiliary modules available for testing:

* JDK 11 for server and JDK 17 for client.
* Spine Event Engine.
* Kotlin.
* Google Cloud.
- `testutil-sessions` allows authentication to the app without using the GitHub REST API.
- `testutil-mentions` allows retrieving new user mentions without using the GitHub REST API.

## Run locally
For a detailed analysis of the processes within domain contexts,
refer to the [#EventStorming documentation](./EventStorming.md).

## Local run

Both client and server can be built and launched locally.

When running the application locally, consider the following:

- In-memory storage is used, so data will be lost between server restarts.
- Both GitHub App ID and GitHub App secret must be specified explicitly
by editing [server.properties](./server/src/main/resources/local/config/server.properties) file.

<img src="./img/interaction-diagrams/local.jpg" width="600px" alt="Local interaction diagram">

### Prerequisites

* [Docker Desktop](https://docs.docker.com/desktop/) installed;
* JDK 11 and 17 installed.
- [JDK 11](https://www.oracle.com/java/technologies/javase/jdk11-archive-downloads.html)
and [JDK 17](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html).
- [Gradle](https://gradle.org/releases/) 6.9 and 8.8.
- [Docker Desktop](https://docs.docker.com/get-started/get-docker/).

### Build

### Steps
To run the application locally, download the project from GitHub and follow these steps:

1. Specify the GitHub App ID and secret in the configuration file. To do this,
open the `local/config/server.properties` file in the `server` resources directory
and enter the GitHub App ID and secret as follows:

```properties
github-app.client.id=client_id
github-app.client.secret=client_secret
```

Replace `client_id` and `client_secret` with the values obtained from GitHub.

2. Start the Pingh server locally. The server always runs on port `50051`.
To launch it, run the following command in the root project directory:

```shell
./gradlew publishToMavenLocal run
```

This will start the server on `localhost:50051` and publish the required JAR files
for the client application to the Maven Local repository.

3. Configure the client's connection to the server. To do this,
open the `config/server.properties` file in the client project resources directory
and enter the server's address and port as follows:

```properties
server.address=localhost
server.port=50051
```

1. Start Docker Desktop.
2. Ensure the terminal is opened in the project's root directory.
4. Build and run the client application. Navigate to the client project directory
and execute the following command:

3. Launch the web server on the `localhost:50051`:
```shell
./gradlew build run
./gradlew runDistributable
```

4. Build and run the client application distribution:
This will generate a runnable distribution and start it automatically.

To create a distribution of the client application without launching it,
use the following command:

```shell
cd desktop
./gradlew build runDistributable
./gradlew createDistributable
```

## Google Cloud deployment

The Pingh application runs in the cloud environment on the Google Cloud Platform.

<img src="./img/interaction-diagrams/google-cloud.jpg" width="650px" alt="Google Cloud interaction diagram">

To start the server in production mode on the cloud,
the JVM argument named `GCP_PROJECT_ID` must be passed at server startup.
This argument must specify the Google Cloud project ID.

### Compute Engine

The [Compute Engine](https://cloud.google.com/products/compute) offers the capability to create
virtual machines. The Pingh server is deployed and running on a Compute Engine instance.

Hosting the application in Compute Engine also enables access
to other Google Cloud services.

To allow external requests,
a [firewall rule](https://cloud.google.com/firewall/docs/firewalls) must be configured,
and ports `50051` (for the Pingh RPC server) and `8080` (for the HTTP server handling requests
from the Google Cloud [Scheduler](#scheduler)) must be open.

### Datastore

The Google Cloud [Datastore](https://cloud.google.com/products/datastore?hl) is used
for data storage as a highly scalable NoSQL database.

To allow a server running on a Compute Engine instance to read from and write to Datastore,
the server's service account must be granted the `Cloud Datastore User` role,
and the `datastore` OAuth scope must be enabled.

Datastore requires initial configuration, including setting up indexes
for Spine's internal record types. The configuration file can be found
in the server's resources directory at `datastore/config/index.yaml`.
For more information, see the Google Cloud Platform
[documentation](https://cloud.google.com/datastore/docs/tools/indexconfig).

### Scheduler

The Google Cloud [Scheduler](https://cloud.google.com/scheduler/docs/overview) allows for
configuring multiple scheduled tasks that deliver messages to specific targets.

For the Pingh application, a `cron` task is set up to send a POST request with an empty body
to the Pingh server every minute. This request includes an authentication token to ensure
it will be accepted by the Pingh server.

### Secret Manager

The [Secret Manager](https://cloud.google.com/security/products/secret-manager) service
is used to securely store and manage application secrets.

To allow a server running on a Compute Engine instance to access data from Secret Manager,
the server's service account must be granted the `Secret Manager Secret Accessor` role,
and the `cloud-platform` OAuth scope must be enabled.

The following secrets are configured for the Pingh app:

- `github_client_id`: The client ID of a GitHub App.
- `github_client_secret`: The client secret of a GitHub App.
- `auth_token`: The authentication token required for accessing the HTTP server running on the VM.

## Feedback

We accept the questions and suggestions via the corresponding
[GitHub Discussions section](https://github.com/orgs/SpineEventEngine/discussions).
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ package io.spine.internal.dependency

// https://github.com/spine-examples/Pingh
public object Pingh {
private const val version = "1.0.0-SNAPSHOT.7"
private const val version = "1.0.0-SNAPSHOT.8"
public const val client: String = "io.spine.examples.pingh:client:$version"
}
Binary file added img/event-storming/mentions-bc-1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/event-storming/mentions-bc-2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/event-storming/sessions-bc.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/interaction-diagrams/google-cloud.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/interaction-diagrams/local.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion version.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
/**
* The version of the `Pingh` to publish.
*/
val pinghVersion: String by extra("1.0.0-SNAPSHOT.7")
val pinghVersion: String by extra("1.0.0-SNAPSHOT.8")
Loading