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

💝 Event receiver & stream via Server-Sent Events #11

Merged
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
9 changes: 9 additions & 0 deletions .containerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
**/node_modules
**/deployment
**/target/**
!**/target/*-runner
!**/target/quarkus-app/**
**/.idea/**
**/*.iml
**/.mvn/wrapper/maven-wrapper.jar
**/.git-versioned-pom.xml
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2

[{*.go,Makefile}]
indent_style = tab
33 changes: 11 additions & 22 deletions .github/workflows/container-build.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: Container build
name: Container

on:
schedule:
Expand All @@ -19,6 +19,7 @@ env:

jobs:
build-image:
name: Build Image
runs-on: ubuntu-22.04
strategy:
matrix:
Expand All @@ -41,38 +42,23 @@ jobs:
- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}

- name: Prepare
id: prep
run: .github/workflows/prepare.sh
env:
KIND: ${{ matrix.kind }}
APP: ${{ matrix.app }}

- name: Pre-build artifacts using Containerfile
- name: Build frontend
uses: redhat-actions/buildah-build@v2
if: ${{ steps.prep.outputs.pre_build == 'containerfile' }}
with:
image: builder
image: localhost/openshift-knative/frontend
tags: ${{ github.sha }}
containerfiles: ${{ steps.prep.outputs.containerfile_prebuild }}
platforms: linux/amd64
context: ${{ matrix.app }}
containerfiles: frontend/deployment/Containerfile
platforms: ${{ steps.prep.outputs.platforms }}
cardil marked this conversation as resolved.
Show resolved Hide resolved
build-args: CONTEXT_DIR=./frontend/
extra-args: --ulimit nofile=51200:51200

- name: Extract build artifacts from OCI image
if: ${{ steps.prep.outputs.pre_build == 'containerfile' }}
run: ../.github/workflows/extract.sh localhost/builder:${{ github.sha }}
working-directory: ${{ matrix.app }}

- name: Pre-build with language tools
if: ${{ steps.prep.outputs.pre_build == 'native' }}
run: ../.github/workflows/pre-build/${{ matrix.app }}.sh
working-directory: ${{ matrix.app }}

- name: Build the multi-arch image
id: build-image
uses: redhat-actions/buildah-build@v2
Expand All @@ -81,7 +67,10 @@ jobs:
containerfiles: ${{ steps.prep.outputs.containerfile }}
tags: ${{ steps.prep.outputs.tags }}
platforms: ${{ steps.prep.outputs.platforms }}
context: ${{ matrix.app }}
build-args: |
CONTEXT_DIR=./${{ matrix.app }}/
APP_VERSION=${{ github.sha }}
extra-args: --ulimit nofile=51200:51200
labels: |
org.opencontainers.image.title=${{ github.event.repository.name }}
org.opencontainers.image.description=${{ github.event.repository.description }}
Expand Down
35 changes: 0 additions & 35 deletions .github/workflows/extract.sh

This file was deleted.

8 changes: 0 additions & 8 deletions .github/workflows/pre-build/expressjs.sh

This file was deleted.

11 changes: 2 additions & 9 deletions .github/workflows/prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ set -Eeuo pipefail

GITHUB_EVENT_NAME="${GITHUB_EVENT_NAME:?Missing event name}"

PRE_BUILD=containerfile
PLATFORMS=linux/amd64,linux/ppc64le,linux/s390x
VERSION=noop
PUSH=true
CONTAINERFILE="${APP}/src/main/container/${KIND}/Containerfile"
CONTAINERFILE_PREBUILD="${APP}/src/main/container/${KIND}/build.Containerfile"
CONTAINERFILE="${APP}/deployment/${KIND}/Containerfile"

