Skip to content
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
5 changes: 5 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ REPO_ORG=https://github.com/canonical
SQLALCHEMY_DATABASE_URI=postgresql://postgres:postgres@localhost:5432/postgres
TASK_DELAY=30
DIRECTORY_API_TOKEN=token
JIRA_EMAIL=email@example.com
JIRA_TOKEN=token
JIRA_URL=https://warthogs.atlassian.net
JIRA_LABELS=sites_BAU
JIRA_COPY_UPDATES_EPIC=KAN-1
5 changes: 5 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ jobs:
-e GH_TOKEN=token \
-e REPO_ORG=https://github.com/canonical \
-e SQLALCHEMY_DATABASE_URI=postgresql://postgres:postgres@localhost:5432/postgres \
-e JIRA_EMAIL=example@canonical.com \
-e JIRA_TOKEN=jiratoken \
-e JIRA_URL=https://example.atlassian.net \
-e JIRA_LABELS=somelabel \
-e JIRA_COPY_UPDATES_EPIC=WD-9999999 \
--network host \
websites-content-system & sleep 1
curl --head --fail --retry-delay 1 --retry 30 --retry-connrefused http://localhost
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,20 @@ $ docker inspect <postgres-container-id> | grep IPAddress
"name": "/",
"title": null
}
}
```

#### Making a webpage update request

<details>
<summary><code>POST</code> <code><b>/request-changes</b></code>
</details>

```json
{
"due_date": "2022-01-01",
"reporter_id": 1,
"webpage_id": 31,
"type": 1,
"description": "This is a description",
}
19 changes: 19 additions & 0 deletions konf/site.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ env:
key: token
name: directory-api

- name: JIRA_EMAIL
secretKeyRef:
key: jira-email
name: cms-jira

- name: JIRA_TOKEN
secretKeyRef:
key: jira-token
name: cms-jira

- name: JIRA_URL
value: "https://warthogs.atlassian.net"

- name: JIRA_LABELS
value: "sites_BAU"

- name: JIRA_COPY_UPDATES_EPIC
value: "WD-12643"

# Overrides for production
production:
replicas: 1
Expand Down
38 changes: 38 additions & 0 deletions migrations/versions/7b0c727c0201_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""empty message

Revision ID: 7b0c727c0201
Revises: c4073a9759fc
Create Date: 2024-09-19 10:41:48.215628

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '7b0c727c0201'
down_revision = 'c4073a9759fc'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('jira_tasks', schema=None) as batch_op:
batch_op.alter_column('jira_id',
existing_type=sa.INTEGER(),
type_=sa.String(),
existing_nullable=True)

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('jira_tasks', schema=None) as batch_op:
batch_op.alter_column('jira_id',
existing_type=sa.String(),
type_=sa.INTEGER(),
existing_nullable=True)

# ### end Alembic commands ###
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ multiprocess==0.70.16
psycopg2-binary==2.9.9
PyYAML==6.0.2
Flask-Migrate==4.0.7
Flask-Pydantic==0.12.0
Flask-SQLAlchemy==3.1.1
talisker[gunicorn,gevent,flask,prometheus,raven]==0.21.3
valkey==6.0.0b1
Expand Down
4 changes: 4 additions & 0 deletions webapp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from webapp.cache import init_cache
from webapp.context import base_context
from webapp.jira import init_jira
from webapp.models import init_db
from webapp.sso import init_sso
from webapp.tasks import init_tasks
Expand All @@ -26,4 +27,7 @@ def create_app():
# Initialize tasks
init_tasks(app)

# Initialize JIRA
init_jira(app)

return app
61 changes: 39 additions & 22 deletions webapp/app.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from os import environ

import requests
from flask import jsonify, render_template, request
from flask_pydantic import validate

from webapp import create_app
from webapp.helper import create_jira_task, get_or_create_user_id
from webapp.models import Reviewer, Webpage, db, get_or_create
from webapp.schemas import (
ChangesRequestModel,
)
from webapp.site_repository import SiteRepository
from webapp.sso import login_required
from webapp.tasks import LOCKS
from webapp.models import get_or_create, db, Reviewer, Webpage
from webapp.helper import get_or_create_user_id

