Skip to content

Commit

Permalink
Fix: [AEA-4066] - run artillery in github action (#13)
Browse files Browse the repository at this point in the history
## Summary

- Routine Change

### Details

- run artillery in github action
  • Loading branch information
anthony-nhs committed Jul 31, 2024
1 parent ee211b2 commit 55acb90
Show file tree
Hide file tree
Showing 15 changed files with 1,779 additions and 799 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ RUN wget -O /tmp/aws-sam-cli.zip https://github.com/aws/aws-sam-cli/releases/lat
USER vscode

# Install ASDF
RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3; \
RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.14.0; \
echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc; \
echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc; \
echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc; \
Expand Down
3 changes: 2 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"streetsidesoftware.code-spell-checker",
"timonwong.shellcheck",
"mkhl.direnv",
"github.vscode-github-actions"
"github.vscode-github-actions",
"artilleryio.vscode-artillery"
],
"settings": {
"python.defaultInterpreterPath": "/workspaces/eps-prescription-status-update/.venv/bin/python",
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/run_psu_load.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Run psu load test

on:
workflow_dispatch:

jobs:
run_artillery:
name: Run Artillery
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
ref: ${{ env.BRANCH_NAME }}

- name: Install asdf
uses: asdf-vm/actions/setup@05e0d2ed97b598bfce82fd30daf324ae0c4570e6
with:
asdf_branch: v0.14.0

- name: Cache asdf
uses: actions/cache@v4
with:
path: |
~/.asdf
key: ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}
restore-keys: |
${{ runner.os }}-asdf-
- name: Install asdf dependencies in .tool-versions
uses: asdf-vm/actions/install@05e0d2ed97b598bfce82fd30daf324ae0c4570e6
with:
asdf_branch: v0.14.0
env:
PYTHON_CONFIGURE_OPTS: --enable-shared

- name: Install Dependencies
run: make install

- name: Assume artillery runner role
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.DEV_ARTILLERY_RUNNER_ROLE }}
role-session-name: github-actions-artillery

- name: Run load tests
shell: bash
run: ./scripts/run_psu_load_test.sh
1 change: 0 additions & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ poetry 1.8.2
shellcheck 0.9.0
direnv 2.32.2
actionlint 1.6.26
ruby 3.3.0
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,15 @@ sam-sync: guard-AWS_DEFAULT_PROFILE guard-stack_name compile
--watch \
--template-file SAMtemplates/main_template.yaml \
--parameter-overrides \
EnableSplunk=false
EnableSplunk=false

install: install-node

install-python:
poetry install

install-node:
npm ci

install-hooks: install-python
poetry run pre-commit install --install-hooks --overwrite
26 changes: 18 additions & 8 deletions artillery/helper/auth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,24 @@ import axios from "axios"
import {dirname} from "path"
import {fileURLToPath} from "url"

const __dirname = dirname(fileURLToPath(import.meta.url))
// const __dirname = dirname(fileURLToPath(import.meta.url))

const privateKey = fs.readFileSync(`${__dirname}/private.key`, "utf8")
// const privateKey = fs.readFileSync(`${__dirname}/private.key`, "utf8")
const privateKey = process.env.psu_private_key
const auth_url = "https://internal-dev.api.service.nhs.uk/oauth2/token"

function createSignedJWT() {
const header = {
typ: "JWT",
alg: "RS512",
kid: "psu-internal-dev"
kid: process.env.psu_kid
}
const jti_value = uuidv4()

const currentTimestamp = Math.floor(Date.now() / 1000)
const data = {
sub: process.env.API_KEY,
iss: process.env.API_KEY,
sub: process.env.psu_api_key,
iss: process.env.psu_api_key,
jti: jti_value,
aud: auth_url,
exp: currentTimestamp + 180 // expiry time is 180 seconds from time of creation
Expand All @@ -31,13 +32,22 @@ function createSignedJWT() {
return signedJWT
}

export async function getAccessToken() {
export async function getAccessToken(logger) {
const signedJWT = createSignedJWT()
const payload = {
grant_type: "client_credentials",
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer",
client_assertion: signedJWT
}
const response = await axios.post(auth_url, payload, {headers: {"content-type": "application/x-www-form-urlencoded"}})
return response.data
try {
const response = await axios.post(auth_url, payload, {
headers: {"content-type": "application/x-www-form-urlencoded"}
})
logger.info(`response data: ${JSON.stringify(response.data)}`)
return response.data
} catch (error) {
logger.error("Got an error")
logger.error(error.response)
throw error
}
}
14 changes: 8 additions & 6 deletions artillery/helper/psu.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {v4 as uuidv4} from "uuid"
import {getAccessToken} from "./auth.mjs"
import pino from "pino"
const logger = pino()

function getBody() {
const task_identifier = uuidv4()
Expand Down Expand Up @@ -96,15 +98,15 @@ export function hasValidToken(vuContext, next) {

export async function getPSUParams(requestParams, vuContext, events) {
if (!vuContext.tokenExpiryTime || vuContext.tokenExpiryTime < Date.now()) {
console.log("Fetching new token")
console.log(` current expiry time: ${vuContext.tokenExpiryTime}`)
const response = await getAccessToken()
logger.info("Fetching new token")
logger.info(` current expiry time: ${vuContext.tokenExpiryTime}`)
const response = await getAccessToken(logger)
vuContext.tokenExpiryTime = Date.now() + response.expires_in * 1000
vuContext.vars.authToken = response.access_token
console.log(` new expiry time: ${vuContext.tokenExpiryTime}`)
console.log(` new token: ${vuContext.vars.authToken}`)
logger.info(` new expiry time: ${vuContext.tokenExpiryTime}`)
logger.info(` new token: ${vuContext.vars.authToken}`)
} else {
console.log(" using cached token")
logger.info(" using cached token")
}
const body = getBody()
requestParams.json = body
Expand Down
7 changes: 7 additions & 0 deletions artillery/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"axios": "^1.7.2",
"jsonwebtoken": "^9.0.2",
"pino": "^9.3.0"
}
}
8 changes: 4 additions & 4 deletions artillery/psu_load_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ config:
apdex: {}
ensure:
thresholds:
- http.response_time.p99: 500
- http.response_time.p95: 400
- http.response_time.p99: 5000
- http.response_time.p95: 4000
- maxErrorRate: 0
phases:
- duration: 120
- duration: 10
arrivalRate: 1
maxVusers: 2
name: running phase
Expand All @@ -28,4 +28,4 @@ scenarios:
expect:
- statusCode: 201
- think: 30
whileTrue: "hasValidToken"
count: 10
Loading

0 comments on commit 55acb90

Please sign in to comment.