Reproduce
Reproduce at a moment in time
Bug report fingerprints
| Fingerprint | Version | Context | Values seen | Seen | |
|---|---|---|---|---|---|
| ex-fp-2 | Version 3 | ctx-2b7e04 | checkout-v2=on | 2026-08-23 07:48 UTC | |
| ex-fp-1 | Version 2 | ctx-9f3a1c | checkout-v2=off | 2026-08-18 13:22 UTC |
CI setup
ci/replay.mjs
// Loglune replay-regression entrypoint (generated by Loglune).
// Pins the Ruleset version live at reproduction point T and asserts the case corpus
// still resolves as expected on the Loglune server. Exits non-zero on any regression,
// failing the CI job. Run: node ci/replay.mjs
import { readFileSync } from 'node:fs';
import { runReplayRegression } from '@loglune/sdk/ci-replay';
function required(name) {
const value = process.env[name];
if (!value) {
console.error(`loglune replay: missing required env ${name}`);
process.exit(2); // config error, distinct from a regression (exit 1)
}
return value;
}
const sdkKey = required('LOGLUNE_SDK_KEY');
const version = Number(required('LOGLUNE_VERSION'));
if (!Number.isInteger(version)) {
console.error(`loglune replay: LOGLUNE_VERSION must be an integer`);
process.exit(2);
}
// Reproduction point T (optional): seeds each case's evaluatedAt so time-dependent rules
// fire at T. Omit to let time rules fail closed.
const at = process.env['LOGLUNE_AT'] || undefined;
const baseUrl = process.env['LOGLUNE_API_URL'] || "https://loglune.com";
const casesPath = process.env['LOGLUNE_CASES'] || "ci/replay-cases.json";
const cases = JSON.parse(readFileSync(casesPath, 'utf8'));
const report = await runReplayRegression({ sdkKey, baseUrl, version, at }, cases);
for (const r of report.results) {
if (!r.pass) {
console.error(
`FAIL case #${r.caseIndex} [${r.contextKey}] ${r.flagKey}: expected ${r.expectedVariationId}, got ${r.actualVariationId}`
);
}
}
console.log(
`loglune replay v${report.version}: ${report.passed}/${report.total} assertions passed`
);
process.exit(report.ok ? 0 : 1);
ci/replay-cases.json
[
{
"context": {
"key": "user-123",
"attributes": {
"plan": "pro",
"country": "JP"
},
"evaluatedAt": "2026-08-27T00:00:00.000Z"
},
"expect": {
"new-checkout": "on",
"pricing-experiment": "variant-b"
}
}
]
.github/workflows/loglune-replay.yml
# Loglune replay regression (generated by Loglune).
# Evaluates the case corpus against a pinned Ruleset version on Loglune's production
# evaluation (POST /api/flags). Fails the check on any regression.
name: loglune-replay
on:
pull_request:
workflow_dispatch:
inputs:
version:
description: Ruleset version live at the reproduction point T
required: true
at:
description: 'Reproduction point T (ISO 8601, optional)'
required: false
jobs:
replay:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm ci
- name: Loglune replay regression
run: node ci/replay.mjs
env:
LOGLUNE_SDK_KEY: ${{ secrets.LOGLUNE_SDK_KEY }}
LOGLUNE_VERSION: ${{ inputs.version }}
LOGLUNE_AT: ${{ inputs.at }}
Recent reproductions · 2026-08
| When | Version | Reproduction ID |
|---|---|---|
| 2026-08-24 10:05 UTC | Version 3 | ex-repro-1 |
| 2026-08-22 16:40 UTC | Version 3 | ex-repro-2 |
| 2026-08-19 08:12 UTC | Version 2 | ex-repro-3 |