Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
7a6d4e0
Add feedback functionality with interactive buttons and feedback storage
kris-szlapa Aug 27, 2025
d3a9e4b
Move imports to top of the file
kris-szlapa Aug 27, 2025
0ffe006
Add comments to feedback handlers
kris-szlapa Aug 27, 2025
75aa4f1
Move feedback messange above buttons
kris-szlapa Aug 27, 2025
9b6e659
Add feedback test suite
kris-szlapa Aug 27, 2025
b0efa00
Update test with feedback blocks
kris-szlapa Aug 27, 2025
71773a5
Add slack handlers test suite
kris-szlapa Aug 27, 2025
22c1d16
Add feedback handling to @mentions and fix feedback message processing
kris-szlapa Aug 27, 2025
a2d51ee
Remove app middleware from slack handler
kris-szlapa Aug 27, 2025
c1f0df2
Update feedback message
kris-szlapa Aug 27, 2025
236cb99
Merge branch 'main' of https://github.com/NHSDigital/eps-assist-me in…
kris-szlapa Aug 28, 2025
6544f9e
Add feedback button handlers and unify message handler
kris-szlapa Aug 29, 2025
373ccd0
Update comments
kris-szlapa Aug 29, 2025
7a0b3b8
Optimise function to handle whitespace by stripping once after regex …
kris-szlapa Sep 1, 2025
7cb5c4c
Add button text to BOT_MESSAGES dictionary
kris-szlapa Sep 1, 2025
f46b0c7
Replace hardcoded strings with constants across codebase
kris-szlapa Sep 1, 2025
1788e7d
Add TTL constants to config file
kris-szlapa Sep 1, 2025
003e0d8
Combine feedback handlers into a single unified handler
kris-szlapa Sep 1, 2025
2243a57
Merge branch 'main' of https://github.com/NHSDigital/eps-assist-me in…
kris-szlapa Sep 1, 2025
23b7755
Update feedback pattern
kris-szlapa Sep 2, 2025
5e24f82
Update function names in tests
kris-szlapa Sep 2, 2025
777f204
Ignore inactive button clicks and store feedback with latest_message_ts
kris-szlapa Sep 2, 2025
d39b31f
Update test suits
kris-szlapa Sep 2, 2025
0e2ba42
Remove log_event true from inject_lambda_context
kris-szlapa Sep 2, 2025
f6135c3
Add logic to clean up previous unfeedback Q&A before storing new one
kris-szlapa Sep 2, 2025
e7ceee0
Update test suites to improve coverage
kris-szlapa Sep 2, 2025
45b2c7a
Add more tests to suits
kris-szlapa Sep 2, 2025
e8e3298
Add tests for feedback logic
kris-szlapa Sep 2, 2025
47c7690
Remove the unused function parameter body
kris-szlapa Sep 2, 2025
8018e71
Refactor store_feedback_with_qa function to reduce its cognitive comp…
kris-szlapa Sep 2, 2025
c46c2b1
Delete previous Q&A pair if no feedback received using atomic operation
kris-szlapa Sep 3, 2025
be6f106
Remove unnecessary comment
kris-szlapa Sep 3, 2025
66d5f67
Remove data duplication by storing only references in feedback records
kris-szlapa Sep 4, 2025
afe9dcf
Allow multiple entries per user when text feedback
kris-szlapa Sep 4, 2025
1ef2405
Refactor comments in slack events code
kris-szlapa Sep 4, 2025
5623172
Add SlackBotFunction README
kris-szlapa Sep 4, 2025
4789dd9
Update conversation flow in README
kris-szlapa Sep 4, 2025
0bd7aad
Rename handlers for clarity
kris-szlapa Sep 4, 2025
ddadc9a
Reformat code and add comments
kris-szlapa Sep 4, 2025
c72216b
Post direct messages to channel instead of using threads and refactor…
kris-szlapa Sep 4, 2025
7b8911a
Add pattern to gitallowed
kris-szlapa Sep 4, 2025
63278f9
use different table
anthony-nhs Sep 10, 2025
1d206f3
Merge remote-tracking branch 'origin/main' into AEA-5696-add-feedback
anthony-nhs Sep 10, 2025
62ac7d8
Revert "use different table"
anthony-nhs Sep 10, 2025
73b3947
Merge branch 'main' into AEA-5696-add-feedback
anthony-nhs Sep 10, 2025
be8cb2c
merge from main
anthony-nhs Sep 16, 2025
a884fc5
Merge remote-tracking branch 'origin/main' into new_feedback_branch
anthony-nhs Sep 16, 2025
afe9123
finish refactor
anthony-nhs Sep 16, 2025
62e20e4
named params
anthony-nhs Sep 16, 2025
866cf52
another refactor
anthony-nhs Sep 16, 2025
5ce9086
fix it
anthony-nhs Sep 16, 2025
219e7ad
rewrite some tests
anthony-nhs Sep 16, 2025
64b8b23
set stuff up for sync
anthony-nhs Sep 17, 2025
99aca27
start of sync
anthony-nhs Sep 17, 2025
ec67cb4
try using a layer
anthony-nhs Sep 17, 2025
cee405f
fix synth
anthony-nhs Sep 17, 2025
598c817
change location of lambda
anthony-nhs Sep 17, 2025
e3b2df2
fix layer packaging
anthony-nhs Sep 17, 2025
05b157e
fix layer
anthony-nhs Sep 17, 2025
20538da
safely add reaction
anthony-nhs Sep 17, 2025
e53d64b
return dynamo item
anthony-nhs Sep 17, 2025
1134621
fix everything
anthony-nhs Sep 17, 2025
869d1cb
add dependencies to build artifact
anthony-nhs Sep 17, 2025
23ead9a
only respond with eyes once
anthony-nhs Sep 17, 2025
7f3ba2f
register app outside of loop
anthony-nhs Sep 17, 2025
1137fa8
log for reporting
anthony-nhs Sep 17, 2025
1d352dd
log feedback to splunk
anthony-nhs Sep 17, 2025
363343b
fix feedback log
anthony-nhs Sep 17, 2025
f4fcdb9
fix test
anthony-nhs Sep 17, 2025
0936265
fix cleanup
anthony-nhs Sep 17, 2025
5282876
warn when can not get friendly name
anthony-nhs Sep 17, 2025
ba023ee
better log levels
anthony-nhs Sep 17, 2025
9b79ffd
always log dynamo duration
anthony-nhs Sep 17, 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
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[flake8]
max-line-length = 120
exclude = .*,venv,node_modules,cdk.out
max-complexity = 10
max-complexity = 12
ignore = F821,E203,W503
21 changes: 16 additions & 5 deletions .github/scripts/fix_cdk_json.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ fix_string_key() {
jq \
--arg key_value "${KEY_VALUE}" \
--arg key_name "${KEY_NAME}" \
'.context += {($key_name): $key_value}' .build/cdk.json > .build/cdk.new.json
mv .build/cdk.new.json .build/cdk.json
'. += {($key_name): $key_value}' "$OUTPUT_FILE_NAME" > "${TEMP_FILE}"
mv "${TEMP_FILE}" "$OUTPUT_FILE_NAME"
}

# helper function to set boolean and number values (without quotes)
Expand All @@ -31,17 +31,27 @@ fix_boolean_number_key() {
jq \
--argjson key_value "${KEY_VALUE}" \
--arg key_name "${KEY_NAME}" \
'.context += {($key_name): $key_value}' .build/cdk.json > .build/cdk.new.json
mv .build/cdk.new.json .build/cdk.json
'. += {($key_name): $key_value}' "$OUTPUT_FILE_NAME" > "${TEMP_FILE}"
mv "${TEMP_FILE}" "$OUTPUT_FILE_NAME"
}


OUTPUT_FILE_NAME=$1
if [ -z "${OUTPUT_FILE_NAME}" ]; then
echo "OUTPUT_FILE_NAME value is unset or set to the empty string"
exit 1
fi
echo "{}" > "$OUTPUT_FILE_NAME"
TEMP_FILE=$(mktemp)

CFN_DRIFT_DETECTION_GROUP="epsam"
IS_PULL_REQUEST="false"
if [[ "$STACK_NAME" =~ -pr-[0-9]+$ ]]; then
CFN_DRIFT_DETECTION_GROUP="epsam-pull-request"
IS_PULL_REQUEST="true"
fi

# go through all the key values we need to set
fix_string_key accountId "${ACCOUNT_ID}"
fix_string_key stackName "${STACK_NAME}"
fix_string_key versionNumber "${VERSION_NUMBER}"
fix_string_key commitId "${COMMIT_ID}"
Expand All @@ -50,3 +60,4 @@ fix_string_key logLevel "${LOG_LEVEL}"
fix_string_key slackBotToken "${SLACK_BOT_TOKEN}"
fix_string_key slackSigningSecret "${SLACK_SIGNING_SECRET}"
fix_string_key cfnDriftDetectionGroup "${CFN_DRIFT_DETECTION_GROUP}"
fix_boolean_number_key isPullRequest "${IS_PULL_REQUEST}"
7 changes: 4 additions & 3 deletions .github/workflows/cdk_package_code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ jobs:
run: |
poetry export --without-hashes --format=requirements.txt --with slackBotFunction > requirements_slackBotFunction
poetry export --without-hashes --format=requirements.txt --with syncKnowledgeBaseFunction > requirements_syncKnowledgeBaseFunction
pip3 install -r requirements_slackBotFunction -t packages/slackBotFunction
pip3 install -r requirements_syncKnowledgeBaseFunction -t packages/syncKnowledgeBaseFunction
pip3 install -r requirements_slackBotFunction -t .dependencies/slackBotFunction/python
pip3 install -r requirements_syncKnowledgeBaseFunction -t .dependencies/syncKnowledgeBaseFunction/python

- name: 'Tar files'
run: |
Expand All @@ -75,7 +75,8 @@ jobs:
package.json \
package-lock.json \
tsconfig.defaults.json \
cdk.json
cdk.json \
.dependencies

- uses: actions/upload-artifact@v4
name: upload build artifact
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/cdk_release_code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:

- name: fix cdk.json for deployment
run: |
./.github/scripts/fix_cdk_json.sh
./.github/scripts/fix_cdk_json.sh .build/epsam_app.json
env:
ACCOUNT_ID: "${{ env.ACCOUNT_ID }}"
STACK_NAME: "${{ inputs.STACK_NAME }}"
Expand All @@ -128,6 +128,7 @@ jobs:
-e AWS_REGION="eu-west-2" \
-e SHOW_DIFF="true" \
-e DEPLOY_CODE="false" \
-e CONFIG_FILE_NAME="epsam_app.json" \
-e CDK_APP_PATH="packages/cdk/bin/EpsAssistMeApp.ts" \
cdk-utils-build-repo:latest

Expand All @@ -142,6 +143,7 @@ jobs:
-e AWS_REGION="eu-west-2" \
-e SHOW_DIFF="false" \
-e DEPLOY_CODE="true" \
-e CONFIG_FILE_NAME="epsam_app.json" \
-e CDK_APP_PATH="packages/cdk/bin/EpsAssistMeApp.ts" \
cdk-utils-build-repo:latest
shell: bash
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ vendor
.npmrc
cdk.out
.build
.requirements_slackBotFunction
.requirements_syncKnowledgeBaseFunction
.local_config/
.dependencies/
47 changes: 19 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ clean:
rm -rf packages/cdk/lib
rm -rf packages/slackBotFunction/coverage
rm -rf packages/slackBotFunction/.coverage
rm -rf packages/slackBotFunction/.dependencies
rm -rf packages/syncKnowledgeBaseFunction/coverage
rm -rf packages/syncKnowledgeBaseFunction/.coverage
rm -rf .dependencies/
rm -rf cdk.out
rm -rf .build
rm -rf .local_config
rm -rf cfn_guard_output
find . -name '.pytest_cache' -type d -prune -exec rm -rf '{}' +

deep-clean: clean
Expand Down Expand Up @@ -98,17 +101,20 @@ cdk-deploy: guard-STACK_NAME
--context slackBotToken=$$SLACK_BOT_TOKEN \
--context slackSigningSecret=$$SLACK_SIGNING_SECRET
cdk-synth:
npx cdk synth \
mkdir -p .dependencies/slackBotFunction
mkdir -p .dependencies/syncKnowledgeBaseFunction
mkdir -p .local_config
STACK_NAME=epsam \
COMMIT_ID=undefined \
VERSION_NUMBER=undefined \
SLACK_BOT_TOKEN=dummy_token \
SLACK_SIGNING_SECRET=dummy_secret \
LOG_RETENTION_IN_DAYS=30 \
LOG_LEVEL=debug \
./.github/scripts/fix_cdk_json.sh .local_config/epsam.config.json
CONFIG_FILE_NAME=.local_config/epsam.config.json npx cdk synth \
--quiet \
--app "npx ts-node --prefer-ts-exts packages/cdk/bin/EpsAssistMeApp.ts" \
--context accountId=123456789012 \
--context stackName=epsam \
--context versionNumber=undefined \
--context commitId=undefined \
--context logRetentionInDays=30 \
--context slackBotToken=dummy \
--context slackSigningSecret=dummy \
--context cfnDriftDetectionGroup=dummy
--app "npx ts-node --prefer-ts-exts packages/cdk/bin/EpsAssistMeApp.ts"

cdk-diff:
npx cdk diff \
Expand All @@ -119,23 +125,8 @@ cdk-diff:
--context commitId=$$COMMIT_ID \
--context logRetentionInDays=$$LOG_RETENTION_IN_DAYS

cdk-watch: guard-STACK_NAME
REQUIRE_APPROVAL="$${REQUIRE_APPROVAL:-any-change}" && \
VERSION_NUMBER="$${VERSION_NUMBER:-undefined}" && \
COMMIT_ID="$${COMMIT_ID:-undefined}" && \
npx cdk deploy \
--app "npx ts-node --prefer-ts-exts packages/cdk/bin/EpsAssistMeApp.ts" \
--watch \
--all \
--ci true \
--require-approval $${REQUIRE_APPROVAL} \
--context accountId=$$ACCOUNT_ID \
--context stackName=$$STACK_NAME \
--context versionNumber=$$VERSION_NUMBER \
--context commitId=$$COMMIT_ID \
--context logRetentionInDays=$$LOG_RETENTION_IN_DAYS \
--context slackBotToken=$$SLACK_BOT_TOKEN \
--context slackSigningSecret=$$SLACK_SIGNING_SECRET
cdk-watch:
./scripts/run_sync.sh

sync-docs:
./scripts/sync_docs.sh
5 changes: 5 additions & 0 deletions cdk.context.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"acknowledged-issue-numbers": [
34892
]
}
17 changes: 12 additions & 5 deletions packages/cdk/bin/EpsAssistMeApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import {App, Aspects, Tags} from "aws-cdk-lib"
import {AwsSolutionsChecks} from "cdk-nag"
import {EpsAssistMeStack} from "../stacks/EpsAssistMeStack"
import {applyCfnGuardSuppressions} from "./utils/appUtils"
import fs from "fs"

const app = new App()
// read the config in
const configFileName = process.env["CONFIG_FILE_NAME"]
if (configFileName === undefined) {
throw new Error("Can not read config file")
}

const configDetails = JSON.parse(fs.readFileSync(configFileName, "utf-8"))

// create the app using the config details
const app = new App({context: configDetails})

/* Required Context:
- accountId
Expand All @@ -13,7 +23,6 @@ const app = new App()
- commit
*/

const accountId = app.node.tryGetContext("accountId")
const stackName = app.node.tryGetContext("stackName")
const version = app.node.tryGetContext("versionNumber")
const commit = app.node.tryGetContext("commitId")
Expand All @@ -22,16 +31,14 @@ const cfnDriftDetectionGroup = app.node.tryGetContext("cfnDriftDetectionGroup")
Aspects.of(app).add(new AwsSolutionsChecks({verbose: true}))

Tags.of(app).add("cdkApp", "EpsAssistMe")
Tags.of(app).add("accountId", accountId)
Tags.of(app).add("stackName", stackName)
Tags.of(app).add("version", version)
Tags.of(app).add("commit", commit)
Tags.of(app).add("cfnDriftDetectionGroup", cfnDriftDetectionGroup)

