Last active
February 4, 2026 21:28
-
-
Save phpwalter/2ce7e735a879a0c843d676ef65a72725 to your computer and use it in GitHub Desktop.
Import Github Labels
This file contains hidden or 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
| /* | |
| Before running: | |
| 1. Go to your GitHub Settings > Developer Settings > Personal Access Tokens (classic). | |
| [https://github.com/settings/tokens] | |
| 2. GENERATE NEW TOKEN -> GENERATE NEW TOKEN [not classic!] | |
| 3. name it "labels" | |
| 4. Experation: tommorow | |
| 5. Select ONLY SELECT REPOSITORIES: your target repository | |
| 6. + ADD PERMISSIONS | |
| 7. Select ISSUES | |
| NOTE: | |
| For a token to be granted "Read and write" access to Issues | |
| 8. ACCESS: Read and Write | |
| 9. GENERATE TOKEN | |
| 10. Review your settings -> GENERATE TOKENS | |
| 11. Copy token | |
| 12. Paste that token into the YOUR_TOKEN_HERE. | |
| 13. go to your ISSUES page | |
| [yourname/your_project/issues/] | |
| 14. Open the browser CONSOLE | |
| 15. paste the modified script | |
| 16. run script and select JSON file | |
| 17. verify it placed issues as expected | |
| Use the sample JSON file to see how this works, than modify the JSON | |
| to add your own issues, desc, etc. | |
| NOTE: | |
| - All fields are required | |
| - DESC must be less than 100 characters | |
| */ |
This file contains hidden or 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
| // 1. CONFIGURATION | |
| const CONFIG = { | |
| token: "YOUR_ACCESS_TOKEN_HERE", | |
| owner: "USERNAME_OR_ORG", | |
| repo: "REPOSITORY_NAME" | |
| }; | |
| // 2. MAIN LOGIC | |
| async function startImport() { | |
| const input = document.createElement('input'); | |
| input.type = 'file'; | |
| input.accept = '.json'; | |
| input.onchange = (e) => { | |
| const file = e.target.files[0]; | |
| if (!file) return; | |
| const reader = new FileReader(); | |
| reader.onload = async (event) => { | |
| try { | |
| const json = JSON.parse(event.target.result); | |
| console.log(`π Loaded ${json.length} labels. Starting strict import...`); | |
| await importToGitHub(json); | |
| } catch (err) { | |
| console.error("β Invalid JSON:", err.message); | |
| } | |
| }; | |
| reader.readAsText(file); | |
| }; | |
| input.click(); | |
| } | |
| async function importToGitHub(labels) { | |
| const headers = { | |
| "Authorization": `token ${CONFIG.token}`, | |
| "Accept": "application/vnd.github.v3+json", | |
| "Content-Type": "application/json" | |
| }; | |
| let created = 0, skipped = 0, errors = 0; | |
| for (const [i, item] of labels.entries()) { | |
| // --- STRICT LENGTH CHECK --- | |
| const desc = item.description || ""; | |
| if (desc.length > 99) { | |
| console.error(`β SKIPPED [${i+1}] "${item.label}": Description too long (${desc.length} chars > 99)`); | |
| errors++; | |
| continue; // Skip to next iteration immediately | |
| } | |
| // Prepare Payload | |
| const payload = { | |
| name: item.label, | |
| description: desc, | |
| color: item.color.replace("#", "") | |
| }; | |
| try { | |
| const res = await fetch(`https://api.github.com/repos/${CONFIG.owner}/${CONFIG.repo}/labels`, { | |
| method: "POST", | |
| headers, | |
| body: JSON.stringify(payload) | |
| }); | |
| if (res.status === 201) { | |
| console.log(`β [${i+1}] Created: "${payload.name}"`); | |
| created++; | |
| } | |
| else if (res.status === 422) { | |
| // We still check for duplicates here just in case | |
| const data = await res.json().catch(() => ({})); | |
| if (data.errors?.[0]?.code === 'already_exists') { | |
| console.warn(`β οΈ [${i+1}] Skipped (Exists): "${payload.name}"`); | |
| skipped++; | |
| } else { | |
| console.error(`β [${i+1}] API Error: "${payload.name}"`, data); | |
| errors++; | |
| } | |
| } | |
| else { | |
| console.error(`β [${i+1}] Failed: "${payload.name}" (${res.status})`); | |
| errors++; | |
| } | |
| } catch (err) { | |
| console.error(`β Network Error on "${payload.name}"`, err); | |
| errors++; | |
| } | |
| // Safety Delay (500ms) | |
| await new Promise(r => setTimeout(r, 500)); | |
| } | |
| console.log(`\nπ IMPORT COMPLETE\nβ Created: ${created}\nβ οΈ Skipped (Exists): ${skipped}\nβ Skipped (Errors/Long): ${errors}`); | |
| } | |
| // 3. RUN | |
| startImport(); |
This file contains hidden or 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
| [ | |
| { | |
| "label": "prio:high", | |
| "description": "Critical path item; must be completed for milestone sign-off.", | |
| "color": "#B60205" | |
| }, | |
| { | |
| "label": "prio:low", | |
| "description": "Nice to have, but not a BLOCKER", | |
| "color": "#1DC036" | |
| }, | |
| { | |
| "label": "prio:medium", | |
| "description": "", | |
| "color": "#F0A795" | |
| }] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment