Linking GitHub usernames with Indent
If you're using Indent to manage GitHub, you'll need to link your team's GitHub usernames to their usernames in Slack. This guide will walk you through how to do that automatically.
Prerequisites
- Node.js v18+
- Indent API key
1. Get your API key
First, you'll need an Indent space and API token which you can find here: indent.com/api-keys
- Current User
- Sign in to get API key
- Can take actions on your behalf
- Appears in audit log as you
- Indent Space
- Access Token
- Note: this token is short lived and will expire soon
- .env
INDENT_SPACE= INDENT_API_TOKEN=************************************************************************************
The INDENT_SPACE
is the Indent account you want to use for requests and an INDENT_API_TOKEN
which is used for authentication. There are two kinds of API tokens: short-lived user access tokens and long-lived service account tokens. Read more about API authentication.
2. Prepare CSV of usernames
Create a folder for your project:
mkdir indent-guide-link-github
Next, you'll need to prepare a CSV file with the GitHub usernames you want to link. The CSV should have a header row with the column names email
and github_id
:
email,github_id
[email protected],user-example-on-github
[email protected],other-example-on-github
3. Upload GitHub usernames
Finally, you can run the following script to link the GitHub usernames with Indent. Ensure that you've exported the INDENT_SPACE
and INDENT_API_TOKEN
environment variables.
You can initialize a new Node.js project and install the dependencies:
npm init -y
npm install --save papaparse axios
Then in a file called index.mjs
(the extension .mjs
allows use of import
keyword) you can add the following code:
import fs from 'fs'
import axios from 'axios'
import Papa from 'papaparse'
async function readCSV(filePath) {
const csvFile = fs.readFileSync(filePath, 'utf8')
return new Promise((resolve, reject) => {
Papa.parse(csvFile, {
header: true,
complete: resolve,
error: reject,
})
})
}
async function updateResources(csvFilePath) {
const parsedCSV = await readCSV(csvFilePath)
const { resources: users } = await listUsers()
const updates = parsedCSV.data
.map(
({
email,
// Replace with the actual column name for the GitHub ID
github_id: githubId,
}) => {
const user = users.find((u) => u.email === email)
if (user && user.labels['github/id'] !== githubId) {
return {
...user,
labels: { ...user.labels, 'github/id': githubId },
}
}
}
)
.filter(Boolean)
if (updates.length > 0) {
await bulkUpdate({ resources: updates })
console.log(`Updated ${updates.length} users:`)
updates.forEach((u) =>
console.log(` - ${u.email} (${u.kind}) :: ${u.labels['github/id']}`)
)
} else {
console.log('No updates required.')
}
}
const spaceName = process.env.INDENT_SPACE
const accessToken = process.env.INDENT_API_TOKEN
async function listUsers() {
const api = client()
return await api({
method: 'get',
url: `/v1/spaces/${spaceName}/resources?labelSelector=indent.com/resource/kind=slack/user`,
}).then((r) => r.data)
}
async function bulkUpdate(req) {
const api = client()
return await api({
method: 'put',
url: `/v1/spaces/${spaceName}/resources:bulkUpdate`,
data: req,
}).then((r) => {
console.log(r.data)
return r.data
})
}
function client() {
if (!spaceName) {
throw new Error('INDENT_SPACE is required')
}
if (!accessToken) {
throw new Error('INDENT_API_TOKEN is required')
}
return axios.create({
baseURL: 'https://platform.indentapis.com',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
})
}
// Call the function with the path to your CSV file
updateResources('./github_usernames.csv').catch(console.error)
To run the script, use your API key from step 1 to run the following command:
INDENT_SPACE=my-space INDENT_API_TOKEN=access-token node index.mjs
Updated 2 users:
- [email protected] (slack/user) :: user-example-on-github
- [email protected] (slack/user) :: other-example-on-github