Skip to content

Instantly share code, notes, and snippets.

@mikenikles
Last active January 24, 2024 20:39
Show Gist options
  • Save mikenikles/d9947dceeb2e6c7a0d1b71c85cae3fd5 to your computer and use it in GitHub Desktop.
Save mikenikles/d9947dceeb2e6c7a0d1b71c85cae3fd5 to your computer and use it in GitHub Desktop.
Scripts to export GitHub issue labels from one repository and import them to another repository.
/**
* The array of issues is copied to your clipboard. Paste it somewhere before you copy the `github-labels-import.js` file content.
*
* Run this script on the https://github.com/OWNER/REPO/labels page.
*/
const convertRgbaToHex = (rgba) => {
// Match the values in the parentheses
const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)/);
if (!match) return;
// Extract the red, green, and blue values from the match
let [, r, g, b] = match.map(Number);
// Convert the values to hexadecimals and return the result
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
};
const collectLabels = () => {
const labelList = document.querySelector(".js-label-list");
const labelRows = [...labelList.children];
const labels = labelRows.map(labelRow => {
const labelRowColumns = [...labelRow.children];
// console.log(labelRow)
const name = labelRowColumns.at(0).querySelector("span").textContent;
const color = convertRgbaToHex(window.getComputedStyle(labelRowColumns.at(0).querySelector("a")).backgroundColor);
const description = labelRowColumns.at(1).querySelector("span").textContent;
return {
name,
color,
description,
};
});
return labels;
};
copy(collectLabels());
/**
* CAUTION: This deletes all existing labels.
*
* Run this script on the https://github.com/OWNER/REPO/labels page.
*/
// Deleting a label shows a confirmation dialog. We silence that temporarily.
const originalConfirm = window.confirm;
window.confirm = () => true;
const sleep = ms => new Promise(r => setTimeout(r, ms));
const deleteAllExistingLabels = async () => {
const labelList = document.querySelector(".js-label-list");
const labelRows = [...labelList.children];
for (let labelRow of labelRows) {
const labelRowColumns = [...labelRow.children];
const editAndDeleteColumn = labelRowColumns.at(3);
const deleteForm = editAndDeleteColumn.querySelector("form.js-delete-label");
deleteForm.querySelector("button").click();
await sleep(1500);
}
window.confirm = originalConfirm;
};
const importLabels = async () => {
const labelsToImportString = window.prompt("Paste your labels array.");
const labelsToImport = JSON.parse(labelsToImportString).reverse();
for (let label of labelsToImport) {
document.querySelector( '.js-new-label-name-input' ).value = label.name;
document.querySelector( '.js-new-label-description-input' ).value = label.description;
document.querySelector( '.js-new-label-color-input' ).value = label.color;
document.querySelector( '.js-details-target ~ .btn-primary' ).disabled = false;
document.querySelector( '.js-details-target ~ .btn-primary' ).click();
await sleep(1500);
}
};
deleteAllExistingLabels()
.then(importLabels)
.then(() => { console.log("All labels imported."); });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment