Forked from rodneyrehm/sentry-clean-debug-information-files.js
Created
October 6, 2020 21:26
-
-
Save yeleleo/33f87a85774dc34c943d834894afdbc4 to your computer and use it in GitHub Desktop.
Sentry Cleanup: Debug Information Files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const axios = require('axios') | |
const LinkHeader = require('http-link-header') | |
const nextPage = (header) => { | |
const link = LinkHeader.parse(header) | |
const [ next ] = link.get('rel', 'next') | |
return next && next.results === 'true' ? next.uri : null | |
} | |
function uri (strings, ...values) { | |
const escapeValue = (value, index) => strings[index] + encodeURIComponent(value) | |
return values.map(escapeValue).join('') + strings[strings.length - 1] | |
} | |
// https://docs.sentry.io/api/ | |
class SentryClient { | |
constructor ( { url, timeout, name, token, org } ) { | |
if (url.slice(-1) === '/') { | |
url = url.slice(0, -1) | |
} | |
this.org = org | |
this.client = axios.create({ | |
baseURL: `${url}/api/0`, | |
timeout: timeout || 30000, | |
headers: { | |
'Authorization': `Bearer ${token}`, | |
'User-Agent': name || 'sentry-client', | |
}, | |
}) | |
} | |
async request ({ method, url }) { | |
try { | |
const response = await this.client.request({ method, url }) | |
// https://docs.sentry.io/api/pagination/ | |
const next = nextPage(response.headers.link || '') | |
if (next) { | |
const _next = await this.request({ method, url: next }) | |
return response.data.concat(_next) | |
} | |
return response.data | |
} catch (error) { | |
// TODO: properly unpack API errors | |
if (error.reponse) { | |
console.error('ERROR processing', method, url) | |
console.error('HTTP', error.response.status, error.response.statusText) | |
console.error('BODY', error.response.data) | |
throw new Error('Nope') | |
} else { | |
throw error | |
} | |
} | |
} | |
// https://docs.sentry.io/api/projects/get-debug-files/ | |
async getDebugFiles({ project }) { | |
return this.request({ | |
method: 'GET', | |
url: uri`/projects/${this.org}/${project}/files/dsyms/`, | |
}) | |
} | |
// https://docs.sentry.io/api/projects/get-debug-files/ | |
async deleteDebugFile({ project, id }) { | |
return this.request({ | |
method: 'DELETE', | |
url: uri`/projects/${this.org}/${project}/files/dsyms/?id=${id}`, | |
}) | |
} | |
async getAllDebugFiles({ projects }) { | |
const promises = projects.map(project => { | |
return this.getDebugFiles({ project }) | |
}) | |
const filesPerProject = await Promise.all(promises) | |
const result = [] | |
const now = Date.now() | |
function addFile (project, item) { | |
const created = new Date(item.dateCreated) | |
const since = Math.floor((now - created.getTime()) / 1000 / 3600 / 24) | |
result.push({ ...item, project, since }) | |
} | |
projects.forEach((project, index) => { | |
filesPerProject[index].forEach(item => { | |
addFile(project, item) | |
}) | |
}) | |
return result | |
} | |
} | |
// ------------------------------------------------------------- | |
const URL = 'https://my-sentry-instance.example.org' | |
const ORG = 'my-organization-slug' | |
// create at https://my-sentry-instance.example.org/settings/account/api/auth-tokens/ requesting these scopes | |
// event:admin, event:read, member:read, org:read, project:read, project:releases, team:read, project:write, project:admin | |
// no idea if they're all necessary as API docs don't elaborate on that | |
const TOKEN = 'my-api-token' | |
const PROJECTS = [ 'my-project-one', 'my-project-two' ] | |
// anything older than that will be removed | |
const DAYS = 180 // 6 months | |
;(async () => { | |
const sentry = new SentryClient({ | |
url: URL, | |
token: TOKEN, | |
org: ORG, | |
}) | |
const files = await sentry.getAllDebugFiles(PROJECTS) | |
const removals = files.filter(item => { | |
// ignore debug information files that are not old enough | |
return item.since >= DAYS | |
}).map(item => { | |
return sentry.deleteDebugFile({ project: item.project, id: item.id }) | |
}) | |
await Promise.all(removals) | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment