Skip to content

Instantly share code, notes, and snippets.

@mauritsvanrees
Created May 11, 2026 15:02
Show Gist options
  • Select an option

  • Save mauritsvanrees/885826601786c14ac26b402432fa0aa5 to your computer and use it in GitHub Desktop.

Select an option

Save mauritsvanrees/885826601786c14ac26b402432fa0aa5 to your computer and use it in GitHub Desktop.
Script to add and check standard branch/tag rulesets on GitHub
#!/bin/sh
# You need to have the 'gh' command installed (GitHub CLI).
# And 'repos.txt' should have a list of repos to add the rulesets to.
# The script assumes the collective organisation:
# https://github.com/collective
for repo in $(cat repos.txt); do
echo ""
echo ""
echo "Handling ${repo}"
current=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
/repos/collective/${repo}/rulesets)
if test "${current}" != "[]"; then
echo "${repo} already has rulesets"
continue
fi
echo "${repo} has no rulesets"
echo "Adding branch protect ruleset to ${repo}"
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
/repos/collective/${repo}/rulesets \
--input - <<< '{
"name": "branch protect",
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"~DEFAULT_BRANCH",
"refs/heads/[0-9]*.x"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
}
]
}'
echo "Adding tag protect ruleset to ${repo}"
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2026-03-10" \
/repos/collective/${repo}/rulesets \
--input - <<< '{
"name": "tag protect",
"target": "tag",
"enforcement": "active",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"~ALL"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "update"
}
]
}'
echo "Done with ${repo}"
sleep 1
done
collective-referencecontent
collective-searchblocks
collective.address
collective.ajaxify
collective.anotherdynamicgroupsplugin
collective.auditlog
collective.beaker
collective.behavior.talcondition
collective.big.bang
collective.catalogtrace
collective.checklist
collective.ckeditor
collective.ckeditortemplates
collective.classschedule
collective.click_to_zoom
collective.collectionepilog
collective.collectionfilter
collective.contact.core
collective.contact.plonegroup
collective.contactformprotection
collective.contentrules.setfield
collective.contentsections
collective.cron
collective.customizedstaticresources
collective.datatablesviews
collective.datepickerpattern
collective.deletepermission
collective.dms.basecontent
collective.dms.batchimport
collective.dms.mailcontent
collective.dms.scanbehavior
collective.documentgenerator
collective.eeafaceted.collectionwidget
collective.eeafaceted.dashboard
collective.eeafaceted.z3ctable
collective.excelexport
collective.exportimport.examples
collective.externalimageeditor
collective.externallinkfilter
collective.faq
collective.formsupport.counter
collective.ftw.tokenauth
collective.ftw.upgrade
collective.ftwslacker
collective.generic.devmode
collective.generic.skel
collective.generic.webbuilder
collective.geolocationbehavior
collective.gridlisting
collective.html2blocks
collective.iconifiedcategory
collective.imagemaps
collective.immediatecreate
collective.impersonate
collective.js.backbone
collective.js.chosen
collective.js.datatables
collective.js.tooltipster
collective.js.underscore
collective.jsconfiguration
collective.keycdn
collective.labels
collective.ldapsetup
collective.localstyles
collective.markdownplus
collective.mockmailhost
collective.pdbpp
collective.portlet.embed
collective.portlet.relateditems
collective.pwexpiry
collective.querynextprev
collective.quickupload
collective.recipe.omelette
collective.restapi.easyform
collective.revisionmanager
collective.richdescription
collective.sendinblue
collective.sidebar
collective.sitter
collective.solr
collective.splitsitemap
collective.tiles.advancedstatic
collective.tiles.carousel
collective.timestamp
collective.translators
collective.transmute
collective.vectorsearch
collective.venue
collective.volto.contactsblock
collective.volto.dropdownmenu
collective.volto.footer
collective.volto.formsupport
collective.volto.gdprcookie
collective.volto.otp
collective.volto.secondarymenu
collective.volto.sections
collective.volto.slimheader
collective.volto.subfooter
collective.webhook
collective.wfadaptations
collective.workspace
collective.xkey
collective.z3cform.captionedrelationfield
collective.z3cform.chosen
collective.z3cform.datagridfield
collective.z3cform.jsonwidget
collective.z3cform.select2
dexterity.localroles
dexterity.localrolesfield
experimental.gracefulblobmissing
fortytwo
i18ndude
iw.rejectanonymous
keycloak-and-plone
lineage.controlpanels
lineage.themeselection
mr.scripty
mrs-developer
pas.plugins.eea
pas.plugins.headers
pas.plugins.tfa
plone_clean_history
plone.app.locales
plone6-autologin-extension
ploneconf.site
plonex
Products.csvreplicata
Products.DateRecurringIndex
Products.LoginLockout
Products.PasswordStrength
Products.PDBDebugMode
Products.PrintingMailHost
Products.RefBiblioParser
pyf-gui
pyf.aggregator
pytest-jsonschema
robotsuite
rss-provider
seven-training-addon
tech-event
training_buildout
tui-forms
volto-blocks-widget
volto-contents-next
volto-csp
volto-dropdownmenu
volto-footer
volto-form-block
volto-form-counter
volto-gdpr-privacy
volto-google-analytics
volto-hideshow-blocks
volto-image-editor
volto-middleware-binary
volto-multilingual-widget
volto-rss-receiver
volto-secondarymenu
volto-slimheader
volto-social-settings
volto-speakerdeck
volto-subfooter
volto-venue
zestreleaser.towncrier
zpretty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment