Skip to content

Commit

Permalink
Merge pull request #1238 from ChildMindInstitute/release/1.3.23
Browse files Browse the repository at this point in the history
Release/1.3.23
  • Loading branch information
vshvechko authored Apr 18, 2024
2 parents c5d21b5 + 06bac9f commit 4d79cf7
Show file tree
Hide file tree
Showing 13 changed files with 570 additions and 89 deletions.
134 changes: 134 additions & 0 deletions .github/workflows/update-jira-tickets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Update Jira Tickets

on:
release:
types: [created]
# Allows running manually from the Actions tab
workflow_dispatch:
inputs:
tagName:
description: "Tag Name"
required: true

jobs:
process-release:
env:
JENKINS_USER: ${{ secrets.JENKINS_USER }}
JENKINS_TOKEN: ${{ secrets.JENKINS_TOKEN }}
JIRA_WEBHOOK_URL: ${{ secrets.JIRA_WEBHOOK_URL }}
JENKINS_HOST: ${{ vars.JENKINS_HOST }}

# The max amount of time (in minutes) we should wait for the current Jenkins build to finish. Defaults to 6 hours
JENKINS_BUILD_MAX_WAIT_MINS: ${{ vars.JENKINS_BUILD_MAX_WAIT_MINS || 360 }}
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Get current tag
id: get-tag
run: |
if [ "${{ github.event_name }}" == "release" ]; then
currentTag=${GITHUB_REF#refs/tags/}
else
currentTag="${{ github.event.inputs.tagName }}"
fi
echo "Tag: ${currentTag}"
echo "tag=${currentTag}" >> $GITHUB_OUTPUT
- name: Validate tag
run: |
git fetch -q --tags
if ! git tag --list | grep -qx "${{ steps.get-tag.outputs.tag }}"; then
echo "Not a valid tag, ending workflow"
exit 1
fi
- name: Check if tag is a release candidate
run: |
if [[ ${{ steps.get-tag.outputs.tag }} != *"-rc"* ]]; then
echo "Not a release candidate, ending workflow."
exit 1
fi
- name: Ping Jenkins for previous successful tag
id: ping-jenkins
run: |
repoName=${GITHUB_REPOSITORY##*/}
currentTag="${{ steps.get-tag.outputs.tag }}"
git fetch -q --tags
rcTags=$(git tag --sort=-creatordate | grep -- -rc)
started=false
previousTag=""
for tagName in $rcTags
do
# Skip tags more recent than the current one
if [ "$tagName" != "$currentTag" ] && [ "$started" = false ]; then
continue;
elif [ "$tagName" == "$currentTag" ]; then
started=true;
continue;
fi
jenkinsUrl="${JENKINS_HOST}/job/${repoName}/view/tags/job/${tagName}/lastSuccessfulBuild"
echo "Checking for successful Jenkins build for GitHub tag ${tagName} at ${jenkinsUrl}"
response=$(curl -o /dev/null --silent -w "%{http_code}\n" -u "${JENKINS_USER}:${JENKINS_TOKEN}" "${jenkinsUrl}/api/json")
echo "Response: ${response}"
if [ "$response" == "200" ]; then
echo "Found successful Jenkins build for GitHub tag ${tagName}: ${jenkinsUrl}"
previousTag="${tagName}"
break
fi
done
if [ "${previousTag}" == "" ]; then
echo "No successful Jenkins builds found for any previous tags. Ending workflow"
exit 1
else
echo "tagName=${previousTag}" >> $GITHUB_OUTPUT
fi
- name: Determine Jira tickets from commit messages
id: jira-tickets
run: |
currentTag="${{ steps.get-tag.outputs.tag }}"
previousTag="${{ steps.ping-jenkins.outputs.tagName }}"
commitMessages=$(git log --pretty=%B $previousTag..$currentTag)
echo "Commit messages since the last release: ${commitMessages}"
jiraTickets=$(echo "$commitMessages" | grep -io 'M2-[0-9]\+' | tr '[:lower:]' '[:upper:]' | sort | uniq | tr '\n' ' ')
echo "Jira tickets since the last release: ${jiraTickets}"
echo "tickets=${jiraTickets}" >> $GITHUB_OUTPUT
- name: Periodically ping Jenkins for current tag build status
run: |
repoName=${GITHUB_REPOSITORY##*/}
currentTag="${{ steps.get-tag.outputs.tag }}"
echo "Waiting for current build to finish.."
start_time=$(date +%s)
while true; do
current_time=$(date +%s)
elapsed_time_mins=$(( (current_time - start_time) / 60 ))
# Break out of the loop if we've been waiting longer than 6 hours
if [ $elapsed_time_mins -ge $JENKINS_BUILD_MAX_WAIT_MINS ]; then
echo "Timed out waiting for build to finish"
exit 1
fi
echo -n "."
result=$(curl --silent -u "${JENKINS_USER}:${JENKINS_TOKEN}" --connect-timeout 10 -m 10 "${JENKINS_HOST}/job/${repoName}/view/tags/job/${currentTag}/lastBuild/api/json" | jq -r .result)
if [[ "$result" == "SUCCESS" ]]; then
echo "Build successful! Submitting ticket numbers to Jira"
tickets="${{ steps.jira-tickets.outputs.tickets }}"
json="{ \"issues\": $(echo "${tickets}" | jq -R -s -c 'split(" ")[:-1]') }"
curl -X POST -H 'Content-Type: application/json' --url "${JIRA_WEBHOOK_URL}" --data "$json"
break
elif [[ "$result" != "null" ]]; then
echo "Build failed, ending workflow"
exit 1
fi
sleep 60
done
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ pipenv --python /opt/homebrew/bin/python3.10
| RABBITMQ\_\_USE_SSL | True | Rabbitmq ssl setting, turn false to local development
| MAILING\_\_MAIL\_\_USERNAME | mailhog | Mail service username
| MAILING\_\_MAIL\_\_PASSWORD | mailhog | Mail service password
| MAILING\_\_MAIL\_\_SERVER | mailhog | Mail service URL
| MAILING\_\_MAIL\_\_SERVER | mailhog | Mail service URL
| SECRETS\_\_SECRET\_KEY | - | Secret key for data encryption. Use this key only for local development

##### ✋ Mandatory:

Expand Down
13 changes: 13 additions & 0 deletions compose/fastapi/Dockerfile.app
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM 917902836630.dkr.ecr.us-east-1.amazonaws.com/base-image:backend

COPY ./ ./

# Application scripts
COPY --chown=code:code ./compose/fastapi/entrypoint /fastapi-entrypoint
RUN sed -i 's/\r$//g' /fastapi-entrypoint && chmod +x /fastapi-entrypoint

COPY --chown=code:code ./compose/fastapi/start /fastapi-start
RUN sed -i 's/\r$//g' /fastapi-start && chmod +x /fastapi-start

# Select internal user
USER code
18 changes: 11 additions & 7 deletions src/apps/answers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
PublicAnswerExportResponse,
PublicReviewActivity,
PublicSummaryActivity,
ReviewsCount,
VersionPublic,
)
from apps.answers.filters import (
Expand Down Expand Up @@ -145,13 +146,16 @@ async def applet_activity_answers_list(
) -> ResponseMulti[AppletActivityAnswerPublic]:
await AppletService(session, user.id).exist_by_id(applet_id)
await CheckAccessService(session, user.id).check_answer_review_access(applet_id)
answers = await AnswerService(session, user.id, answer_session).get_activity_answers(
applet_id, activity_id, query_params
)
return ResponseMulti(
result=parse_obj_as(list[AppletActivityAnswerPublic], answers),
count=len(answers),
)
service = AnswerService(session, user.id, answer_session)
answers = await service.get_activity_answers(applet_id, activity_id, query_params)

answers_ids = [answer.answer_id for answer in answers if answer.answer_id is not None]
answer_reviews = await service.get_assessments_count(answers_ids)
result = []
for answer in answers:
review_count = answer_reviews.get(answer.answer_id, ReviewsCount())
result.append(parse_obj_as(AppletActivityAnswerPublic, {**answer.dict(), "review_count": review_count}))
return ResponseMulti(result=result, count=len(answers))


async def summary_latest_report_retrieve(
Expand Down
9 changes: 8 additions & 1 deletion src/apps/answers/crud/answer_items.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import uuid
from typing import Collection, List, Set, Union

from sqlalchemy import and_, delete, select
from sqlalchemy import and_, delete, func, select
from sqlalchemy.orm import Query

from apps.answers.db.schemas import AnswerItemSchema, AnswerSchema
Expand Down Expand Up @@ -198,3 +198,10 @@ async def delete_assessment(self, assessment_id: uuid.UUID):
query: Query = delete(AnswerItemSchema)
query = query.where(AnswerItemSchema.id == assessment_id, AnswerItemSchema.is_assessment.is_(True))
await self._execute(query)

async def get_reviewers_by_answers(self, answer_ids: list[uuid.UUID]) -> list[tuple[uuid.UUID, list[uuid.UUID]]]:
query: Query = select(AnswerItemSchema.answer_id, func.array_agg(AnswerItemSchema.respondent_id))
query = query.where(AnswerItemSchema.answer_id.in_(answer_ids), AnswerItemSchema.is_assessment.is_(True))
query = query.group_by(AnswerItemSchema.answer_id)
db_result = await self._execute(query)
return db_result.all() # noqa
10 changes: 8 additions & 2 deletions src/apps/answers/crud/answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ async def get_item_history_by_activity_history(self, activity_hist_ids: list[str
async def get_identifiers_by_activity_id(
self,
activity_hist_ids: Collection[str],
respondent_id: uuid.UUID,
respondent_id: uuid.UUID | None = None,
answer_id: uuid.UUID | None = None,
) -> list[tuple[str, str, dict, datetime.datetime]]:
query: Query = select(
AnswerItemSchema.identifier,
Expand All @@ -247,7 +248,12 @@ async def get_identifiers_by_activity_id(
AnswerItemSchema.identifier.isnot(None),
AnswerSchema.activity_history_id.in_(activity_hist_ids),
)
query = query.where(AnswerSchema.respondent_id == respondent_id)
if respondent_id:
query = query.where(AnswerSchema.respondent_id == respondent_id)

if answer_id:
query = query.where(AnswerItemSchema.answer_id == answer_id)

db_result = await self._execute(query)
return db_result.all() # noqa

Expand Down
26 changes: 19 additions & 7 deletions src/apps/answers/domain/answers.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,30 @@ class PublicAnswerDates(PublicModel):
dates: list[datetime.date]


class Identifier(InternalModel):
identifier: str
user_public_key: str | None = None
last_answer_date: datetime.datetime


class ActivityAnswer(InternalModel):
user_public_key: str | None
answer: str | None
events: str | None
item_ids: list[str] = Field(default_factory=list)
items: list[PublicActivityItemFull] = Field(default_factory=list)
identifier: Identifier | None
created_at: datetime.datetime
version: str


class ReviewsCount(PublicModel):
mine: int = 0
other: int = 0


class AppletActivityAnswer(InternalModel):
answer_id: uuid.UUID | None
answer_id: uuid.UUID
version: str | None
user_public_key: str | None
answer: str | None
Expand Down Expand Up @@ -192,6 +206,9 @@ class ActivityAnswerPublic(PublicModel):
events: str | None
item_ids: list[str] = Field(default_factory=list)
items: list[PublicActivityItemFull] = Field(default_factory=list)
identifier: Identifier | None
created_at: datetime.datetime
version: str


class AppletActivityAnswerPublic(PublicModel):
Expand All @@ -205,6 +222,7 @@ class AppletActivityAnswerPublic(PublicModel):
start_datetime: datetime.datetime
end_datetime: datetime.datetime
subscale_setting: SubscaleSetting | None
review_count: ReviewsCount


class ReviewerPublic(PublicModel):
Expand Down Expand Up @@ -354,12 +372,6 @@ class VersionPublic(PublicModel):
created_at: datetime.datetime


class Identifier(InternalModel):
identifier: str
user_public_key: str | None = None
last_answer_date: datetime.datetime


class IdentifierPublic(PublicModel):
identifier: str
user_public_key: str
Expand Down
Loading

0 comments on commit 4d79cf7

Please sign in to comment.