import requests

app = create_app()

Expand Down Expand Up @@ -43,7 +46,7 @@ def index(path):
return render_template("index.html")


@app.route('/get-users/<username>', methods=['GET'])
@app.route("/get-users/<username>", methods=["GET"])
@login_required
def get_users(username: str):
query = """
Expand All @@ -59,27 +62,28 @@ def get_users(username: str):
}
"""

headers = {
"Authorization": "token " + environ.get("DIRECTORY_API_TOKEN")
}
headers = {"Authorization": "token " + environ.get("DIRECTORY_API_TOKEN")}

# Currently directory-api only supports strict comparison of field values,
# so we have to send two requests instead of one for first and last names
response = requests.post(
"https://directory.wpe.internal/graphql/", json={
'query': query,
'variables': {'name': username.strip()},
}, headers=headers, verify=False)

if (response.status_code == 200):
users = response.json().get('data', {}).get(
'employees', [])
"https://directory.wpe.internal/graphql/",
json={
"query": query,
"variables": {"name": username.strip()},
},
headers=headers,
verify=False,
)

if response.status_code == 200:
users = response.json().get("data", {}).get("employees", [])
return jsonify(list(users))
else:
return jsonify({"error": "Failed to fetch users"}), 500


@app.route('/set-reviewers', methods=['POST'])
@app.route("/set-reviewers", methods=["POST"])
@login_required
def set_reviewers():
data = request.get_json()
Expand All @@ -99,15 +103,14 @@ def set_reviewers():

# Create new reviewer rows
for user_id in user_ids:
get_or_create(db.session,
Reviewer,
user_id=user_id,
webpage_id=webpage_id)
get_or_create(
db.session, Reviewer, user_id=user_id, webpage_id=webpage_id
)

return jsonify({"message": "Successfully set reviewers"}), 200


@app.route('/set-owner', methods=['POST'])
@app.route("/set-owner", methods=["POST"])
@login_required
def set_owner():
data = request.get_json()
Expand All @@ -123,3 +126,17 @@ def set_owner():
db.session.commit()

return jsonify({"message": "Successfully set owner"}), 200


@app.route("/request-changes", methods=["POST"])
@login_required
@validate()
def request_changes(body: ChangesRequestModel):

# Make a request to JIRA to create a task
try:
create_jira_task(app, body.model_dump())
except Exception as e:
return jsonify(str(e)), 500

return jsonify("Task created successfully"), 201
45 changes: 36 additions & 9 deletions webapp/helper.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
from webapp.models import get_or_create, db, User
from webapp.models import JiraTask, User, db, get_or_create


def get_or_create_user_id(user):
# If user does not exist, create a new user in the "users" table
user_hrc_id = user.get("id")
user_exists = User.query.filter_by(hrc_id=user_hrc_id).first()
if not user_exists:
user_exists, _ = get_or_create(db.session,
User,
name=user.get("name"),
email=user.get("email"),
team=user.get("team"),
department=user.get("department"),
job_title=user.get("jobTitle"),
hrc_id=user_hrc_id)
user_exists, _ = get_or_create(
db.session,
User,
name=user.get("name"),
email=user.get("email"),
team=user.get("team"),
department=user.get("department"),
job_title=user.get("jobTitle"),
hrc_id=user_hrc_id,
)

return user_exists.id


def create_jira_task(app, task):
"""
Create a new issue on jira and add a record to the db
"""
# TODO: If an epic already exists for this request, add subtasks to it.

jira = app.config["JIRA"]
issue = jira.create_issue(
due_date=task["due_date"],
reporter_id=task["reporter_id"],
webpage_id=task["webpage_id"],
request_type=task["type"],
description=task["description"],
)

# Create jira task in the database
get_or_create(
db.session,
JiraTask,
jira_id=issue["key"],
webpage_id=task["webpage_id"],
user_id=task["reporter_id"],
)
Loading
Loading