Skip to content

Commit 63b3a52

Browse files
authored
Merge branch 'develop' into na/backend/add-exclude-attending
2 parents ad90c2e + 7656ca8 commit 63b3a52

77 files changed

Lines changed: 1508 additions & 832 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/autoreviewers.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ web Couchers-org/web:
1313
mobile Couchers-org/mobile:
1414
- 'app/mobile/**'
1515
- '!app/mobile/**/locales/*.json'
16+
fingerprints aapeliv:
17+
- 'app/mobile/fingerprint*'
1618
locales tristanlabelle:
1719
- 'app/**/locales/*.json'
1820
i18n tristanlabelle:

app/.gitlab-ci.yml

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
# suppress external PR pipelines: they duplicate the branch pipeline per PR
2+
# push (job rules key on CI_COMMIT_BRANCH, which is unset there yet matches)
3+
workflow:
4+
rules:
5+
- if: $CI_PIPELINE_SOURCE == "external_pull_request_event"
6+
when: never
7+
- when: always
8+
19
stages:
210
- protos
311
- build
@@ -340,7 +348,7 @@ test:backend:
340348
- cp /app/.coverage.$CI_NODE_INDEX $CI_PROJECT_DIR/
341349
- cp /app/.test_durations.$CI_NODE_INDEX $CI_PROJECT_DIR/
342350
- mkdir -p $CI_PROJECT_DIR/artifacts/test_artifacts
343-
- cp /app/test_artifacts/* $CI_PROJECT_DIR/artifacts/test_artifacts/ 2>/dev/null || true
351+
- cp -r /app/test_artifacts/* $CI_PROJECT_DIR/artifacts/test_artifacts/ 2>/dev/null || true
344352
artifacts:
345353
reports:
346354
junit: junit-$CI_NODE_INDEX.xml
@@ -762,6 +770,7 @@ preview:backend:
762770
- aws s3 rm s3://$AWS_PREVIEW_BUCKET/test-artifacts/$CI_COMMIT_REF_SLUG/ --recursive
763771
- aws s3 cp artifacts/test_artifacts s3://$AWS_PREVIEW_BUCKET/test-artifacts/$CI_COMMIT_REF_SLUG/ --recursive 2>/dev/null || true
764772
- echo "Done, test artifacts available at https://$CI_COMMIT_SHORT_SHA--test-artifacts.$PREVIEW_DOMAIN/ and https://$CI_COMMIT_REF_SLUG--test-artifacts.$PREVIEW_DOMAIN/"
773+
- echo "Sample emails index at https://$CI_COMMIT_SHORT_SHA--test-artifacts.$PREVIEW_DOMAIN/emails/index.html and https://$CI_COMMIT_REF_SLUG--test-artifacts.$PREVIEW_DOMAIN/emails/index.html"
765774
artifacts:
766775
paths:
767776
- artifacts/schema_dumps
@@ -888,12 +897,19 @@ build:mobile-ota-devtool:
888897
- npm ci
889898
- npx expo config --type public --json > ota-expo-config.json
890899
- |
900+
# develop's preview keeps the build default (staging web)
901+
WEB_BASE_URL=""
902+
if [ "$CI_COMMIT_BRANCH" != "$RELEASE_BRANCH" ]; then
903+
WEB_BASE_URL=$(node scripts/vercel-preview-url.mjs --branch "$CI_COMMIT_BRANCH" --sha "$CI_COMMIT_SHA")
904+
fi
905+
echo "web base url: ${WEB_BASE_URL:-(build default)}"
891906
for P in $OTA_PLATFORMS; do
892907
rm -rf dist
893908
npx expo export --platform "$P"
894909
RV=$(npx expo-updates fingerprint:generate --platform "$P" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).hash))')
895910
echo "fingerprint($P) = $RV"
896-
node scripts/ota-stage.mjs --platform "$P" --runtime-version "$RV" --base-url "https://$CI_COMMIT_SHORT_SHA--ota.$PREVIEW_DOMAIN" --dist dist --out ota-out --expo-config ota-expo-config.json
911+
node scripts/ota-bundle.mjs --platform "$P" --runtime-version "$RV" --base-url "https://$CI_COMMIT_SHORT_SHA--ota.$PREVIEW_DOMAIN" --dist dist --out ota-out --expo-config ota-expo-config.json ${WEB_BASE_URL:+--web-base-url "$WEB_BASE_URL"}
912+
node scripts/ota-open-page.mjs --manifest-url "https://$CI_COMMIT_SHORT_SHA--ota.$PREVIEW_DOMAIN/$P/manifest" --out "ota-out/$P/open.html"
897913
npx --yes qrcode -o "ota-out/$P/qr.png" "couchers-devtool://expo-development-client/?url=https%3A%2F%2F$CI_COMMIT_SHORT_SHA--ota.$PREVIEW_DOMAIN%2F$P%2Fmanifest" < /dev/null
898914
done
899915
artifacts:
@@ -938,26 +954,40 @@ preview:mobile-ota-devtool:
938954
- app/mobile/**/*
939955
- app/scripts/**/*
940956

