Skip to content

Commit c414be3

Browse files
Merge remote-tracking branch 'origin/main' into eric/temporary-language-selection
* origin/main: (29 commits) add patent pledge link to readme (#9118) Fix feedfeedback metrics not distinguishing which feed it's from (#9099) Nightly source-language update Add StackedButton component (#9086) [Web] Fix thread jumps (#9111) Button tweaks (#9106) Update admonition component (#9068) fix gap on profile (#9081) Nightly source-language update Catch errors on geolocation request, reduce Sentry logs (#9098) remove root sibling library (#9097) don't send some "activity no longer available" errors (#9100) Log OTA errors properly (#9101) Fix link crash (#9102) Send inferrable interactions to third-party feeds (#9094) patch react native screens (#9087) fix: remove escapejs and fix profile issues feat: profile.html escapejs feat: post.html structured content, wip feat: profile.html structured content ...
2 parents ebf4715 + 5fd52b3 commit c414be3

File tree

268 files changed

+2971
-4582
lines changed

Some content is hidden

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

268 files changed

+2971
-4582
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = {
3737
'Toast.Action',
3838
'AgeAssuranceAdmonition',
3939
'Span',
40+
'StackedButton',
4041
],
4142
impliedTextProps: [],
4243
suggestedTextWrappers: {

.github/workflows/build-and-push-link-aws.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
name: build-and-push-link-aws
22
on:
33
workflow_dispatch:
4+
pull_request:
5+
paths:
6+
- 'bskylink/**'
7+
- 'Dockerfile.bskylink'
8+
- '.github/workflows/build-and-push-link-aws.yaml'
49

510
env:
611
REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_REGISTRY }}
@@ -45,7 +50,7 @@ jobs:
4550
uses: docker/build-push-action@v4
4651
with:
4752
context: .
48-
push: ${{ github.event_name != 'pull_request' }}
53+
push: true
4954
file: ./Dockerfile.bskylink
5055
tags: ${{ steps.meta.outputs.tags }}
5156
labels: ${{ steps.meta.outputs.labels }}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ Bluesky is an open social network built on the AT Protocol, a flexible technolog
7070

7171
See [./LICENSE](./LICENSE) for the full license.
7272

