Skip to content

Commit 445c389

Browse files
authored
Merge pull request #1052 from serlo/staging
Deployment (production)
2 parents 9bb0b60 + 1d4003d commit 445c389

File tree

5 files changed

+189
-255
lines changed

5 files changed

+189
-255
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Sync to GitLab
2+
on:
3+
push:
4+
branches:
5+
- staging
6+
- production
7+
8+
jobs:
9+
sync:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Sync to GitLab
13+
uses: kulla/sync-to-gitlab@v1
14+
with:
15+
owner: stephan_kulla
16+
repository_name: serlo-cloudflare-worker
17+
token: ${{ secrets.GITLAB_TOKEN }}

__tests__/current-alias-redirects.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,41 +74,31 @@ describe('redirects for course pages', () => {
7474
id: 42,
7575
__typename: 'Course',
7676
alias: '/math/42/a-course',
77-
currentRevision: {
78-
content: JSON.stringify({
79-
state: {
80-
pages: [
81-
{ id: '527bcd55-977c-489d-a3c8-9fd0feaf51a6', title: 'Foo' },
82-
{ id: 'a47077ca-a9f9-4ab9-bf22-6c26fb3490d8', title: 'Bar' },
83-
],
84-
},
85-
}),
86-
},
8777
})
8878
})
8979

9080
test('redirect first course page to course alias', async () => {
9181
const response = await localTestEnvironment().fetch({
9282
subdomain: 'en',
93-
pathname: '/math/42/527bcd55/xyz',
83+
pathname: '/math/42/527bc/foo',
9484
})
9585

9686
const target = env.createUrl({
9787
subdomain: 'en',
98-
pathname: '/math/42/a-course',
88+
pathname: '/math/42/a-course#527bc',
9989
})
10090
expectToBeRedirectTo(response, target, 301)
10191
})
10292

