|
/** |
|
* run: GITHUB_TOKEN=<replace with yours> GITHUB_REPOSITORY=<owner>/<repo> TAG_PREFIX=<tag prefix> node delete-github-tags-with-prefix.js |
|
* |
|
* GITHUB_TOKEN: github secret token with access **repo** |
|
* GITHUB_REPOSITORY: repo name in the form of <owner>/<repoName> |
|
* TAG_PREFIX: prefix of tags that need to be deleted. refer: https://developer.github.com/v3/git/refs/#list-matching-references |
|
*/ |
|
|
|
const https = require("https"); |
|
|
|
if (!process.env.GITHUB_TOKEN) { |
|
console.error("π΄ no GITHUB_TOKEN found. pass `GITHUB_TOKEN` as env"); |
|
process.exitCode = 1; |
|
return; |
|
} |
|
const GITHUB_TOKEN = process.env.GITHUB_TOKEN; |
|
|
|
if (!process.env.GITHUB_REPOSITORY) { |
|
console.error( |
|
"π΄ no GITHUB_REPOSITORY found. pass `GITHUB_REPOSITORY` as env" |
|
); |
|
process.exitCode = 1; |
|
return; |
|
} |
|
|
|
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/"); |
|
|
|
if (!owner || !repo) { |
|
console.error("β οΈ either owner or repo name is empty. exiting..."); |
|
process.exitCode = 1; |
|
return; |
|
} |
|
|
|
if (!process.env.TAG_PREFIX) { |
|
console.error("π TAG_PREFIX is mandatory"); |
|
process.exitCode = 1; |
|
return; |
|
} |
|
const tagPrefix = process.env.TAG_PREFIX; |
|
|
|
function fetch(options, data) { |
|
return new Promise(function (resolve, reject) { |
|
const req = https.request(options, function (res) { |
|
let data = ""; |
|
res.on("data", function (chunk) { |
|
data += chunk; |
|
}); |
|
|
|
res.on("end", function () { |
|
let body = undefined; |
|
try { |
|
body = data ? JSON.parse(data) : undefined; |
|
} catch (e) { |
|
return reject(e); |
|
} |
|
|
|
if (res.statusCode < 200 || res.statusCode >= 300) { |
|
return reject(body ? new Error(body.message) : res.statusMessage); |
|
} |
|
|
|
return resolve(body); |
|
}); |
|
}); |
|
|
|
req.on("error", function (err) { |
|
reject(err); |
|
}); |
|
|
|
if (data) { |
|
req.write(data); |
|
} |
|
req.end(); |
|
}); |
|
} |
|
|
|
const commonOpts = { |
|
host: "api.github.com", |
|
port: 443, |
|
protocol: "https:", |
|
auth: `user:${GITHUB_TOKEN}`, |
|
headers: { |
|
"Content-Type": "application/json", |
|
"User-Agent": "node.js", |
|
}, |
|
}; |
|
|
|
async function deleteTags(pattern) { |
|
let tagRefs = []; |
|
try { |
|
let data = await fetch({ |
|
...commonOpts, |
|
path: `/repos/${owner}/${repo}/git/matching-refs/tags/${pattern}`, |
|
method: "GET", |
|
}); |
|
data = data || []; |
|
console.log(`π¬ found total of ${data.length} tag ref(s)`); |
|
tagRefs = data.map(({ ref }) => ref); |
|
} catch (error) { |
|
console.error(`πΆ failed to get list of releases <- ${error.message}`); |
|
console.error(`exiting...`); |
|
process.exitCode = 1; |
|
return; |
|
} |
|
|
|
if (tagRefs.length === 0) { |
|
console.log(`π no tags found with prefix ${pattern}`); |
|
return; |
|
} |
|
|
|
console.log( |
|
`βΉοΈ tags that are going to be deleted are: ${tagRefs |
|
.map((r) => r.replace("refs/tags/", "")) |
|
.join(", ")}` |
|
); |
|
|
|
for (let i = 0; i < tagRefs.length; i++) { |
|
const tagRef = tagRefs[i]; |
|
try { |
|
const _ = await fetch({ |
|
...commonOpts, |
|
path: `/repos/${owner}/${repo}/git/${tagRef}`, |
|
method: "DELETE", |
|
}); |
|
console.log( |
|
`β
π '${tagRef.replace("refs/tags/", "")}' deleted successfully` |
|
); |
|
} catch (error) { |
|
console.error(`πΆ failed to delete ref "${tagRef}" <- ${error.message}`); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
(function main() { |
|
deleteTags(tagPrefix); |
|
})(); |
How to push deleted tags to remote ? https://devconnected.com/how-to-delete-local-and-remote-tags-on-git/