957+
# posts the comment placeholder within seconds of the push
958+
preview:pr-comment-stub:
959+
needs: []
960+
stage: preview
961+
image: python:3.14-slim
962+
inherit:
963+
default: false
964+
# serialize comment writes across concurrent pipelines
965+
resource_group: pr-preview-comment
966+
script:
967+
- pip install --quiet --no-cache-dir requests
968+
- python app/scripts/pr_preview_comment.py --stub
969+
rules:
970+
- if: $CI_COMMIT_BRANCH != $RELEASE_BRANCH
971+
941972
preview:pr-comment:
942973
needs:
974+
- job: preview:pr-comment-stub
975+
artifacts: false
943976
- job: preview:mobile-ota-devtool
944977
artifacts: false
978+
optional: true
945979
stage: preview
946980
image: python:3.14-slim
947981
inherit:
948982
default: false
983+
resource_group: pr-preview-comment
949984
variables:
950985
OTA_PLATFORMS: "ios android"
951986
script:
952987
- pip install --quiet --no-cache-dir requests
953988
- python app/scripts/pr_preview_comment.py
954989
rules:
955-
- if: ($BUILD_MOBILE == "true") && ($CI_COMMIT_BRANCH == $RELEASE_BRANCH)
956-
- if: ($BUILD_MOBILE == "true") && ($CI_COMMIT_BRANCH != $RELEASE_BRANCH)
957-
changes:
958-
- app/proto/**/*
959-
- app/mobile/**/*
960-
- app/scripts/**/*
990+
- if: $CI_COMMIT_BRANCH != $RELEASE_BRANCH
961991

962992
build:mobile-native-devtool:
963993
needs: ["protos"]
@@ -1009,7 +1039,7 @@ build:mobile-ota-staging:
10091039
npx sentry-expo-upload-sourcemaps dist
10101040
RV=$(npx expo-updates fingerprint:generate --platform "$P" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).hash))')
10111041
echo "fingerprint($P) = $RV"
1012-
node scripts/ota-stage.mjs --platform "$P" --runtime-version "$RV" --base-url "$OTA_CDN_BASE" --dist dist --out ota-staging-out --expo-config ota-expo-config.json
1042+
node scripts/ota-bundle.mjs --platform "$P" --runtime-version "$RV" --base-url "$OTA_CDN_BASE" --dist dist --out ota-staging-out --expo-config ota-expo-config.json
10131043
node scripts/ota-sign.mjs --dir "ota-staging-out/$P" --key-file ota-staging-private-key.pem --key-id staging
10141044
done
10151045
- rm -f ota-staging-private-key.pem
@@ -1216,7 +1246,7 @@ build:mobile-ota-prod:
12161246
npx sentry-expo-upload-sourcemaps dist
12171247
RV=$(npx expo-updates fingerprint:generate --platform "$P" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).hash))')
12181248
echo "fingerprint($P) = $RV"
1219-
node scripts/ota-stage.mjs --platform "$P" --runtime-version "$RV" --base-url '__OTA_BUNDLE_BASE__' --dist dist --out ota-prod-out --expo-config ota-expo-config.json
1249+
node scripts/ota-bundle.mjs --platform "$P" --runtime-version "$RV" --base-url '__OTA_BUNDLE_BASE__' --dist dist --out ota-prod-out --expo-config ota-expo-config.json
12201250
tar -C ota-prod-out/"$P" -czf "native-ota-dist/native-ota-$P-$CI_PIPELINE_ID-$CI_COMMIT_SHA.tar.gz" .
12211251
done
12221252
artifacts:

app/backend/src/couchers/constants.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
EMAIL_REGEX = r"^[0-9a-z]([0-9a-z\-\_\+]|(\.[0-9a-z\-\_\+]))*@([0-9a-z\-]+\.)*[0-9a-z\-]+\.[a-z]{2,}$"
1414

15-
# Must match the frontend pattern in app/web/utils/validation.ts
15+
# Must match the frontend values in app/web/utils/validation.ts
16+
VALID_NAME_MIN_LENGTH = 2
17+
VALID_NAME_MAX_LENGTH = 100
1618
VALID_NAME_REGEX = r"^[\p{L}'-]+(\s+[\p{L}'-]+)*$"
1719

1820
BANNED_USERNAME_PHRASES = [

app/backend/src/couchers/context.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(
7272
token: str | None,
7373
localization: LocalizationContext,
7474
sofa: str | None = None,
75+
serialize_shadowed: bool,
7576
):
7677
"""Don't ever construct directly, always use the `make_*_context_` functions!"""
7778
self._grpc_context = grpc_context
@@ -80,6 +81,7 @@ def __init__(
8081
self.__token = token
8182
self.__localization = localization
8283
self._sofa = sofa
84+
self.__serialize_shadowed = serialize_shadowed
8385
self.__is_interactive = is_interactive
8486
self.__logged_in = self._user_id is not None
8587
self.__cookies: list[str] = []
@@ -192,6 +194,10 @@ def token(self) -> str:
192194
def localization(self) -> LocalizationContext:
193195
return self.__localization
194196

197+
@property
198+
def serialize_shadowed(self) -> bool:
199+
return self.__serialize_shadowed
200+
195201
# Feature-flag evaluation methods mirror the OpenFeature evaluation API, evaluating for this
196202
# context's user. The gating lives in experimentation; we just pass our cached per-request
197203
# evaluator. The in-code default is honored even for flags not yet set up in GrowthBook.
@@ -233,6 +239,7 @@ def make_interactive_context(
233239
token=token,
234240
localization=localization,
235241
sofa=sofa,
242+
serialize_shadowed=False,
236243
)
237244

238245

@@ -244,6 +251,7 @@ def make_one_off_interactive_user_context(couchers_context: CouchersContext, use
244251
is_api_key=None,
245252
token=None,
246253
localization=couchers_context.localization,
254+
serialize_shadowed=False,
247255
)
248256

249257

@@ -255,6 +263,7 @@ def make_media_context(grpc_context: grpc.ServicerContext) -> CouchersContext:
255263
grpc_context=grpc_context,
256264
token=None,
257265
localization=LocalizationContext.en_utc(),
266+
serialize_shadowed=False,
258267
)
259268

260269

@@ -266,6 +275,19 @@ def make_background_user_context(user_id: int, localization: LocalizationContext
266275
grpc_context=None,
267276
token=None,
268277
localization=localization or LocalizationContext.en_utc(),
278+
serialize_shadowed=False,
279+
)
280+
281+
282+
def make_notification_user_context(user_id: int, localization: LocalizationContext | None = None) -> CouchersContext:
283+
return CouchersContext(
284+
is_interactive=False,
285+
user_id=user_id,
286+
is_api_key=None,
287+
grpc_context=None,
288+
token=None,
289+
localization=localization or LocalizationContext.en_utc(),
290+
serialize_shadowed=True,
269291
)
270292

271293

@@ -277,4 +299,5 @@ def make_logged_out_context(localization: LocalizationContext) -> CouchersContex
277299
grpc_context=None,
278300
token=None,
279301
localization=localization,
302+
serialize_shadowed=False,
280303
)

0 commit comments

Comments
 (0)