if [ "${GITHUB_EVENT_NAME}" = "schedule" ]; then
VERSION=nightly
elif [[ "$GITHUB_REF" == refs/tags/* ]]; then
Expand All @@ -29,15 +28,11 @@ if [[ "${KIND}" == *"native"* ]]; then
VERSION="${VERSION}-native"
PLATFORMS=linux/amd64
fi
if [[ "${KIND}" == *"standalone"* ]]; then
PRE_BUILD=false
fi
if [[ "${APP}" == 'expressjs' ]]; then
VERSION="js-${VERSION}"
if [[ "${VERSION}" == 'js-latest' ]]; then
VERSION="${VERSION} js"
fi
PRE_BUILD=native
CONTAINERFILE="${APP}/deployment/Containerfile"
fi
TAGS="${VERSION}"
Expand All @@ -47,8 +42,6 @@ TAGS="${VERSION}"
echo "tags=${TAGS}"
echo "created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
echo "platforms=${PLATFORMS}"
echo "pre_build=${PRE_BUILD}"
echo "push=${PUSH}"
echo "containerfile=${CONTAINERFILE}"
echo "containerfile_prebuild=${CONTAINERFILE_PREBUILD}"
} >> "$GITHUB_OUTPUT"
47 changes: 10 additions & 37 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---

name: Validate & Test
name: Tests

on:
push:
Expand All @@ -18,8 +18,8 @@ env:
JDK_DISTRO: adopt

jobs:
lint-expressjs:
name: Lint Express app
expressjs:
name: Express backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -29,56 +29,29 @@ jobs:
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
working-directory: expressjs
run: npm install

- name: Run Lints
working-directory: expressjs
run: npm run lint
- name: Test
run: make expressjs
env:
FORCE_COLOR: 1

test-expressjs:
name: Tests Express app
needs:
- lint-expressjs
quarkus:
name: Quarkus backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # fetch all branches and tags

- uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
working-directory: expressjs
run: npm install

- name: Run Tests
working-directory: expressjs
run: npm test
env:
FORCE_COLOR: 1
node-version: ${{ env.NODE_VERSION }}

test-quarkus:
name: Tests Quarkus app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # fetch all branches and tags
- uses: actions/setup-java@v3
with:
distribution: ${{ env.JDK_DISTRO }}
java-version: ${{ env.JDK_VERSION }}

- name: Run Tests
working-directory: quarkus
run: |
./mvnw -V --no-transfer-progress -Dmaven.artifact.threads=50 \
clean dependency:go-offline
./mvnw -V --no-transfer-progress verify -Pnative
run: make quarkus
env:
FORCE_COLOR: 1
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
default: expressjs quarkus

frontend:
+$(MAKE) -C frontend

frontend.clean:
+$(MAKE) -C frontend clean

expressjs:
+$(MAKE) -C expressjs

expressjs.clean:
+$(MAKE) -C expressjs clean

quarkus:
+$(MAKE) -C quarkus

quarkus.clean:
+$(MAKE) -C quarkus clean

clean: frontend.clean expressjs.clean quarkus.clean
cardil marked this conversation as resolved.
Show resolved Hide resolved

.PHONY: default frontend expressjs quarkus clean frontend.clean expressjs.clean quarkus.clean
73 changes: 60 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ Express.JS frameworks.

## Features

The features below are there for two basic reasons. First reason is to showcase
some of the features of the Knative (like scaling, traffic shaping, or event
cardil marked this conversation as resolved.
Show resolved Hide resolved
sending and receiving). The other group is to showcase some basic features
almost every production ready application deployed on Kubernetes should have.
The non-functional features were added, so the apps be close to the real world
apps, and could serve as a reference for developers.
cardil marked this conversation as resolved.
Show resolved Hide resolved

### Knative related features
cardil marked this conversation as resolved.
Show resolved Hide resolved

* [x] Supports the `PORT` env

```bash
Expand All @@ -14,19 +23,6 @@ Express.JS frameworks.
http :$PORT
```

* [x] `/`

```bash
http :8080 user-agent:Mozilla/5.0
# returns a nice hello page when called from Browser

http :8080
# returns a JSON with app's coordinates when called from command line

http options :8080
# returns a JSON with app's coordinates
```

* [x] `/hello`

```bash
Expand All @@ -37,6 +33,36 @@ Express.JS frameworks.
operational delay can be enforced by using `DELAY` (in msec) environmental
variable.

* [x] `/events`

```bash
http :8080/events
```
Returns a stream of Server-Sent Events, where each event is a CloudEvent
represented in structured JSON format. This stream will continue to send next
events if they come.

```bash
kn event send --field a.b=true --to-url http://localhost:8080/events
```
You can send events to the app, by `POST /events` endpoint. Those events will
be stored in ephemeral im-memory storage and send to the listening clients.
cardil marked this conversation as resolved.
Show resolved Hide resolved

### Openshift Serverless related features
cardil marked this conversation as resolved.
Show resolved Hide resolved

* [x] `/` home page ready for Web, and CLI

```bash
http :8080 user-agent:Mozilla/5.0
# returns a React app when called from Browser,
# together with browser for captured CloudEvents

http :8080
# returns a JSON with app's coordinates when called from command line
```

### Supporting features

* [x] K8s readyness and liveness probes

```bash
Expand All @@ -58,3 +84,24 @@ Express.JS frameworks.
```
* [x] Input validation (validation by OpenAPI schema)
* [ ] Distributed Tracing

## Architecture

We've prepared two backend implementations of the above feature. First one is
implemented in Red Hat build of Quarkus framework and live in the `quarkus`
directory. The second backend has been implemented in Express.JS, runs on Node,
and lives in `expressjs` directory. Both of those backend are using single
frontend, written in React framework, in Typescript.

```
├── quarkus/ # Quarkus backend
├── expressjs/ # Express.JS backend
├── frontend/ # React frontend
└── Makefile # Main make file
```

The frontend application builds static Web files. They are packaged as
[Webjar](https://www.webjars.org/documentation) in the user's Maven repository
(`~/.m2/repository`). Thanks to that the Quarkus application is able to use
those static files directly. The express backend needs to extract those webjar
files.
2 changes: 0 additions & 2 deletions expressjs/.dockerignore → expressjs/.containerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
node_modules/
.git
deployment/
test/
2 changes: 2 additions & 0 deletions expressjs/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/
public/
1 change: 1 addition & 0 deletions expressjs/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
build/
public/
npm-debug.log
Loading