Skip to content

Commit b8f8d8a

Browse files
committed
Allow system, segment and team to be linked to other databases
1 parent 0969839 commit b8f8d8a

6 files changed

Lines changed: 145 additions & 26 deletions

File tree

action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ inputs:
1616
database:
1717
description: 'Parent database to add to'
1818
required: true
19+
system_database:
20+
description: 'Database ID to read systems from'
21+
segment_database:
22+
description: 'Database ID to read segments from'
23+
team_database:
24+
description: 'Database ID to read teams from'
1925
repository_type:
2026
description: 'Github repository type (e.g. all|private|internal), defaults to `all`'
2127
catalog_file:

catalog-info.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ metadata:
55
description: A githb action to keep a notion database in sync with Github repository info
66
annotations:
77
segment: general
8-
team: all
8+
team: opensource
99
tags:
1010
- notion
1111
- github

readme.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ First, you need to have an integration access token - which you can get from htt
88

99
By default integrations cant access any content so you you *must* share your database (or the parent page / tree it is contained within) with the integration you created earlier to be able to access it.
1010

11-
## Notion Database
11+
## Notion Databases
1212

13-
This action expects a Notion database with the following properties:
13+
This action expects a Notion database with the following properties, this will become the
1414

1515
- Name: text
1616
- Description: text
@@ -30,6 +30,19 @@ It looks like this after it has run:
3030

3131
<img width="1451" alt="Screenshot 2021-12-19 at 12 55 39" src="https://user-images.githubusercontent.com/239305/146673989-01187d53-d2fd-42ba-9968-31442b8cc92d.png">
3232

33+
## Relation Databases
34+
35+
You have an option to provide additional 'lookup' databases to convert some of the above selects into relations:
36+
37+
### Segment, Team, System
38+
39+
1. Create a database that has *at least* a `Name` column that is unique, all other columns are up to you.
40+
2. Create an 'Unknown' row - this is what services that cannot be mapped go to (this name matters).
41+
3. In the config of the action, provide the input variable `segment_database` pointing to this database.
42+
4. In the main service catalogue table convert the `Segment` column to a relation, pointing at the above database.
43+
44+
This can be repeated for `Team` and `System`. The full config is below in the usage.
45+
3346
## Service Descriptor Format
3447

3548
This action expects each of your repositories to have a descriptor file format in the root of the repo in the form of a Backstage `catalog-info` file. This is because we are testing this approach against using Backstage directly, and wanted to leverage a format that perhaps has a chance of becoming a defacto standard. It does not currently map all fields from Backstage, but if you look at the code you can see what it does map. I may add a config option to allow mapping to be more dynamic in future (a good PR!).
@@ -57,6 +70,9 @@ jobs:
5770
github_token: ${{ secrets.PAT_GITHUB_TOKEN }}
5871
notion_token: ${{ secrets.NOTION_TOKEN }}
5972
database: 2b26b4290cc84d95ad3e93c3255277a1
73+
segment_database: '7943615f4dba43b3a3b0f991f4f7136d'
74+
team_database: 'c11736fe61b941149de098676bde8d92'
75+
system_database: '121534684fe840a1953500e603c2b602'
6076
repository_type: all
6177
catalog_file: catalog-info.yaml
6278

src/index.js

Lines changed: 111 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ try {
77
const NOTION_TOKEN = core.getInput('notion_token')
88
const GITHUB_TOKEN = core.getInput('github_token')
99
const database = core.getInput('database')
10+
const systemDb = core.getInput('system_database')
11+
const segmentDb = core.getInput('segment_database')
12+
const teamDb = core.getInput('team_database')
1013
const owner = core.getInput('github_owner')
1114
const catalogFile = core.getInput('catalog_file') || 'catalog-info.yaml'
1215
const repositoryType = core.getInput('repository_type') || 'all'
@@ -17,8 +20,6 @@ try {
1720
logLevel: LogLevel.ERROR
1821
})
1922

20-
console.log(database, owner)
21-
2223
const octokit = new Octokit({ auth: GITHUB_TOKEN })
2324

2425
const getRepos = async () => {
@@ -55,7 +56,60 @@ try {
5556
return repoData
5657
}
5758

58-
const createProperties = (repo) => {
59+
const createProperties = (repo, { systems, segments, teams }) => {
60+
let segment, team, system
61+
const segmentAnnotation = repo?.metadata?.annotations?.segment
62+
const systemAnnotation = repo?.metadata?.annotations?.system
63+
const teamAnnotation = repo?.metadata?.annotations?.team
64+
65+
if (segments) {
66+
// Segments are a relation
67+
segment = {
68+
relation: [
69+
{ id: segments[segmentAnnotation?.toLowerCase()] || segments.unknown }
70+
]
71+
}
72+
} else {
73+
// Segments are a tag
74+
segment = {
75+
select: {
76+
name: segmentAnnotation || 'Unknown'
77+
}
78+
}
79+
}
80+
81+
if (teams) {
82+
// Teams are a relation
83+
team = {
84+
relation: [
85+
{ id: teams[teamAnnotation?.toLowerCase()] || teams.unknown }
86+
]
87+
}
88+
} else {
89+
// Teams are a tag
90+
team = {
91+
select: {
92+
name: teamAnnotation || 'Unknown'
93+
}
94+
}
95+
}
96+
97+
if (systems) {
98+
// Segments are a relation
99+
system = {
100+
relation: [
101+
{ id: systems[systemAnnotation?.toLowerCase()] || systems.unknown }
102+
]
103+
}
104+
} else {
105+
// Segments are a tag
106+
system = {
107+
select: {
108+
name: systemAnnotation || 'Unknown'
109+
}
110+
}
111+
}
112+
59113
return {
60114
Name: {
61115
title: [
@@ -83,16 +137,9 @@ try {
83137
URL: {
84138
url: repo._repo.html_url
85139
},
86-
Segment: {
87-
select: {
88-
name: repo?.metadata?.annotations?.segment || 'Unknown'
89-
}
90-
},
91-
Team: {
92-
select: {
93-
name: repo?.metadata?.annotations?.team || 'Unknown'
94-
}
95-
},
140+
Segment: segment,
141+
Team: team,
142+
System: system,
96143
Visibility: {
97144
select: {
98145
name: repo._repo.visibility
@@ -119,31 +166,31 @@ try {
119166
}
120167
}
121168

122-
const updateNotionRow = async (repo, pageId) => {
169+
const updateNotionRow = async (repo, pageId, { systems, segments, teams }) => {
123170
try {
124171
await notion.pages.update({
125172
page_id: pageId,
126-
properties: createProperties(repo)
173+
properties: createProperties(repo, { systems, segments, teams })
127174
})
128175
} catch (ex) {
129176
core.error(`Error updating notion document for ${repo._repo.name}: ${ex.message} ...`)
130177
}
131178
}
132179

133-
const createNotionRow = async (repo) => {
180+
const createNotionRow = async (repo, { systems, segments, teams }) => {
134181
try {
135182
await notion.pages.create({
136183
parent: {
137184
database_id: database
138185
},
139-
properties: createProperties(repo)
186+
properties: createProperties(repo, { systems, segments, teams })
140187
})
141188
} catch (ex) {
142189
core.error(`Error creating notion document for ${repo._repo.name}: ${ex.message} ...`)
143190
}
144191
}
145192

146-
const updateNotion = async (repositories) => {
193+
const updateNotion = async (repositories, { systems, segments, teams }) => {
147194
for (const repo of repositories) {
148195
// Lets see if we can find the row
149196
const search = await notion.databases.query({
@@ -161,19 +208,62 @@ try {
161208
// Lets just update the first one to not make the problem worse
162209
if (search.results.length > 0) {
163210
const pageId = search.results[0].id
164-
await updateNotionRow(repo, pageId)
211+
await updateNotionRow(repo, pageId, { systems, segments, teams })
165212
} else {
166-
await createNotionRow(repo)
213+
await createNotionRow(repo, { systems, segments, teams })
167214
}
168215
}
169216
}
170217

218+
const loadData = async () => {
219+
const processRows = (data) => {
220+
const parent = {}
221+
data.results.forEach((row) => {
222+
const name = row.properties.Name.title[0].plain_text.toLowerCase()
223+
if (name) parent[name] = row.id
224+
})
225+
return parent
226+
}
227+
228+
let systemRows, segmentRows, teamRows
229+
230+
if (systemDb) {
231+
systemRows = await notion.databases.query({
232+
database_id: systemDb
233+
})
234+
}
235+
236+
if (segmentDb) {
237+
segmentRows = await notion.databases.query({
238+
database_id: segmentDb
239+
})
240+
}
241+
242+
if (teamDb) {
243+
teamRows = await notion.databases.query({
244+
database_id: teamDb
245+
})
246+
}
247+
248+
return {
249+
systems: systemDb ? processRows(systemRows) : null,
250+
segments: segmentDb ? processRows(segmentRows) : null,
251+
teams: teamDb ? processRows(teamRows) : null
252+
}
253+
}
254+
171255
const refreshData = async () => {
256+
core.startGroup('Loading systems, segments and teams')
257+
const { systems, segments, teams } = await loadData()
258+
core.info(`Loaded ${Object.keys(systems || {}).length} systems`)
259+
core.info(`Loaded ${Object.keys(segments || {}).length} segments`)
260+
core.info(`Loaded ${Object.keys(teams || {}).length} teams`)
261+
core.endGroup()
172262
core.startGroup('🌀 Getting github repositories')
173263
const repositories = await getRepos()
174264
core.endGroup()
175265
core.startGroup(`✨ Updating notion with ${repositories.length} services ...`)
176-
await updateNotion(repositories)
266+
await updateNotion(repositories, { systems, segments, teams })
177267
core.endGroup()
178268
}
179269

src/index.test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ test('complete input should succeed with default inputs', () => {
1010
process.env.INPUT_GITHUB_TOKEN = process.env.GITHUB_TOKEN
1111
process.env.INPUT_REPOSITORY_TYPE = 'public'
1212
process.env.INPUT_GITHUB_OWNER = 'infinitaslearning'
13+
process.env.INPUT_SEGMENT_DATABASE = '7943615f4dba43b3a3b0f991f4f7136d'
14+
process.env.INPUT_TEAM_DATABASE = 'c11736fe61b941149de098676bde8d92'
15+
process.env.INPUT_SYSTEM_DATABASE = '121534684fe840a1953500e603c2b602'
16+
1317
const ip = path.join(__dirname, 'index.js')
1418
const options = {
1519
env: process.env

src/local.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ const { spawn } = require('child_process')
22
const path = require('path')
33
const process = require('process')
44

5-
process.env.INPUT_DATABASE = '2b26b4290cc84d95ad3e93c3255277a1' // 'cecaf0beb15945158d155866ff9acce8'
5+
process.env.INPUT_DATABASE = 'cecaf0beb15945158d155866ff9acce8' // '2b26b4290cc84d95ad3e93c3255277a1'
66
process.env.INPUT_NOTION_TOKEN = process.env.NOTION_TOKEN
77
process.env.INPUT_GITHUB_TOKEN = process.env.GITHUB_TOKEN
8-
process.env.INPUT_REPOSITORY_TYPE = 'all'
8+
process.env.INPUT_REPOSITORY_TYPE = 'public'
99
process.env.INPUT_GITHUB_OWNER = 'infinitaslearning'
10+
process.env.INPUT_SEGMENT_DATABASE = '7943615f4dba43b3a3b0f991f4f7136d'
11+
process.env.INPUT_TEAM_DATABASE = 'c11736fe61b941149de098676bde8d92'
12+
process.env.INPUT_SYSTEM_DATABASE = '121534684fe840a1953500e603c2b602'
1013

1114
const ip = path.join(__dirname, 'index.js')
1215
const options = {

0 commit comments

Comments
 (0)