const EpsAssistMe = new EpsAssistMeStack(app, "EpsAssistMeStack", {
env: {
region: "eu-west-2",
account: accountId
region: "eu-west-2"
},
stackName: stackName,
version: version,
Expand Down
13 changes: 12 additions & 1 deletion packages/cdk/constructs/LambdaFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface LambdaFunctionProps {
readonly additionalPolicies?: Array<IManagedPolicy>
readonly logRetentionInDays: number
readonly logLevel: string
readonly dependencyLocation?: string
}

// Lambda Insights layer for enhanced monitoring
Expand Down Expand Up @@ -115,6 +116,16 @@ export class LambdaFunction extends Construct {
managedPolicies: requiredPolicies
})

const layers = [insightsLambdaLayer]
if (props.dependencyLocation) {
const dependencyLayer = new LayerVersion(this, "DependencyLayer", {
removalPolicy: RemovalPolicy.DESTROY,
code: Code.fromAsset(props.dependencyLocation),
compatibleArchitectures: [Architecture.X86_64]
})
layers.push(dependencyLayer)
}

// Create Lambda function with Python runtime and monitoring
const lambdaFunction = new LambdaFunctionResource(this, props.functionName, {
runtime: Runtime.PYTHON_3_13,
Expand All @@ -129,7 +140,7 @@ export class LambdaFunction extends Construct {
POWERTOOLS_LOG_LEVEL: props.logLevel
},
logGroup,
layers: [insightsLambdaLayer]
layers: layers
})

// Suppress CFN guard rules for Lambda function
Expand Down
2 changes: 2 additions & 0 deletions packages/cdk/resources/Functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class Functions extends Construct {
logRetentionInDays: props.logRetentionInDays,
logLevel: props.logLevel,
additionalPolicies: [props.slackBotManagedPolicy],
dependencyLocation: ".dependencies/slackBotFunction",
environmentVariables: {
"RAG_MODEL_ID": RAG_MODEL_ID,
"QUERY_REFORMULATION_MODEL_ID": QUERY_REFORMULATION_MODEL_ID,
Expand Down Expand Up @@ -80,6 +81,7 @@ export class Functions extends Construct {
handler: "app.handler.handler",
logRetentionInDays: props.logRetentionInDays,
logLevel: props.logLevel,
dependencyLocation: ".dependencies/syncKnowledgeBaseFunction",
environmentVariables: {
"KNOWLEDGEBASE_ID": props.knowledgeBaseId,
"DATA_SOURCE_ID": props.dataSourceId
Expand Down
20 changes: 19 additions & 1 deletion packages/cdk/stacks/EpsAssistMeStack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class EpsAssistMeStack extends Stack {
const account = Stack.of(this).account
const logRetentionInDays = Number(this.node.tryGetContext("logRetentionInDays"))
const logLevel: string = this.node.tryGetContext("logLevel")
const isPullRequest: boolean = this.node.tryGetContext("isPullRequest")

// Get secrets from context or fail if not provided
const slackBotToken: string = this.node.tryGetContext("slackBotToken")
Expand Down Expand Up @@ -179,7 +180,24 @@ export class EpsAssistMeStack extends Stack {
value: storage.kbDocsBucket.bucket.bucketName,
exportName: `${props.stackName}:kbDocsBucket:Name`
})

if (isPullRequest) {
new CfnOutput(this, "VERSION_NUMBER", {
value: props.version,
exportName: `${props.stackName}:local:VERSION-NUMBER`
})
new CfnOutput(this, "COMMIT_ID", {
value: props.commitId,
exportName: `${props.stackName}:local:COMMIT-ID`
})
new CfnOutput(this, "slackBotToken", {
value: slackBotToken,
exportName: `${props.stackName}:local:slackBotToken`
})
new CfnOutput(this, "slackSigningSecret", {
value: slackSigningSecret,
exportName: `${props.stackName}:local:slackSigningSecret`
})
}
// Final CDK Nag Suppressions
nagSuppressions(this)
}
Expand Down
Loading