103-
test('redirect course page url when title was changed', async () => {
93+
test('redirect any course page url to course alias, even with differen title', async () => {
10494
const response = await localTestEnvironment().fetch({
10595
subdomain: 'en',
106-
pathname: '/math/42/a47077ca/xyz',
96+
pathname: '/math/42/a4707/xyz',
10797
})
10898

10999
const target = env.createUrl({
110100
subdomain: 'en',
111-
pathname: '/math/42/a47077ca/bar',
101+
pathname: '/math/42/a-course#a4707',
112102
})
113103
expectToBeRedirectTo(response, target, 301)
114104
})

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,18 @@
3636
"toucan-js": "^4.1.1"
3737
},
3838
"devDependencies": {
39-
"@cloudflare/workers-types": "^4.20250321.0",
40-
"@eslint/compat": "^1.2.7",
41-
"@eslint/eslintrc": "^3.3.0",
42-
"@eslint/js": "^9.23.0",
39+
"@cloudflare/workers-types": "^4.20250407.0",
40+
"@eslint/compat": "^1.2.8",
41+
"@eslint/eslintrc": "^3.3.1",
42+
"@eslint/js": "^9.24.0",
4343
"@iarna/toml": "^2.2.5",
4444
"@jest/globals": "^29.7.0",
45-
"@sentry/core": "^9.9.0",
45+
"@sentry/core": "^9.10.1",
4646
"@testing-library/jest-dom": "^6.6.3",
4747
"@types/iarna__toml": "^2.0.5",
4848
"@types/jest": "^29.5.14",
49-
"@typescript-eslint/eslint-plugin": "^8.28.0",
50-
"@typescript-eslint/parser": "^8.28.0",
49+
"@typescript-eslint/eslint-plugin": "^8.29.1",
50+
"@typescript-eslint/parser": "^8.29.1",
5151
"cross-env": "^7.0.3",
5252
"depcheck": "^1.4.7",
5353
"eslint": "^9.23.0",
@@ -61,11 +61,11 @@
6161
"npm-run-all": "^4.1.5",
6262
"prettier": "^3.5.3",
6363
"prettier-plugin-packagejson": "^2.5.10",
64-
"prettier-plugin-sh": "^0.15.0",
65-
"ts-jest": "^29.3.0",
64+
"prettier-plugin-sh": "^0.16.1",
65+
"ts-jest": "^29.3.1",
6666
"ts-unused-exports": "^11.0.1",
67-
"typescript": "^5.8.2",
68-
"wrangler": "^4.4.0"
67+
"typescript": "^5.8.3",
68+
"wrangler": "^4.8.0"
6969
},
7070
"packageManager": "[email protected]",
7171
"engines": {

src/current-alias-redirects.ts

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,6 @@ const ApiResult = t.type({
5151
const CourseResult = t.type({
5252
id: t.number,
5353
alias: t.string,
54-
currentRevision: t.type({ content: t.string }),
55-
})
56-
57-
const CourseContent = t.type({
58-
state: t.type({
59-
pages: t.array(t.type({ title: t.string, id: t.string })),
60-
}),
6154
})
6255

6356
async function getPathInfo(
@@ -94,9 +87,6 @@ async function getPathInfo(
9487
... on Course {
9588
id
9689
alias
97-
currentRevision {
98-
content
99-
}
10090
}
10191
... on Comment {
10292
id
@@ -136,53 +126,29 @@ async function getPathInfo(
136126

137127
const isTrashedComment = uuid.__typename === 'Comment' && uuid.trashed
138128
let currentPath: string = ''
129+
let hash: string = ''
139130

140131
if (coursePageId !== null) {
141132
if (!CourseResult.is(uuid)) return null
142133

143-
try {
144-
const courseContent = JSON.parse(uuid.currentRevision.content) as unknown
145-
146-
if (!CourseContent.is(courseContent)) return null
147-
148-
if (courseContent.state.pages.at(0)?.id?.startsWith(coursePageId)) {
149-
currentPath = uuid.alias
150-
} else {
151-
const coursePage = courseContent.state.pages.find((page) =>
152-
page.id.startsWith(coursePageId),
153-
)
154-
155-
if (coursePage === undefined) {
156-
// This case should never happen => return course alias as a fallback
157-
currentPath = uuid.alias
158-
} else {
159-
const subject = uuid.alias.split('/').at(1) ?? 'serlo'
160-
const slugTitle = toSlug(coursePage.title)
161-
const shortPageId = coursePage.id.split('-').at(0)
162-
if (!shortPageId) {
163-
currentPath = uuid.alias
164-
} else {
165-
currentPath = `/${subject}/${uuid.id}/${shortPageId}/${slugTitle}`
166-
}
167-
}
168-
}
169-
} catch {
170-
return null
171-
}
134+
currentPath = uuid.alias
135+
hash = `#${coursePageId}`
172136
} else {
173137
currentPath = isTrashedComment
174138
? `error/deleted/${uuid.__typename}`
175139
: uuid.legacyObject !== undefined
176140
? uuid.legacyObject.alias
177141
: (uuid.alias ?? path)
142+
143+
if (uuid.legacyObject !== undefined && !isTrashedComment) {
144+
hash = `#comment-${uuid.id ?? 0}`
145+
}
178146
}
179147

180148
const result = {
181149
currentPath,
182150
instance: uuid.instance,
183-
...(uuid.legacyObject !== undefined && !isTrashedComment
184-
? { hash: `#comment-${uuid.id ?? 0}` }
185-
: {}),
151+
...(hash ? { hash } : {}),
186152
}
187153

188154
await env.PATH_INFO_KV.put(cacheKey, JSON.stringify(result), {
@@ -199,25 +165,3 @@ async function getPathInfo(
199165
function gql(strings: TemplateStringsArray): string {
200166
return strings[0]
201167
}
202-
203-
// Copied from https://github.com/serlo/api.serlo.org/blob/ce94045b513e59da1ddd191b498fe01f6ff6aa0a/packages/server/src/schema/uuid/abstract-uuid/resolvers.ts#L685-L703
204-
// Try to keep both functions in sync
205-
function toSlug(name: string) {
206-
return name
207-
.toLowerCase()
208-
.replace(/ä/g, 'ae')
209-
.replace(/ö/g, 'oe')
210-
.replace(/ü/g, 'ue')
211-
.replace(/ß/g, 'ss')
212-
.replace(/á/g, 'a')
213-
.replace(/é/g, 'e')
214-
.replace(/í/g, 'i')
215-
.replace(/ó/g, 'o')
216-
.replace(/ú/g, 'u')
217-
.replace(/ñ/g, 'n')
218-
.replace(/ /g, '-') // replace spaces with hyphens
219-
.replace(/[^\w-]+/g, '') // remove all non-word chars including _
220-
.replace(/--+/g, '-') // replace multiple hyphens
221-
.replace(/^-+/, '') // trim starting hyphen
222-
.replace(/-+$/, '') // trim end hyphen
223-
}

0 commit comments

Comments
 (0)