release-manager
Create and manage release PRs against master branch. Use this when preparing releases, bumping versions, resolving merge conflicts, and publishing GitHub releases. Handles the full release workflow including merging release into master, version bumping in pyproject.toml, running uv lock, and creating GitHub releases.
What this skill does
# Release Manager Skill
Manages the full release workflow for Django4Lyfe backend releases to production.
## When to Use This Skill
- Creating release PRs against master branch
- Preparing hotfix releases
- Bumping versions in pyproject.toml
- Resolving merge conflicts between release and master
- Publishing GitHub releases after PRs are merged
- Checking what commits are on release but not on master
## Core Workflow
### 1. Check What Needs Releasing
```bash
git fetch origin master release
# PRIMARY CHECK — are there actual code differences between the branches?
git diff --stat origin/master origin/release
```
`git diff --stat` compares the actual tree state (file contents), not commit
history. It is the only reliable way to determine whether there is something to
release. If the output is empty, there is nothing to release — stop here.
If there ARE differences, identify which PRs they belong to. Use GitHub's PR
metadata (merge timestamps), not git commit ancestry:
```bash
# Get the merge date of the last release PR (the definitive cutoff).
# The release PR's merge to master is the exact moment `git merge origin/release`
# captured the release branch state. Anything merged to release BEFORE that
# moment was included; anything AFTER is genuinely new.
LAST_RELEASE_DATE=$(gh pr list --base master --state merged --limit 100 \
--json number,title,mergedAt \
--jq '[.[] | select(.title | test("^(Release|Hotfix)"))] | sort_by(.mergedAt) | last | .mergedAt // empty' \
2>/dev/null || echo "")
# List PRs merged to release since that date
if [ -n "${LAST_RELEASE_DATE}" ]; then
gh pr list --base release --state merged --limit 100 --json number,title,mergedAt \
--jq "[.[] | select(.mergedAt > \"${LAST_RELEASE_DATE}\")] | sort_by(.mergedAt) | .[] | \"#\\(.number): \\(.title)\""
else
# No previous release — list recent merged PRs as candidates
gh pr list --base release --state merged --limit 20 --json number,title \
--jq '.[] | "#\(.number): \(.title)"'
fi
```
**Why the release PR's `mergedAt` instead of `publishedAt`?** GitHub release
`publishedAt` is when a human clicks "Publish" — which can be minutes or hours
after the release PR actually merges. PRs merged to release in that gap would
be missed on the next check. The release PR's `mergedAt` is the definitive
cutoff because `git merge origin/release` captures the exact state of the
release branch at that moment.
**Why GitHub metadata instead of `git log`?** All `git log`-based approaches
(`master..release`, `--cherry-pick`, `--first-parent` with tags) can return
stale results due to historical cherry-pick artifacts and because release tags
live on master's ancestry, not release's first-parent chain. PR merge
timestamps from GitHub are immune to git ancestry issues.
### 2. Create Release PR (Merge Method)
Merge the release branch into a branch from master. This preserves commit
ancestry so that `git log master..release` works correctly after the PR merges.
```bash
# 1. Create branch from master
git checkout -b releases/YYYY.MM.DD[-N] origin/master
# 2. Merge release into it
git merge origin/release --no-edit
# 3. Bump version in pyproject.toml
# Format: YYYY.MM.DD for first release, YYYY.MM.DD-N for subsequent releases
# 4. Update lock file
uv lock
# 5. Commit version bump
git add pyproject.toml uv.lock
git commit -m "Version bump to YYYY.MM.DD[-N]"
# 6. Push and create PR
git push -u origin releases/YYYY.MM.DD[-N]
gh pr create --base master --title "Release: DDth Month YYYY" --body "..."
```
**Why merge instead of cherry-pick?** Cherry-picking creates new commits with
different SHAs. Even with merge-back, `git log master..release` permanently
shows the original commits as "pending" because git compares SHAs, not patches.
Merging preserves the original commit objects so master and release share the
same ancestry. After the release PR merges to master, `git log master..release`
correctly shows only genuinely new commits.
### 3. Version Numbering Convention
| Scenario | Version Format | Example |
|----------|---------------|---------|
| First release of day | `YYYY.MM.DD` | `2026.01.21` |
| Second release | `YYYY.MM.DD-2` | `2026.01.21-2` |
| Third release | `YYYY.MM.DD-3` | `2026.01.21-3` |
| Hotfix release | `YYYY.MM.DD` or `YYYY.MM.DD-N` | `2026.01.21` |
### 4. PR Title and Body Format
**Title patterns:**
- Regular release: `Release: 21st January 2026`
- Multiple same-day: `Release 2: 21st January 2026`
- Hotfix: `Hotfix Release: 21st January 2026`
**Body format:**
```markdown
- https://github.com/DiversioTeam/Django4Lyfe/pull/XXXX
- https://github.com/DiversioTeam/Django4Lyfe/pull/YYYY
```
### 5. Resolve Conflicts (If Any)
If the merge has conflicts:
```bash
# 1. Edit conflicted files to keep correct changes
# 2. For uv.lock conflicts, regenerate:
git checkout --theirs uv.lock
uv lock
# 3. Stage resolved files
git add <resolved-files>
# 4. Complete merge
git commit -m "Merge origin/release into releases/YYYY.MM.DD"
```
### 6. Publish GitHub Release
After PR is merged to master, create a GitHub release.
**IMPORTANT: Merge Strategy** — Release PRs to master MUST be merged using
**"Create a merge commit"** (not squash). Squash merging breaks commit ancestry
and causes `master..release` to grow unboundedly. If GitHub is configured to
allow multiple merge strategies, always select "Create a merge commit" for
release PRs.
#### Step 1: Verify PR is merged
```bash
gh pr view <PR_NUMBER> --json state,mergeCommit,mergedAt
# Should show: "state": "MERGED"
```
#### Step 2: Check recent releases for format consistency
```bash
gh release list --limit 5
```
#### Step 3: Get PR details for release notes
```bash
# Get the PR body which contains the list of included PRs
gh pr view <PR_NUMBER> --json body,title
```
#### Step 4: Create the GitHub release
```bash
gh release create YYYY.MM.DD[-N] \
--title "Release Title" \
--notes "$(cat <<'EOF'
- https://github.com/DiversioTeam/Django4Lyfe/pull/XXXX
- https://github.com/DiversioTeam/Django4Lyfe/pull/YYYY
EOF
)" \
--target master
```
#### GitHub Release Title Patterns
| Release Type | Tag | Title |
|--------------|-----|-------|
| First of day | `2026.01.21` | `January 21st 2026` |
| Second release | `2026.01.21-2` | `Release 2: January 21st 2026` |
| Third release | `2026.01.21-3` | `Release 3: January 21st 2026` |
| Hotfix | `2026.01.21` | `Hotfix Release: January 21st 2026` |
#### Step 5: Verify release was created
```bash
gh release list --limit 3
# Or view specific release:
gh release view YYYY.MM.DD[-N]
```
#### Complete Example
```bash
# 1. Check PR is merged
gh pr view 2608 --json state,mergeCommit,mergedAt
# 2. Create release (using heredoc for multi-line notes)
gh release create 2026.01.21 \
--title "January 21st 2026" \
--notes "$(cat <<'EOF'
- https://github.com/DiversioTeam/Django4Lyfe/pull/2607
EOF
)" \
--target master
# 3. Verify
gh release list --limit 3
```
### 7. Merge Master Back Into Release
**This step is mandatory after every release PR merge.** It keeps the branches
in sync so that `git diff --stat origin/master origin/release` is clean and
future releases start from a consistent baseline.
```bash
git fetch origin
git checkout release
git merge origin/master --no-edit
git push origin release
```
**Why this matters**: After a release PR merges into master, master has a merge
commit and a version-bump commit that release doesn't. Without merge-back,
`git diff --stat origin/master origin/release` shows the version bump as a
pending difference, and the next `git merge origin/release` will conflict on
`pyproject.toml` / `uv.lock`. The merge-back keeps both branches aligned.
## Pre-Release Checks
Before creating a release PR, verify:
1. **Ruff formatting passes:**
```bash
./.security/ruff_pr_diff.sh
```
If it fails, fix with:
```bash
.bin/ruff format <file>
```
2. **Active Python type gate passes (strict):**
- Detect in this order unless repo docs/Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.