73+
Bluesky Social PBC has committed to a software patent non-aggression pledge. For details see [the original announcement](https://bsky.social/about/blog/10-01-2025-patent-pledge).
74+
7375
## P.S.
7476

7577
We ❤️ you and all of the ways you support us. Thank you for making Bluesky a great place!

bskylink/src/bin.ts

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,62 @@
11
import {Database, envToCfg, httpLogger, LinkService, readEnv} from './index.js'
2+
23
async function main() {
3-
const env = readEnv()
4-
const cfg = envToCfg(env)
5-
if (cfg.db.migrationUrl) {
6-
const migrateDb = Database.postgres({
7-
url: cfg.db.migrationUrl,
8-
schema: cfg.db.schema,
9-
})
10-
await migrateDb.migrateToLatestOrThrow()
11-
await migrateDb.close()
12-
}
4+
try {
5+
httpLogger.info('Starting blink service')
136

14-
const link = await LinkService.create(cfg)
7+
const env = readEnv()
8+
const cfg = envToCfg(env)
159

16-
if (link.ctx.cfg.service.safelinkEnabled) {
17-
link.ctx.safelinkClient.runFetchEvents()
18-
}
10+
httpLogger.info(
11+
{
12+
port: cfg.service.port,
13+
safelinkEnabled: cfg.service.safelinkEnabled,
14+
hasDbUrl: !!cfg.db.url,
15+
hasDbMigrationUrl: !!cfg.db.migrationUrl,
16+
},
17+
'Configuration loaded',
18+
)
19+
20+
if (cfg.db.migrationUrl) {
21+
httpLogger.info('Running database migrations')
22+
const migrateDb = Database.postgres({
23+
url: cfg.db.migrationUrl,
24+
schema: cfg.db.schema,
25+
})
26+
await migrateDb.migrateToLatestOrThrow()
27+
await migrateDb.close()
28+
httpLogger.info('Database migrations completed')
29+
}
1930

20-
await link.start()
21-
httpLogger.info('link service is running')
22-
process.on('SIGTERM', async () => {
23-
httpLogger.info('link service is stopping')
24-
await link.destroy()
25-
httpLogger.info('link service is stopped')
26-
})
31+
httpLogger.info('Creating LinkService')
32+
const link = await LinkService.create(cfg)
33+
34+
if (link.ctx.cfg.service.safelinkEnabled) {
35+
httpLogger.info('Starting Safelink client')
36+
link.ctx.safelinkClient.runFetchEvents()
37+
}
38+
39+
await link.start()
40+
httpLogger.info('Link service is running')
41+
42+
process.on('SIGTERM', async () => {
43+
httpLogger.info('Link service is stopping')
44+
await link.destroy()
45+
httpLogger.info('Link service is stopped')
46+
})
47+
} catch (error) {
48+
httpLogger.error(
49+
{
50+
error: String(error),
51+
stack: error instanceof Error ? error.stack : undefined,
52+
},
53+
'Failed to start blink service',
54+
)
55+
process.exit(1)
56+
}
2757
}
2858

29-
main()
59+
main().catch(error => {
60+
console.error('Unhandled startup error:', error)
61+
process.exit(1)
62+
})

bskylink/src/db/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ export class Database {
3434

3535
static postgres(opts: PgOptions): Database {
3636
const {schema, url, txLockNonce} = opts
37+
log.info(
38+
{
39+
schema,
40+
poolSize: opts.poolSize,
41+
poolMaxUses: opts.poolMaxUses,
42+
poolIdleTimeoutMs: opts.poolIdleTimeoutMs,
43+
},
44+
'Creating database connection',
45+
)
46+
3747
const pool =
3848
opts.pool ??
3949
new Pg.Pool({

bskyogcard/src/index.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ export class CardService {
6262
// Start main application server
6363
this.server = this.app.listen(this.ctx.cfg.service.port)
6464
this.server.keepAliveTimeout = 90000
65-
this.terminator = createHttpTerminator({server: this.server})
65+
this.terminator = createHttpTerminator({
66+
server: this.server,
67+
gracefulTerminationTimeout: 15000, // 15s timeout for in-flight requests
68+
})
6669
await events.once(this.server, 'listening')
6770

6871
// Start separate metrics server
@@ -73,13 +76,32 @@ export class CardService {
7376
})
7477

7578
this.metricsServer = metricsApp.listen(this.ctx.cfg.service.metricsPort)
76-
this.metricsTerminator = createHttpTerminator({server: this.metricsServer})
79+
this.metricsTerminator = createHttpTerminator({
80+
server: this.metricsServer,
81+
gracefulTerminationTimeout: 2000, // 2s timeout for metrics server
82+
})
7783
await events.once(this.metricsServer, 'listening')
7884
}
7985

8086
async destroy() {
87+
const startTime = Date.now()
88+
8189
this.ctx.abortController.abort()
82-
await this.terminator?.terminate()
83-
await this.metricsTerminator?.terminate()
90+
91+
const shutdownPromises = []
92+
93+
if (this.terminator) {
94+
shutdownPromises.push(this.terminator.terminate())
95+
}
96+
97+
if (this.metricsTerminator) {
98+
shutdownPromises.push(this.metricsTerminator.terminate())
99+
}
100+
101+
await Promise.all(shutdownPromises)
102+
103+
const elapsed = Date.now() - startTime
104+
const {httpLogger} = await import('./logger.js')
105+
httpLogger.info(`Graceful shutdown completed in ${elapsed}ms`)
84106
}
85107
}

bskyweb/templates/post.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,41 @@
5656
<meta property="article:published_time" content="{{ postView.IndexedAt }}">
5757
<link rel="alternate" type="application/json+oembed" href="https://embed.bsky.app/oembed?format=json&url={{ postView.Uri | urlencode }}" />
5858
<link rel="alternate" href="{{ postView.Uri }}" />
59+
<script type="application/ld+json">
60+
{
61+
"@context": "https://schema.org",
62+
"@type": "DiscussionForumPosting",
63+
"author": {
64+
"@type": "Person",
65+
"name": "{{ postView.Author.DisplayName }}",
66+
"url": "https://bsky.app/profile/{{ postView.Author.Handle }}"
67+
},
68+
{%- if postText %}
69+
"text": "{{ postText }}",
70+
{% endif %}
71+
{%- if imageThumbUrls %}
72+
"image": "{{ imageThumbUrls[0] }}",
73+
{% endif %}
74+
"datePublished": "{{ postView.IndexedAt }}",
75+
"interactionStatistic": [
76+
{
77+
"@type": "InteractionCounter",
78+
"interactionType": "https://schema.org/LikeAction",
79+
"userInteractionCount": {{ postView.LikeCount }}
80+
},
81+
{
82+
"@type": "InteractionCounter",
83+
"interactionType": "https://schema.org/CommentAction",
84+
"userInteractionCount": {{ postView.ReplyCount }}
85+
},
86+
{
87+
"@type": "InteractionCounter",
88+
"interactionType": "https://schema.org/ShareAction",
89+
"userInteractionCount": {{ postView.RepostCount + postView.QuoteCount }}
90+
}
91+
]
92+
}
93+
</script>
5994
{%- elif requiresAuth and profileHandle -%}
6095
<meta property="og:type" content="article">
6196
<meta property="profile:username" content="{{ profileHandle }}">

bskyweb/templates/profile.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,41 @@
5151
<meta property="og:description" content="This profile requires authentication to view.">
5252
<meta property="twitter:description" content="This profile requires authentication to view.">
5353
{% endif %}
54+
55+
<script type="application/ld+json">
56+
{
57+
"@context": "https://schema.org",
58+
"@type": "ProfilePage",
59+
"dateCreated": "{{ profileView.CreatedAt }}",
60+
"mainEntity": {
61+
"@type": "Person",
62+
"name": "{{ profileView.DisplayName }}",
63+
"alternateName": "@{{ profileView.Handle }}",
64+
"identifier": "{{ profileView.Did }}",
65+
"description": "{{ profileView.Description }}",
66+
"image": "{{ profileView.Avatar }}",
67+
"interactionStatistic": [
68+
{
69+
"@type": "InteractionCounter",
70+
"interactionType": "https://schema.org/FollowAction",
71+
"userInteractionCount": {{ profileView.FollowersCount }}
72+
}
73+
],
74+
"agentInteractionStatistic": [
75+
{
76+
"@type": "InteractionCounter",
77+
"interactionType": "https://schema.org/FollowAction",
78+
"userInteractionCount": {{ profileView.FollowsCount }}
79+
},
80+
{
81+
"@type": "InteractionCounter",
82+
"interactionType": "https://schema.org/WriteAction",
83+
"userInteractionCount": {{ profileView.PostsCount }}
84+
}
85+
]
86+
}
87+
}
88+
</script>
5489
{% endif -%}
5590
{%- endblock %}
5691

jest/test-utils.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
1-
import React from 'react'
2-
import {render} from '@testing-library/react-native'
31
import {GestureHandlerRootView} from 'react-native-gesture-handler'
4-
import {RootSiblingParent} from 'react-native-root-siblings'
52
import {SafeAreaProvider} from 'react-native-safe-area-context'
6-
import {RootStoreProvider, RootStoreModel} from '../src/state'
3+
import {render} from '@testing-library/react-native'
4+
75
import {ThemeProvider} from '../src/lib/ThemeContext'
6+
import {type RootStoreModel, RootStoreProvider} from '../src/state'
87

98
const customRender = (ui: any, rootStore: RootStoreModel) =>
109
render(
11-
// eslint-disable-next-line react-native/no-inline-styles
1210
<GestureHandlerRootView style={{flex: 1}}>
13-
<RootSiblingParent>
14-
<RootStoreProvider value={rootStore}>
15-
<ThemeProvider theme="light">
16-
<SafeAreaProvider>{ui}</SafeAreaProvider>
17-
</ThemeProvider>
18-
</RootStoreProvider>
19-
</RootSiblingParent>
11+
<RootStoreProvider value={rootStore}>
12+
<ThemeProvider theme="light">
13+
<SafeAreaProvider>{ui}</SafeAreaProvider>
14+
</ThemeProvider>
15+
</RootStoreProvider>
2016
</GestureHandlerRootView>,
2117
)
2218

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"@atproto/api": "^0.16.7",
7575
"@bitdrift/react-native": "^0.6.8",
7676
"@braintree/sanitize-url": "^6.0.2",
77+
"@bsky.app/alf": "^0.1.2",
7778
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
7879
"@emoji-mart/react": "^1.1.1",
7980
"@expo/html-elements": "^0.12.5",
@@ -196,7 +197,6 @@
196197
"react-native-progress": "bluesky-social/react-native-progress",
197198
"react-native-qrcode-styled": "^0.3.3",
198199
"react-native-reanimated": "^3.19.1",
199-
"react-native-root-siblings": "^5.0.1",
200200
"react-native-safe-area-context": "~5.6.0",
201201
"react-native-screens": "~4.16.0",
202202
"react-native-svg": "15.12.1",

0 commit comments

Comments
 (0)