Deploy != Release
Stable codebase
Trunk-based development or short-lived branches
Easy to release-rollback
DevOps culture: good observability, traceability
Deployment Issues
DevOps culture
Observability Issues
Spécialité de XUND
Stable codebase
Trunk-based development or short-lived branches
Easy to release-rollback
DevOps culture: good observability, traceability
?
?
?
?
Stable codebase
Trunk-based development or short-lived branches
Easy to release-rollback
DevOps culture: good observability, traceability
Stable codebase
Trunk-based development or short-lived branches
Easy to release-rollback
DevOps culture: good observability, traceability
Quick & Safe deploy
Deploy half-baked code
Try & Show in production
if (await FeatureFlags.isOn("patientIntent")) {
...
}
const { value: isPatientIntentEnabled } = useFeatureFlag(
'patientIntent',
false,
);
...
{isPatientIntentEnabled && <PatientIntent />}
FeatureFlags.isOn(
"patientIntent",
{
userId: "ad233-2d34",
environment: "development",
version: "2.32.1"
},
false
))
Feature Flag Service
CDN
Add/remove flags
Segment
Deprecate and alert
Cache
Cache
XUND Frontend
XUND Backend
XUND Frontend
XUND Backend
WebApp
CH Ext BE
CH DB
CH Ext FE
Admin UI to save/edit questions and answers
Show Patient Intent questionare
const { value: isPatientIntentEnabled } = useFeatureFlag(
'patientIntent',
false,
);
{isPatientIntentEnabled && <PatientIntent />}
WebApp side
<FlagProvider sdkKey={window.xundEnvironment.flagApiKey}>
...
</FlagProvider>
Client Hub External Backend / Answer API side
Nothing to flip as
/external/patient-intent
is a new API
{ isPatientIntentEnabled &&
<WebAppReportPatientIntentFieldsGroup />
}
Client Hub External Frontend side
export const convertToWebAppEdit: ...) = async (props) => {
[...]
const patientIntentData = await FeatureFlags.isOn("patientIntent") ? {
scReportPatientIntent: data.scReportPatientIntent,
icReportPatientIntent: data.icReportPatientIntent,
} : {}
return {
apiKeyId: data.apiKeyId,
partnerId,
[...],
...patientIntentData
}
}
Client Hub External Backend side
export type WebAppEdit = Omit<
WebApp,
'createdAt' | 'updatedAt' | 'id' | [...]
> & {
scReportPatientIntentQuestion?: PatientIntentQuestionEdit | null
icReportPatientIntentQuestion?: PatientIntentQuestionEdit | null
}
Client Hub External Backend side
export const bulkCheckIllnessSymptomGroupRelations = async (
relations: IllnessSymptomGroupRelation[],
): Promise<ScIcIntegrityCheckError[]> => {
return [
...(await bulkCheck...PublicationScores(relations)),
...(await bulkCheckUnlockedIllnessesWithLockedSymptoms(relations)),
...(await bulkCheckBodyTagQuestionsOnSymptom(relations)),
]
}
export const bulkCheckIllnessSymptomGroupRelations = async (
relations: IllnessSymptomGroupRelation[],
): Promise<ScIcIntegrityCheckError[]> => {
return [
...(await bulkCheck...PublicationScores(getRelationIds(relations))),
...(await bulkCheckUnlockedIllnessesWithLockedSymptoms(relations)),
...(await bulkCheckBodyTagQuestionsOnSymptom(relations)),
]
}
Before the MR
After the MR
export const bulkCheckIllnessSymptomGroupRelations = async (
relations: IllnessSymptomGroupRelation[],
): Promise<ScIcIntegrityCheckError[]> => {
const publicationErrors = await FeatureFlags.isOn("fixPublication") ?
await bulkCheck...PublicationScores(getRelationIds(relations))
await bulkCheck...PublicationScoresOld(relations)
return [
...publicationErrors,
...(await bulkCheckUnlockedIllnessesWithLockedSymptoms(relations)),
...(await bulkCheckBodyTagQuestionsOnSymptom(relations)),
]
}
With Feature Flag