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

Working container ping in github action #13

Merged
merged 13 commits into from
Jun 3, 2024
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
12 changes: 12 additions & 0 deletions .env.default
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# this file lists all environment variables needed by this app

PSQL_HOST=localhost #pragma: allowlist secret
PSQL_PORT=5432 #pragma: allowlist secret
PSQL_USER=postgres #pragma: allowlist secret
PSQL_PASSWORD=admin123456 #pragma: allowlist secret
PSQL_DATABASE_NAME=test #pragma: allowlist secret

REDIS_HOST=localhost #pragma: allowlist secret
REDIS_PORT=6379 #pragma: allowlist secret
REDIS_USER=admin #pragma: allowlist secret
REDIS_PASSWORD=admin123456 #pragma: allowlist secret
12 changes: 12 additions & 0 deletions .github/actions/docker-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Setup DOCKER
runs:
using: composite
steps:
- name: Cache Docker images.
uses: ScribeMD/[email protected]
with:
key: docker-${{ runner.os }}-${{ hashFiles('Dockerfile') }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
39 changes: 39 additions & 0 deletions .github/inactive/app-start.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# this workflow will build the docker file and verify the image gets up and running
name: App Start Workflow
on:
push:
branches:
- dev
workflow_dispatch: {}
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# - name: Build Docker Image
# run: docker build -t myapp .
# - name: Run Docker Image
# run: docker run -d -p 8080:8080 myapp
# - name: Verify Docker Image
# run: curl -s http://localhost:8080 | grep "Hello World"
- name: Setup DOCKER environment
uses: ./.github/actions/docker-setup
- name: Build and export to docker
uses: docker/build-push-action@v5
with:
push: false
context: .
file: ./Dockerfile
load: true # load the image after building so it can be used in the next steps
platforms: linux/amd64
tags: gipo999/tomcat-webapp-boilerplate:latest
# - name: Test docker image
# run: |
# docker run --rm ${{ env.TEST_TAG }}
- name: Run docker image
run: |
docker run -d -p 8080:8080 gipo999/tomcat-webapp-boilerplate:latest
- name: Verify docker image endpoint
run: |
curl -s http://localhost:8080/tomcat-webapp-boilerplate/app/base/health | grep "Hello World"
75 changes: 61 additions & 14 deletions .github/workflows/gradle-check-build.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
name: Gradle Check and Build Workflow
env:
TEST_TAG: gipo999/tomcat-webapp-boilerplate:test
on:
pull_request:
branches: ["dev"]
# push:
# branches: ["app-start-test"]
workflow_dispatch: {}
jobs:
build-linux:
Expand All @@ -11,22 +15,65 @@ jobs:
steps:
- name: Checkout sources Step
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4
- uses: ./.github/actions/ci-setup
name: Setup CI environment
- name: Setup CI environment
uses: ./.github/actions/ci-setup
# run the gradle check and build tasks
- name: Build with Gradle Wrapper Step
run: ./gradlew build
# buildWar runs check, test, war tasks
# at this point we won't know if the app will run in a container
run: ./gradlew buildWar
- name: Upload coverage to Codecov
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
build-windows:
if: github.event.pull_request.draft == false
name: Lint and Build on Windows Job
runs-on: windows-latest
steps:
- name: Checkout sources Step
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4
- uses: ./.github/actions/ci-setup
name: Setup CI environment
- name: Build with Gradle Wrapper Step
run: ./gradlew build
# test the docker image
- name: Setup DOCKER environment
uses: ./.github/actions/docker-setup
- name: Build and export to docker
uses: docker/build-push-action@v5
with:
push: false
context: .
file: ./Dockerfile
load: true # load the image after building so it can be used in the next steps
platforms: linux/amd64
tags: ${{ env.TEST_TAG }}
# - name: Test docker image
# run: |
# docker run --rm ${{ env.TEST_TAG }}
- name: Run docker image
run: |
docker run -d -p 8080:8080 ${{ env.TEST_TAG }}
# - name: Verify docker image endpoint
# # it returns 200 with json {"status":"UP"}
# run: |
# curl -s http://localhost:8080/tomcat-webapp-boilerplate/app/base/health | grep "UP"
- name: Test docker image endpoint
# Use the retry action
uses: nick-fields/retry@v3
with:
max_attempts: 5
retry_on: error
timeout_seconds: 10
# You can specify the shell commands you want to retry here
command: |
curl -s http://localhost:8080/tomcat-webapp-boilerplate/app/base/health | grep "UP"

# pen test and put comment in pr with the results now using PR image
# we will replicate the pen test with cron on another action on the dev branch tag released image

#
#
# we don't care about windows for this app since it only runs on linux
# build-windows:
# if: github.event.pull_request.draft == false
# name: Lint and Build on Windows Job
# runs-on: windows-latest
# steps:
# - name: Checkout sources Step
# uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4
# - uses: ./.github/actions/ci-setup
# name: Setup CI environment
# - name: Build with Gradle Wrapper Step
# # buildWar runs check and test tasks
# run: ./gradlew buildWar
87 changes: 54 additions & 33 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
# steps:
# 1. build image on java image
# 2. move war to tomcat image
# 3. run tomcat image

FROM eclipse-temurin:21@sha256:2e387a63a9086232a53fb668f78bcda1f233118f234326fcb88b0bb2a968ec39 as BUILD_IMAGE

# VULN: should probably not run as root

# VULN: should probably move to alpine, preferably embedding tomcat in the app

# initialize defaults for overriding through --env

# example
ENV INFISICAL_TOKEN=''

ENV PORT=8080

RUN mkdir -p /home/app

WORKDIR /home/app

COPY . /home/app

WORKDIR /home/app

RUN ./gradlew war

## MULTI STAGE

FROM tomcat:9-jdk21-temurin-jammy@sha256:f7c4623aa616f46473003b325246befcc5fe7120b39b07c977dd44057bbdc306

COPY --from=BUILD_IMAGE /home/app/build/libs/* /usr/local/tomcat/webapps
# # steps:
# # 1. build image on java image
# # 2. move war to tomcat image
# # 3. run tomcat image
#
# # FROM eclipse-temurin:21@sha256:2e387a63a9086232a53fb668f78bcda1f233118f234326fcb88b0bb2a968ec39 as BUILD_IMAGE
# FROM gradle:8-jdk21 as BUILD_IMAGE
#
# # VULN: should probably not run as root
#
# # VULN: should probably move to alpine, preferably embedding tomcat in the app
#
# # initialize defaults for overriding through --env
#
# # example
# ENV INFISICAL_TOKEN=''
#
# ENV PORT=8080
#
# RUN mkdir -p /home/app
#
# WORKDIR /home/app
#
# COPY . /home/app
#
# WORKDIR /home/app
#
# # RUN ./gradlew war
# # if we don't use the wrapper, we can use the gradle image and prevent
# # downloading gradle every time which takes ALOT and allows for caching
# RUN gradle war

FROM tomcat:9-jdk21

# If not using multistage: docker file expects the war file to be in the build/libs folder.
# if we build it outside we can use github action gradle caching
# to make the build faster

## IF MULTI STAGE
# COPY --from=BUILD_IMAGE /home/app/build/libs/* /usr/local/tomcat/webapps
## else
COPY build/libs/* /usr/local/tomcat/webapps

RUN adduser tomcat

RUN chown -R tomcat:tomcat /usr/local/tomcat/webapps

# FIXME: this should be run in the compose or cli command to run
# HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=30s \
# CMD curl --fail http://localhost:8080/tomcat-webapp-boilerplate/api/base/health || exit 1
# HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=30s \
# CMD curl --fail http://localhost:8080/wrong || exit 1

USER tomcat

EXPOSE ${PORT}

Expand Down
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,32 @@ compose up -d

# env vars

SEMGREP_APP_TOKEN
DOCKERHUB_TOKEN
DOCKERHUB_USERNAME
SNYK_TOKEN
PAT
CODECOV_TOKEN
- SEMGREP_APP_TOKEN
- DOCKERHUB_TOKEN
- DOCKERHUB_USERNAME
- SNYK_TOKEN
- PAT
- CODECOV_TOKEN

# feats

- gradle

- docker

- compose
auto restart on src change

- pre commit

- post commit

- pre push

- on pr
test, check, war, tomcat /health
vulnerability checks on container and image

- on dev push

- cron
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ project.webAppDirName = 'src/main/webapp'
// IMP: compatibliity with tomcat 9?
// jersey 2+ works only with tomcat 9+
// jersey 3+ works only with tomcat 10+
// check docke compose file
// check docker compose file
// https://stackoverflow.com/questions/62595510/severe-servlet-jersey-web-application-in-web-application-restapp-threw-loa
def JERSEY_VERSION = "2+"
def TOMCAT_VERSION = "9+"
Expand Down Expand Up @@ -133,7 +133,7 @@ spotless {
format 'xml', {
target '**/*.xml'

targetExclude 'build/**/*', 'node_modules/**/*', 'target/**/*', 'out/**/*', 'dist/**/*', 'bin/**/*'
targetExclude 'build/**/*', 'node_modules/**/*', 'target/**/*', 'out/**/*', 'dist/**/*', 'bin/**/*', 'tomcat/**/*'

eclipseWtp('xml')
}
Expand Down Expand Up @@ -223,6 +223,8 @@ jacocoTestReport {
}
}

// we provide another command as we need to run war in CI without running the tests
// check requires nodejs
// war {
// dependsOn 'check'
// dependsOn 'test'
Expand Down
67 changes: 63 additions & 4 deletions compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,75 @@
# TODO: possibly use only compose with 1 container with nodemon and tomcat
#
# this is a dev only compose file that will be used to start the services needed
# and provide live reload for the tomcat webapp by running npm run dev
#
# network mode exposes the service directly to the host, no mapping needed
# requires ports available on the host

services:
tomcat-webapp-boilerplate:
# environment:
# image: tomcat:9-jdk21-temurin-jammy
build:
dockerfile: ./docker/tomcat.Dockerfile
# dockerfile: ./docker/tomcat.Dockerfile
dockerfile: ./Dockerfile
container_name: tomcat-webapp-boilerplate
env_file: ./.env
develop:
# watch allows to sync files from host to container
watch:
- action: sync+restart
path: "build/libs/"
path: "./build/libs/"
target: "/usr/local/tomcat/webapps/"
network_mode: host
ports:
- 127.0.0.1:8080:8080
# ports:
# - 127.0.0.1:8080:8080
########## postgres
postgresdev:
env_file: ./.env
image: postgres:latest
# restart: unless-stopped
# user: postgres
network_mode: host
# ports:
# - 127.0.0.1:5432:5432
# - 5432:5432
container_name: postgresdev
volumes:
# - ~/data/postgres:/var/lib/postgresql/data
- /tmp/db/psql:/var/lib/postgresql/data
environment:
POSTGRES_USER: ${PSQL_USER} # default
POSTGRES_PASSWORD: ${PSQL_PASSWORD}
POSTGRES_DB: ${PSQL_DATABASE_NAME}
pgadmin:
container_name: pgadmin4_container
image: dpage/pgadmin4:latest
# restart: unless-stopped
network_mode: host
depends_on:
- postgresdev
environment:
PGADMIN_DEFAULT_EMAIL: [email protected] #pragma: allowlist secret
PGADMIN_DEFAULT_PASSWORD: admin #pragma: allowlist secret
# PGADMIN_LISTEN_PORT: 9001
# ports:
# - 127.0.0.1:9001:80
# - 9001:80
########## redis
redisdev:
env_file: ./.env
image: redis/redis-stack:latest
# user: redis
# restart: unless-stopped
network_mode: host
# ports:
# - 127.0.0.1:6379:6379
# - 127.0.0.1:9002:8001 # redis insight
container_name: redisdev
# volumes:
# - ~/data/redis:/data
# - /tmp/db/redis:/data
environment:
# default user is: default
- REDIS_ARGS=--save 60 1000 --appendonly yes --loglevel warning --requirepass ${REDIS_PASSWORD}
Loading
Loading