Skip to content

Commit 1af3110

Browse files
init
1 parent 1b1fe91 commit 1af3110

File tree

139 files changed

+17065
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+17065
-0
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.git

.github/workflows/build-image.yaml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#
2+
name: Create and publish a Docker image
3+
4+
# Configures this workflow to run every time a change is pushed to the branch called `release`.
5+
on:
6+
push:
7+
tags:
8+
- '*'
9+
10+
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: ${{ github.repository }}
14+
15+
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
16+
jobs:
17+
build-and-push-image:
18+
runs-on: puzl-ubuntu-latest
19+
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
20+
permissions:
21+
contents: read
22+
packages: write
23+
attestations: write
24+
id-token: write
25+
#
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v4
29+
- name: Set up QEMU
30+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
31+
with:
32+
platforms: all
33+
- name: Set up Docker Buildx
34+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
35+
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
36+
- name: Log in to the Container registry
37+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
38+
with:
39+
registry: ${{ env.REGISTRY }}
40+
username: ${{ github.actor }}
41+
password: ${{ secrets.GITHUB_TOKEN }}
42+
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
43+
- name: Extract metadata (tags, labels) for Docker
44+
id: meta
45+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
46+
with:
47+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
48+
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
49+
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see [Usage](https://github.com/docker/build-push-action#usage) in the README of the `docker/build-push-action` repository.
50+
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
51+
- name: Build and push Docker image
52+
id: push
53+
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
54+
with:
55+
context: .
56+
push: true
57+
platforms: linux/amd64,linux/arm64
58+
tags: ${{ steps.meta.outputs.tags }}
59+
labels: ${{ steps.meta.outputs.labels }}
60+
61+
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see [Using artifact attestations to establish provenance for builds](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds).
62+
- name: Generate artifact attestation
63+
uses: actions/attest-build-provenance@v2
64+
with:
65+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
66+
subject-digest: ${{ steps.push.outputs.digest }}
67+
push-to-registry: true
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Python Tests
2+
3+
on:
4+
push:
5+
branches: ['*']
6+
pull_request:
7+
branches: ['*']
8+
9+
jobs:
10+
test:
11+
runs-on: puzl-ubuntu-latest
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
19+
with:
20+
python-version: '3.11'
21+
22+
- name: Cache pip dependencies
23+
uses: puzl-cloud/github-actions-cache@v3
24+
with:
25+
path: ~/.cache/pip
26+
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
27+
restore-keys: |
28+
${{ runner.os }}-pip-
29+
30+
- name: Install dependencies
31+
run: |
32+
pip3 install coverage
33+
pip3 install -r requirements.txt
34+
35+
- name: Run tests
36+
run: |
37+
coverage run -m unittest discover
38+
coverage report -m

.gitignore

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Dependencies
2+
/node_modules
3+
4+
# Production
5+
/build
6+
7+
# Generated files
8+
.docusaurus
9+
.cache-loader
10+
11+
# Misc
12+
.DS_Store
13+
.env.local
14+
.env.development.local
15+
.env.test.local
16+
.env.production.local
17+
18+
npm-debug.log*
19+
yarn-debug.log*
20+
yarn-error.log*
21+
22+
23+
# Byte-compiled / optimized / DLL files
24+
__pycache__/
25+
*.py[cod]
26+
*$py.class
27+
28+
# C extensions
29+
*.so
30+
31+
# Distribution / packaging
32+
.Python
33+
build/
34+
develop-eggs/
35+
dist/
36+
downloads/
37+
eggs/
38+
.eggs/
39+
lib/
40+
!ui/**/lib/
41+
lib64/
42+
parts/
43+
sdist/
44+
var/
45+
wheels/
46+
share/python-wheels/
47+
*.egg-info/
48+
.installed.cfg
49+
*.egg
50+
MANIFEST
51+
52+
# PyInstaller
53+
# Usually these files are written by a python script from a template
54+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
55+
*.manifest
56+
*.spec
57+
58+
# Installer logs
59+
pip-log.txt
60+
pip-delete-this-directory.txt
61+
62+
# Unit test / coverage reports
63+
htmlcov/
64+
.tox/
65+
.nox/
66+
.coverage
67+
.coverage.*
68+
.cache
69+
nosetests.xml
70+
coverage.xml
71+
*.cover
72+
.hypothesis/
73+
.pytest_cache/
74+
75+
# Translations
76+
*.mo
77+
*.pot
78+
79+
# Django stuff:
80+
*.log
81+
local_settings.py
82+
db.sqlite3
83+
84+
# Flask stuff:
85+
instance/
86+
.webassets-cache
87+
88+
# Scrapy stuff:
89+
.scrapy
90+
91+
# Sphinx documentation
92+
docs/_build/
93+
94+
# PyBuilder
95+
target/
96+
97+
# Jupyter Notebook
98+
.ipynb_checkpoints
99+
100+
# IPython
101+
profile_default/
102+
ipython_config.py
103+
104+
# pyenv
105+
.python-version
106+
107+
# celery beat schedule file
108+
celerybeat-schedule
109+
110+
# SageMath parsed files
111+
*.sage.py
112+
113+
# Environments
114+
.env
115+
.venv
116+
env/
117+
venv/
118+
ENV/
119+
env.bak/
120+
venv.bak/
121+
122+
# Spyder project settings
123+
.spyderproject
124+
.spyproject
125+
126+
# Rope project settings
127+
.ropeproject
128+
129+
# mkdocs documentation
130+
/site
131+
132+
# mypy
133+
.mypy_cache/
134+
.dmypy.json
135+
dmypy.json
136+
137+
# Pyre type checker
138+
.pyre/
139+
140+
# Pycharm
141+
/.idea
142+
143+
# Local .terraform directories
144+
**/.terraform/*
145+
146+
# .tfstate files
147+
*.tfstate
148+
*.tfstate.*
149+
150+
# Crash log files
151+
crash.log
152+
153+
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
154+
# .tfvars files are managed as part of configuration and so should be included in
155+
# version control.
156+
#
157+
# example.tfvars
158+
159+
# Ignore override files as they are usually used to override resources locally and so
160+
# are not checked in
161+
override.tf
162+
override.tf.json
163+
*_override.tf
164+
*_override.tf.json
165+
166+
# Include override files you do wish to add to version control using negated pattern
167+
#
168+
# !example_override.tf
169+
170+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
171+
# example: *tfplan*
172+
173+
**/package/*
174+
*.zip
175+
176+
# Tmp files
177+
.tmp
178+
tmp/
179+
tmp1/
180+
181+
.npmrc
182+
__crd-source-dev
183+
app-populated
184+
_k8s_version
185+
crd
186+
crd_docs_generator/final_docs
187+
188+
html/

Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
ARG NODE_TAG=22-slim
2+
ARG PYTHON_VERSION=3.11
3+
ARG PYTHON_TAG=$PYTHON_VERSION-slim
4+
5+
FROM node:$NODE_TAG AS node-build
6+
7+
WORKDIR /app
8+
COPY ui/ .
9+
10+
RUN npm install
11+
12+
RUN npm run build
13+
14+
FROM python:$PYTHON_TAG AS python-build
15+
16+
WORKDIR /tmp
17+
18+
COPY requirements.txt .
19+
20+
RUN pip3 install -r requirements.txt
21+
22+
FROM python:$PYTHON_TAG
23+
ARG PYTHON_VERSION
24+
25+
ENV LISTEN_PORT=3000 \
26+
PYTHONPATH=/usr/local/lib/python$PYTHON_VERSION/site-packages
27+
28+
WORKDIR /app
29+
30+
COPY --from=node-build app/dist html
31+
COPY --from=python-build /usr/local/lib/python$PYTHON_VERSION/site-packages /usr/local/lib/python$PYTHON_VERSION/site-packages
32+
33+
COPY . .
34+
35+
RUN apt-get update \
36+
&& apt-get install --no-install-recommends -y \
37+
git
38+
39+
CMD ["python3", "app.py"]

app.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import logging
2+
3+
from sanic import Sanic
4+
5+
from env import *
6+
from src.utils.sanic_utils import catch_signals, register_custom_error_handler
7+
from src.api import health_bp, api_bp, static_bp
8+
9+
logging.basicConfig()
10+
logging.getLogger().setLevel(logging.INFO)
11+
12+
13+
APP_NAME = "github-workflow-assistant"
14+
app = Sanic(APP_NAME)
15+
app.config.API_VERSION = "0.0.1"
16+
app.config.API_TITLE = APP_NAME
17+
app.config.API_PRODUCES_CONTENT_TYPES = ['application/json']
18+
19+
# API routes
20+
app.blueprint(health_bp)
21+
app.blueprint(api_bp)
22+
app.blueprint(static_bp)
23+
24+
# Customize error responses
25+
register_custom_error_handler(app)
26+
27+
# Terminate the app gracefully
28+
app.add_task(catch_signals(app))
29+
30+
# Use keep alive to match Chrome's AJAX requests
31+
app.config.KEEP_ALIVE_TIMEOUT = 180
32+
33+
34+
if __name__ == '__main__':
35+
ssl = {'cert': SSL_CERT_PATH, 'key': SSL_KEY_PATH} if SSL_CERT_PATH and SSL_KEY_PATH else None
36+
try:
37+
logging.info(f"{APP_NAME} started: v{app.config.API_VERSION}", extra={"version": app.config.API_VERSION})
38+
app.run(host=LISTEN_HOST, port=LISTEN_PORT, ssl=ssl)
39+
except KeyboardInterrupt:
40+
logging.info(f"Got KeyboardInterrupt. {APP_NAME} terminated successfully.")
41+
exit(0)

0 commit comments

Comments
 (0)