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

wip: added charm config #117

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c5d76b7
wip: added charm config
samhotep Jan 28, 2025
a352567
fix: start even if directory api is unreachable
samhotep Jan 28, 2025
2722d96
chore: update linter to exclude charm/*
samhotep Jan 28, 2025
7ee12d4
fix: bug when checking for existing webpages
samhotep Jan 28, 2025
a8eb0b9
feat: revert to filecache if redis not available
samhotep Feb 18, 2025
a143a01
chore: removed default debug in local
samhotep Feb 18, 2025
d41b2b9
fix: run periodic tasks on celery configure
samhotep Feb 18, 2025
e9fd892
feat: added juju deployment CI
samhotep Feb 19, 2025
7132787
fix: use redis for ci
samhotep Feb 19, 2025
7da9d10
fix: create rock directories
samhotep Feb 19, 2025
8418eeb
feat: removed git dependency
samhotep Feb 21, 2025
b0114dd
feat: Added copydoctemplate id
samhotep Feb 24, 2025
7204321
chore: lint python
samhotep Feb 24, 2025
00ae8d2
fix: name controller in deployment
samhotep Feb 24, 2025
0a9830e
feat: auto rollback on error
samhotep Feb 27, 2025
3fbc225
feat: directly import google credentials
samhotep Feb 27, 2025
245ba1c
feat: use scoped sessions
samhotep Feb 27, 2025
7574588
fix: updated juju deploy controller
samhotep Feb 27, 2025
eaf1046
fix: update vault read controller
samhotep Feb 27, 2025
86fb311
feat: default to flask_ prefix variables
samhotep Feb 27, 2025
62defc5
feat: ping jira server on startup and report
samhotep Feb 27, 2025
ec8b793
chore: remove unused var
samhotep Feb 27, 2025
a14f010
feat: add google auth check on startup
samhotep Feb 27, 2025
6a114b6
feat: added prod deployment
samhotep Mar 4, 2025
59cc02c
feat: updated repo directory perms
samhotep Mar 4, 2025
60edcbb
feat: make redis optional in charm
samhotep Mar 4, 2025
63da450
feat: reload tree if webpages are incomplete
samhotep Mar 4, 2025
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
4 changes: 2 additions & 2 deletions .env
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PORT=8104
SECRET_KEY=secret_key
VALKEY_HOST=localhost
VALKEY_PORT=6379
REDIS_HOST=localhost
REDIS_PORT=6379
GH_TOKEN=token
REPO_ORG=https://github.com/canonical
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/content
Expand Down
26 changes: 14 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,19 @@ jobs:
name: Run Python
runs-on: ubuntu-latest
services:
valkey:
image: valkey/valkey
redis:
image: redis
options: >-
--health-cmd "valkey-cli ping"
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
postgres:
image: postgres:latest
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.12
Expand All @@ -121,9 +123,9 @@ jobs:
GOOGLE_PRIVATE_KEY_ID: ${{ secrets.PRIVATE_KEY_ID }}
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
SECRET_KEY: secret_key
VALKEY_HOST: localhost
VALKEY_PORT: 6379
GH_TOKEN: token
REDIS_HOST: localhost
REDIS_PORT: 6379
GH_TOKEN: ${{ github.token }}
REPO_ORG: https://github.com/canonical
JIRA_EMAIL: [email protected]
JIRA_TOKEN: jiratoken
Expand All @@ -141,10 +143,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
services:
valkey:
image: valkey/valkey
redis:
image: redis
options: >-
--health-cmd "valkey-cli ping"
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
Expand All @@ -170,9 +172,9 @@ jobs:
docker run \
-p 8104:8104 \
-e SECRET_KEY=secret_key \
-e VALKEY_HOST=localhost \
-e VALKEY_PORT=6379 \
-e GH_TOKEN=token \
-e REDIS_HOST=localhost \
-e REDIS_PORT=6379 \
-e GH_TOKEN=${{ github.token }} \
-e REPO_ORG=https://github.com/canonical \
-e DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres \
-e [email protected] \
Expand Down
160 changes: 160 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
name: Deploy

on:
push:
branches:
- add-charm

env:
CHARMCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: true
ROCKCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: true

jobs:
pack-charm:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Setup LXD
uses: canonical/setup-lxd@main

- name: Setup Charmcraft
run: sudo snap install charmcraft --classic --channel=latest/edge

- name: Pack charm
run: charmcraft pack -v --project-dir ./charm

- name: Upload charm
uses: actions/upload-artifact@v4
with:
name: cs-canonical-com-charm
path: ./*.charm

pack-rock:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3

- name: Build Assets
run: |
yarn install
yarn run build

- name: Setup LXD
uses: canonical/setup-lxd@main

- name: Create repositories directory
run: |
mkdir -m 777 repositories
mkdir -m 777 tree-cache

- name: Setup Rockcraft
run: sudo snap install rockcraft --classic --channel=latest/edge

- name: Pack Rock
run: rockcraft pack

- name: Upload Rock
uses: actions/upload-artifact@v4
with:
name: cs-canonical-com-rock
path: ./*.rock

publish-image:
runs-on: ubuntu-latest
needs: pack-rock
outputs:
image_url: ${{ steps.set_image_url.outputs.image_url }}
steps:
- name: Get Rock
uses: actions/download-artifact@v4
with:
name: cs-canonical-com-rock

- name: Set image URL
id: set_image_url
run: echo "image_url=ghcr.io/canonical/cs.canonical.com:$(date +%s)-${GITHUB_SHA:0:7}" >> $GITHUB_OUTPUT

- name: Push to GHCR
run: skopeo --insecure-policy copy oci-archive:$(ls *.rock) docker://${{ steps.set_image_url.outputs.image_url }} --dest-creds "canonical:${{ secrets.GITHUB_TOKEN }}"

deploy-staging:
runs-on: [self-hosted, self-hosted-linux-amd64-jammy-private-endpoint-medium]
needs: [pack-charm, publish-image]
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Dependencies
run: |
sudo snap install juju --channel=3.4/stable --classic
sudo snap install vault --classic

- name: Download Charm Artifact
uses: actions/download-artifact@v4
with:
name: cs-canonical-com-charm

- name: Configure Vault and Juju
run: |
export VAULT_ADDR=https://vault.admin.canonical.com:8200
export TF_VAR_login_approle_role_id=${{ secrets.VAULT_APPROLE_ROLE_ID }}
export TF_VAR_login_approle_secret_id=${{ secrets.VAULT_APPROLE_SECRET_ID }}
export VAULT_SECRET_PATH_ROLE=secret/prodstack6/roles/stg-cs-canonical-com
export VAULT_SECRET_PATH_COMMON=secret/prodstack6/juju/common
VAULT_TOKEN=$(vault write -f -field=token auth/approle/login role_id=${TF_VAR_login_approle_role_id} secret_id=${TF_VAR_login_approle_secret_id})
export VAULT_TOKEN
mkdir -p ~/.local/share/juju
vault read -field=controller_config "${VAULT_SECRET_PATH_COMMON}/controllers/juju-controller-36-staging-ps6" | base64 -d > ~/.local/share/juju/controllers.yaml
USERNAME=$(vault read -field=username "${VAULT_SECRET_PATH_ROLE}/juju")
PASSWORD=$(vault read -field=password "${VAULT_SECRET_PATH_ROLE}/juju")
printf "controllers:\n juju-controller-36-staging-ps6:\n user: %s\n password: %s\n" "$USERNAME" "$PASSWORD" > ~/.local/share/juju/accounts.yaml

- name: Deploy Application to staging
run: |
export JUJU_MODEL=admin/stg-cs-canonical-com
juju refresh cs-canonical-com --path ./cs-canonical-com_ubuntu-22.04-amd64.charm --resource flask-app-image=${{ needs.publish-image.outputs.image_url }}
juju wait-for application cs-canonical-com --query='name=="cs-canonical-com" && (status=="active" || status=="idle")'

deploy-production:
runs-on: [self-hosted, self-hosted-linux-amd64-jammy-private-endpoint-medium]
needs: [pack-charm, publish-image]
steps:
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Dependencies
run: |
sudo snap install juju --channel=3.6/stable --classic
sudo snap install vault --classic

- name: Download Charm Artifact
uses: actions/download-artifact@v4
with:
name: cs-canonical-com-charm

- name: Configure Vault and Juju
run: |
export VAULT_ADDR=https://vault.admin.canonical.com:8200
export TF_VAR_login_approle_role_id=${{ secrets.PROD_VAULT_APPROLE_ROLE_ID }}
export TF_VAR_login_approle_secret_id=${{ secrets.PROD_VAULT_APPROLE_SECRET_ID }}
export VAULT_SECRET_PATH_ROLE=secret/prodstack6/roles/prod-cs-canonical-com
export VAULT_SECRET_PATH_COMMON=secret/prodstack6/juju/common
VAULT_TOKEN=$(vault write -f -field=token auth/approle/login role_id=${TF_VAR_login_approle_role_id} secret_id=${TF_VAR_login_approle_secret_id})
export VAULT_TOKEN
mkdir -p ~/.local/share/juju
vault read -field=controller_config "${VAULT_SECRET_PATH_COMMON}/controllers/juju-controller-36-production-ps6" | base64 -d > ~/.local/share/juju/controllers.yaml
USERNAME=$(vault read -field=username "${VAULT_SECRET_PATH_ROLE}/juju")
PASSWORD=$(vault read -field=password "${VAULT_SECRET_PATH_ROLE}/juju")
printf "controllers:\n juju-controller-36-production-ps6:\n user: %s\n password: %s\n" "$USERNAME" "$PASSWORD" > ~/.local/share/juju/accounts.yaml

- name: Deploy Application to production
run: |
export JUJU_MODEL=admin/prod-cs-canonical-com
juju refresh cs-canonical-com --path ./cs-canonical-com_ubuntu-22.04-amd64.charm --resource flask-app-image=${{ needs.publish-image.outputs.image_url }}
juju wait-for application cs-canonical-com --query='name=="cs-canonical-com" && (status=="active" || status=="idle")'
4 changes: 2 additions & 2 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ jobs:
env:
DISABLE_SSO: True
SECRET_KEY: secret_key
VALKEY_HOST: localhost
VALKEY_PORT: 6379
REDIS_HOST: localhost
REDIS_PORT: 6379
GH_TOKEN: token
REPO_ORG: https://github.com/canonical
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ COPY . .

# Install python and import python dependencies
RUN apt-get update \
&& apt-get install --no-install-recommends --yes ca-certificates git python3-venv python3-pip python3-psycopg2
&& apt-get install --no-install-recommends --yes ca-certificates python3-venv python3-pip python3-psycopg2
RUN python3 -m venv .venv \
&& . .venv/bin/activate \
&& pip install --no-cache-dir -r requirements.txt
Expand Down
52 changes: 46 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Template parser backend
# Websites Content System

Backend service for the CMS template parser
This is a portal tailored to managing content on our websites. It's useful for:
- Making change requests on specific pages, and automating the related JIRA overhead
- Assigning owners to individual pages
- Collecting all relevant links for a page in one place:
- copydoc link
- link to github code
- product category

## Getting it running

Expand All @@ -17,8 +23,8 @@ PORT=8104
FLASK_DEBUG=true
SECRET_KEY=secret_key
DEVEL=True
VALKEY_HOST=valkey
VALKEY_PORT=6379
REDIS_HOST=valkey
REDIS_PORT=6379
GH_TOKEN=ghp_somepersonaltoken
REPO_ORG=https://github.com/canonical
DATABASE_URL=postgresql://postgres:postgres@postgres:5432/postgres
Expand Down Expand Up @@ -208,8 +214,8 @@ Then modify the .env file, and change the following to match your valkey and pos

```
# .env
VALKEY_HOST=localhost
VALKEY_PORT=6379
REDIS_HOST=localhost
REDIS_PORT=6379
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
```

Expand Down Expand Up @@ -257,6 +263,40 @@ To ensure hot module reloading, make sure to do the following changes.
- Comment out <code>"process.env.NODE_ENV": '"production"'</code> in vite.config.ts file.
- Run the vite dev server locally, using <code>yarn run dev</code>.

### Background tasks

### Creating tasks

You can create a background task for Celery in your Flask application by following these steps:

1. Create a task by decorating a function with `@celery.task`:

```python
from webapp.celery_config import celery

@shared_task
def my_background_task():
# Task logic here
pass
```

2. Call the task from your Flask route:

```python
@app.route('/call-task')
def some_route():
my_background_task.delay() # async
# or
my_background_task.apply_async(countdown=60) # run after 60s
return 'Task started'
```

Both periodic and regular tasks can then be run with:

```bash
celery -A webapp.app.celery_app worker -B --loglevel=INFO
```

### API Requests

#### Getting the website page structure as a JSON tree
Expand Down
1 change: 1 addition & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from webapp.app import app # noqa F401
9 changes: 9 additions & 0 deletions charm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
venv/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it be .venv?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's created by default by the charm initialization, along with some charm src files, so I've left it as is

build/
*.charm
.tox/
.coverage
__pycache__/
*.py[cod]
.idea
.vscode/
Loading