Lab: Repository protections, permissions, and tags
Outcome
Enforce the same protected-main workflow in a disposable GitHub repository and Azure Repos repository, prove blocked direct/PR completion, grant a least-privilege contributor role, and create an annotated release tag under controlled tag rules.
Do
- Create two disposable repositories with
main, a feature branch, a small passing CI check, and a test contributor identity/group. - In GitHub, create a branch ruleset for
main: require a pull request, approval, and the named status check; block force pushes; configure bypass only for the designated emergency role. Create a tag ruleset that restricts creation ofv*tags. In Azure Repos, configure equivalentmainpolicies (minimum reviewers and build/status validation) and branch permissions. Keep Bypass policies when completing PRs separate from Bypass policies when pushing; deny direct-push bypass unless the scenario explicitly requires it. - Push directly to
mainand try to complete an unapproved/failed PR in each platform. Record the blocked condition. Satisfy the review/check, complete the PR, and record the merge evidence. - Grant the test identity only the needed repository contribution/PR role; verify clone/feature-branch/PR succeeds while policy editing, force push, or protected-branch push is denied. Remove the role afterward.
- Create
git tag -a v0.1.0 -m "training release", push it, and inspect the tag target from both remote platforms. Attempt unauthorizedv0.1.1creation, correct the tag rule or use the approved release identity, and avoid moving a published release tag.
Verify
Capture both policy/ruleset configurations, direct-push and PR block messages, successful checked merge, effective test-user permissions, annotated tag object/target, and tag rule result. You should now understand: repository permissions control who can act; branch policy/rulesets control which changes may enter a ref; a tag is a release reference, not a branch policy.
Break and fix
- Make the required status check unavailable; diagnose its exact name, trigger, and PR target, then restore it.
- Grant bypass too broadly; inspect scope and split PR-completion bypass from push bypass in Azure Repos or narrow the GitHub ruleset actor.
- Let the test identity create a restricted tag; correct the tag restriction and verify denial.
Scenario practice
- Configure: Select review, status, force-push, bypass, permission, and tag controls for a regulated release branch.
- Diagnose: A PR is blocked although its author has write access. Inspect target policy, review, status, merge strategy, and bypass permission.
- Distinguish: Contrast GitHub ruleset/branch protection with Azure Repos policy, repository role with branch permission, and annotated tag with release branch.
Clean up
Delete test branches/PRs/tags and remove test identities, rulesets, policies, and repositories. Preserve no bypass role after the exercise.
Sources and re-audit
- GitHub ruleset rules, checked 2026-08-22.
- Azure Repos branch policies, checked 2026-08-22.
- Azure Repos permissions, checked 2026-08-22.
Re-audit when platform policy, permission, ruleset, or tag behavior changes.
Related
branch-protection · pull-request · azure-devops-security-groups · semantic-versioning · All labs