-
Notifications
You must be signed in to change notification settings - Fork 0
[RELEASE] 2026-08-13 / v1.1.2 #279
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
Changes from all commits
e934cde
02396bb
591ba79
dc793a1
f1a7eec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import http from 'k6/http'; | ||
| import { check, sleep } from 'k6'; | ||
| import { | ||
| BASE_URL, | ||
| VU_OPTIONS, | ||
| authHeaders, | ||
| createGuest, | ||
| getCalendarParams, | ||
| } from './common.js'; | ||
|
|
||
| export const options = { | ||
| ...VU_OPTIONS, | ||
| duration: '1m', | ||
| }; | ||
|
|
||
| export default function () { | ||
| const { res: guestRes } = createGuest(); | ||
|
|
||
| const guestOk = check(guestRes, { | ||
| 'guest created': (r) => r.status === 201 || r.status === 200, | ||
| 'guest has token': (r) => !!r.json('data.auth.accessToken'), | ||
| }); | ||
|
|
||
| if (!guestOk) { | ||
| return; | ||
| } | ||
|
|
||
| const headers = authHeaders(guestRes.json('data.auth.accessToken')); | ||
| const { year, month, selectedDate } = getCalendarParams(); | ||
|
|
||
| const statusRes = http.get(`${BASE_URL}/api/v1/users/status`, { headers }); | ||
| check(statusRes, { 'user status 200': (r) => r.status === 200 }); | ||
|
|
||
| const calRes = http.get( | ||
| `${BASE_URL}/api/v1/calendars/main?year=${year}&month=${month}&selectedDate=${selectedDate}`, | ||
| { headers }, | ||
| ); | ||
| check(calRes, { 'calendar main 200': (r) => r.status === 200 }); | ||
|
|
||
| const dateEventsRes = http.get( | ||
| `${BASE_URL}/api/v1/calendars/dates/${selectedDate}/events`, | ||
| { headers }, | ||
| ); | ||
| check(dateEventsRes, { 'date events 200': (r) => r.status === 200 }); | ||
|
|
||
| const labelsRes = http.get(`${BASE_URL}/api/v1/labels`, { headers }); | ||
| check(labelsRes, { 'labels 200': (r) => r.status === 200 }); | ||
|
|
||
| sleep(1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import http from 'k6/http'; | ||
| import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js'; | ||
|
|
||
| export const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080'; | ||
|
|
||
| export const VU_OPTIONS = { | ||
| vus: 10, | ||
| duration: '30s', | ||
| thresholds: { | ||
| http_req_duration: ['p(95)<500'], | ||
| http_req_failed: ['rate<0.01'], | ||
| }, | ||
| }; | ||
|
|
||
| export function createGuest() { | ||
| const guestId = uuidv4(); | ||
| const res = http.post( | ||
| `${BASE_URL}/api/v1/guests`, | ||
| JSON.stringify({ guestId }), | ||
| { headers: { 'Content-Type': 'application/json' } }, | ||
| ); | ||
|
|
||
| return { res, guestId }; | ||
| } | ||
|
|
||
| export function authHeaders(accessToken) { | ||
| return { | ||
| Authorization: `Bearer ${accessToken}`, | ||
| 'Content-Type': 'application/json', | ||
| }; | ||
| } | ||
|
|
||
| export function getCalendarParams() { | ||
| const now = new Date(); | ||
| return { | ||
| year: now.getFullYear(), | ||
| month: now.getMonth() + 1, | ||
| selectedDate: now.toISOString().slice(0, 10), | ||
| }; | ||
|
Comment on lines
+33
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ฏ Functional Correctness | ๐ก Minor | โก Quick win ๐งฉ Analysis chain๐ Web query:
๐ก Result: Yes, that is correct. The k6 JavaScript runtime, which utilizes the Goja engine to execute ECMAScript code, follows standard JavaScript Citations:
๐ Script executed: #!/bin/bash
set -eu
file="$(git ls-files | awk '$0 == "load-tests/common.js" { print; exit }')"
if [ -z "$file" ]; then
printf '%s\n' "load-tests/common.js not found"
exit 0
fi
printf '%s\n' "--- $file ---"
sed -n '1,80p' "$file"
printf '%s\n' '--- JavaScript date behavior near UTC midnight ---'
TZ=America/Los_Angeles node - <<'JS'
const instant = new Date('2026-09-01T00:30:00.000Z');
console.log(JSON.stringify({
timeZone: process.env.TZ,
year: instant.getFullYear(),
month: instant.getMonth() + 1,
selectedDate: instant.toISOString().slice(0, 10),
localDate: [
instant.getFullYear(),
String(instant.getMonth() + 1).padStart(2, '0'),
String(instant.getDate()).padStart(2, '0'),
].join('-'),
}));
JSRepository: tryna-team/backend Length of output: 1252 Use one time basis for all calendar parameters.
๐ค Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import http from 'k6/http'; | ||
| import { check, sleep } from 'k6'; | ||
| import { BASE_URL, VU_OPTIONS, createGuest } from './common.js'; | ||
|
|
||
| export const options = VU_OPTIONS; | ||
|
|
||
| export function setup() { | ||
| const res = http.get(`${BASE_URL}/health`); | ||
| if (res.status !== 200) { | ||
| throw new Error( | ||
| `๋ฐฑ์๋์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค (${BASE_URL}/health โ status=${res.status}). ` + | ||
| 'Spring Boot๊ฐ ์คํ ์ค์ธ์ง ํ์ธํ์ธ์.', | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| export default function () { | ||
| const { res } = createGuest(); | ||
|
|
||
| check(res, { | ||
| 'guest created or reconnected': (r) => { | ||
| if (r.status !== 201 && r.status !== 200) { | ||
| console.error(`guest ์คํจ: status=${r.status}, body=${r.body}`); | ||
| } | ||
| return r.status === 201 || r.status === 200; | ||
| }, | ||
| 'guest response has access token': (r) => !!r.json('data.auth.accessToken'), | ||
| }); | ||
|
|
||
| sleep(1); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import http from 'k6/http'; | ||
| import { check, sleep } from 'k6'; | ||
| import { BASE_URL, VU_OPTIONS } from './common.js'; | ||
|
|
||
| export const options = VU_OPTIONS; | ||
|
|
||
| export default function () { | ||
| const res = http.get(`${BASE_URL}/health`); | ||
|
|
||
| check(res, { | ||
| 'health status is 200': (r) => r.status === 200, | ||
| 'health overall UP': (r) => r.json('status') === 'UP', | ||
| }); | ||
|
|
||
| sleep(1); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ฏ Functional Correctness | ๐ Major | โก Quick win
๐งฉ Analysis chain
๐ Web query:
In k6, do failedcheck()expressions cause a non-zero process exit when no threshold is configured for thechecksmetric? Ischecks: ['rate==1']supported threshold syntax?๐ก Result:
In k6, failed check expressions do not cause a non-zero process exit code when no threshold is configured [1][2][3]. By default, failed checks are simply recorded as failures in the test metrics, but they do not affect the overall pass/fail status or the exit status of the k6 process [1][4][5]. Regarding threshold syntax,
checks: ['rate==1']is supported and valid syntax [3]. Thresholds in k6 follow the pattern of<aggregation_method> <operator> <value>[6], andchecksis a valid metric that you can apply thresholds to [4][5][6]. Settingrate==1effectively mandates that 100% of checks must pass for the test to be considered successful [3]. To ensure a test fails with a non-zero exit code based on check results, you must explicitly configure a threshold for thechecksmetric [1][2][7]. When a threshold is breached, k6 will exit with a non-zero code (commonly 99) [8][9].Citations:
๐ Script executed:
Repository: tryna-team/backend
Length of output: 3324
Add a
checksthreshold to fail the test when a check fails.Without a
checksthreshold, failed endpoint assertions do not make k6 exit with a failure status. Addchecks: ['rate==1']when every assertion must pass for the release test.๐ค Prompt for AI Agents