Skip to content

Commit 369721a

Browse files
committed
Merge #449: docs/ci: [#448] define release process and add release automation workflows
649a682 docs: [#448] update issue spec with completed tasks and fix step order (Jose Celano) fc87174 docs: [#448] add open-pull-request skill guidance (Jose Celano) 5b038bd docs: [#448] add release-new-version agent skill (Jose Celano) 0c99abf docs: [#448] add publish crate workflow badge (Jose Celano) 231db3f ci: [#448] fix docs.rs spelling in crate workflow (Jose Celano) abeae8c chore: [#448] add SDK crate repository metadata (Jose Celano) 2249927 ci: [#448] add SDK crate release workflow (Jose Celano) 0d93e58 ci: [#448] simplify container publish jobs by branch type (Jose Celano) 8340801 docs: [#448] add release process documentation (Jose Celano) Pull request description: ## Summary - add release operational guide in docs/release-process.md - extend and simplify container workflow to publish from main/develop/release branches - add dedicated crate release workflow for SDK crate on releases/vX.Y.Z - enforce SDK crate release metadata and add publish-crate badge in README - add release-new-version skill for agent workflow guidance ## Included changes - docs/release-process.md (new) - .github/workflows/container.yaml (updated) - .github/workflows/publish-crate.yaml (new) - packages/sdk/Cargo.toml (metadata for publish readiness) - README.md (new workflow badge) - .github/skills/dev/git-workflow/release-new-version/skill.md (new) - AGENTS.md (skill registration) Closes #448 ACKs for top commit: josecelano: ACK 649a682 Tree-SHA512: 6eec5e95cc9b3d7d596cffb45ad72342a859c04df7ba1063d86352b3443dc8e6cdc94e829c0b328d3e1ceda8ca21ec9d565a3ff1a421010640c7e8c147d113ca
2 parents 8c6e1d0 + 649a682 commit 369721a

10 files changed

Lines changed: 725 additions & 108 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
name: open-pull-request
3+
description: Open a pull request from a feature branch using GitHub CLI (preferred) or GitHub MCP tools. Covers pre-flight checks, correct base/head configuration for fork workflows, title/body conventions, and post-creation validation. Use when asked to "open PR", "create pull request", or "submit branch for review".
4+
metadata:
5+
author: torrust
6+
version: "1.0"
7+
---
8+
9+
# Open a Pull Request
10+
11+
This skill explains how to create a pull request for this repository in a repeatable way.
12+
13+
## CLI vs MCP decision rule
14+
15+
Use the tool that matches the loop:
16+
17+
- **Inner loop (fast local branch work):** prefer GitHub CLI (`gh`) because it is fast and low overhead.
18+
- **Outer loop (cross-system coordination):** use MCP when you need structured/authenticated access across shared systems.
19+
20+
For opening a PR from the current local branch, prefer `gh pr create`.
21+
22+
## Pre-flight checks
23+
24+
Before opening a PR:
25+
26+
- [ ] Working tree is clean (`git status`)
27+
- [ ] Branch is pushed to remote
28+
- [ ] Commits are signed (`git log --show-signature -n 1`)
29+
- [ ] Required checks have been run (`./scripts/pre-commit.sh`)
30+
31+
## Title and description convention
32+
33+
Use conventional commit style in the PR title when possible, including issue reference.
34+
35+
Examples:
36+
37+
- `ci: [#448] add crate publish workflow`
38+
- `docs: [#448] define release process`
39+
40+
Include in PR body:
41+
42+
- Summary of changes
43+
- Files/workflows touched
44+
- Validation performed
45+
- Issue link (`Closes #<issue-number>`)
46+
47+
## Option A (Preferred): GitHub CLI
48+
49+
### Same-repo branch
50+
51+
```bash
52+
gh pr create \
53+
--repo torrust/torrust-tracker-deployer \
54+
--base main \
55+
--head <branch-name> \
56+
--title "<title>" \
57+
--body "<body>"
58+
```
59+
60+
### Fork branch (common maintainer flow)
61+
62+
```bash
63+
gh pr create \
64+
--repo torrust/torrust-tracker-deployer \
65+
--base main \
66+
--head <fork-owner>:<branch-name> \
67+
--title "<title>" \
68+
--body "<body>"
69+
```
70+
71+
If successful, `gh` prints the PR URL.
72+
73+
## Option B: GitHub MCP tools
74+
75+
When MCP pull request management tools are available:
76+
77+
1. Create branch remotely if needed
78+
2. Open PR with base `main` and correct head branch
79+
3. Capture and share resulting PR URL
80+
81+
## Post-creation validation
82+
83+
After PR creation:
84+
85+
- [ ] Verify PR points to `torrust/torrust-tracker-deployer:main`
86+
- [ ] Verify head branch is correct
87+
- [ ] Confirm CI workflows started
88+
- [ ] Confirm issue is linked in description
89+
90+
## Troubleshooting
91+
92+
- `fatal: ... does not appear to be a git repository`: push to correct remote (`git remote -v`)
93+
- `A pull request already exists`: open existing PR URL instead of creating a new one
94+
- Permission errors on upstream repo: create PR from your fork branch (`owner:branch`)
95+
96+
## References
97+
98+
- [`docs/contributing/commit-process.md`](../../../../../docs/contributing/commit-process.md)
99+
- [`docs/contributing/pr-review-guide.md`](../../../../../docs/contributing/pr-review-guide.md)
100+
- Existing branch skill: `.github/skills/dev/git-workflow/create-feature-branch/skill.md`
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
name: release-new-version
3+
description: Guide for releasing a new version of the deployer using the standard branch/tag workflow. Covers version bump, signed release commit, pushing main, creating signed tag, creating release branch, and verifying Docker + crate publication workflows. Use when asked to "release", "cut a version", "publish a new version", or "create release vX.Y.Z".
4+
metadata:
5+
author: torrust
6+
version: "1.0"
7+
---
8+
9+
# Release New Version
10+
11+
This skill provides the canonical workflow to release a new version of the Torrust Tracker Deployer.
12+
13+
Primary reference: [`docs/release-process.md`](../../../../../docs/release-process.md)
14+
15+
## Release Order (Mandatory)
16+
17+
Execute these steps in order:
18+
19+
1. Update versions in manifests
20+
2. Create release commit
21+
3. Push release commit to `main`
22+
4. Create and push signed tag `vX.Y.Z`
23+
5. Create and push release branch `releases/vX.Y.Z`
24+
6. Verify release workflows
25+
7. Create GitHub release
26+
27+
Do not reorder these steps.
28+
29+
## Version and Naming Rules
30+
31+
- Git tag: `vX.Y.Z`
32+
- Release branch: `releases/vX.Y.Z`
33+
- Docker release tag: `X.Y.Z` (no `v` prefix)
34+
- Crate version: `X.Y.Z`
35+
36+
## Pre-Flight Checklist
37+
38+
Before starting:
39+
40+
- [ ] Clean working tree (`git status`)
41+
- [ ] Up to date with `origin/main`
42+
- [ ] GitHub environment `dockerhub-torrust` configured
43+
- [ ] GitHub environment `crates-io` configured with `CARGO_REGISTRY_TOKEN`
44+
- [ ] Releaser has permissions for `main`, tags, and release branches
45+
46+
## Commands
47+
48+
### 1) Update versions
49+
50+
Update `version` in:
51+
52+
- `Cargo.toml`
53+
- `packages/sdk/Cargo.toml`
54+
55+
### 2) Commit and push
56+
57+
```bash
58+
git add Cargo.toml packages/sdk/Cargo.toml
59+
git commit -S -m "release: version vX.Y.Z"
60+
git push origin main
61+
```
62+
63+
### 3) Tag and release branch
64+
65+
```bash
66+
git tag -s -a vX.Y.Z -m "Release vX.Y.Z"
67+
git push origin vX.Y.Z
68+
69+
git checkout -b releases/vX.Y.Z
70+
git push origin releases/vX.Y.Z
71+
```
72+
73+
### 4) Verify workflows
74+
75+
- Container workflow: publishes Docker image from release branch
76+
- Publish Crate workflow: publishes `torrust-tracker-deployer-sdk`
77+
78+
Workflow files:
79+
80+
- `.github/workflows/container.yaml`
81+
- `.github/workflows/publish-crate.yaml`
82+
83+
### 5) Create GitHub release
84+
85+
Create the release manually from tag `vX.Y.Z` after both workflows pass.
86+
87+
## Failure Handling
88+
89+
- Docker failed, crate not started: fix Docker workflow and rerun on same release branch
90+
- Docker passed, crate failed before upload: fix issue and rerun crate workflow on same release branch
91+
- Crate already published: do not republish same version; cut a patch release
92+
- Ref already exists (tag/branch): stop and investigate partial release state before continuing
93+
94+
## Quick Validation
95+
96+
```bash
97+
# Verify refs exist remotely
98+
git ls-remote --tags origin vX.Y.Z
99+
git ls-remote --heads origin releases/vX.Y.Z
100+
```
101+
102+
For full operational guidance, troubleshooting, and rollback/yank policy, use [`docs/release-process.md`](../../../../../docs/release-process.md).

.github/workflows/container.yaml

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
# Following patterns from torrust/torrust-tracker container.yaml workflow.
55
#
66
# Triggers:
7-
# - Push to main/develop branches
7+
# - Push to main/develop/releases/** branches
88
# - Pull requests to main/develop
99
# - Manual dispatch
1010
#
1111
# Publishing:
12-
# - Images are pushed to Docker Hub on push to main/develop (not PRs)
13-
# - Requires Docker Hub credentials in repository secrets
12+
# - Images are pushed to Docker Hub on push to main/develop/release branches (not PRs)
13+
# - Release branches (releases/vX.Y.Z) publish versioned Docker tags (X.Y.Z)
14+
# - Release Docker tags use bare semver without the v prefix
15+
# - Requires Docker Hub credentials in the dockerhub-torrust GitHub Environment
1416

1517
name: Container
1618

@@ -19,6 +21,7 @@ on:
1921
branches:
2022
- "develop"
2123
- "main"
24+
- "releases/**/*"
2225
paths:
2326
- "src/**"
2427
- "Cargo.toml"
@@ -100,6 +103,7 @@ jobs:
100103
outputs:
101104
continue: ${{ steps.check.outputs.continue }}
102105
type: ${{ steps.check.outputs.type }}
106+
version: ${{ steps.check.outputs.version }}
103107

104108
steps:
105109
- name: Check Context
@@ -108,10 +112,15 @@ jobs:
108112
if [[ "${{ github.repository }}" == "torrust/torrust-tracker-deployer" ]]; then
109113
if [[ "${{ github.event_name }}" == "push" ]]; then
110114
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
111-
echo "type=production" >> $GITHUB_OUTPUT
115+
echo "type=main" >> $GITHUB_OUTPUT
112116
echo "continue=true" >> $GITHUB_OUTPUT
113117
elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
114-
echo "type=development" >> $GITHUB_OUTPUT
118+
echo "type=develop" >> $GITHUB_OUTPUT
119+
echo "continue=true" >> $GITHUB_OUTPUT
120+
elif [[ $(echo "${{ github.ref }}" | grep -P '^refs/heads/releases/v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$') ]]; then
121+
version=$(echo "${{ github.ref }}" | sed -n -E 's/^refs\/heads\/releases\///p')
122+
echo "version=$version" >> $GITHUB_OUTPUT
123+
echo "type=release" >> $GITHUB_OUTPUT
115124
echo "continue=true" >> $GITHUB_OUTPUT
116125
fi
117126
fi
@@ -122,71 +131,54 @@ jobs:
122131
echo "continue=false" >> $GITHUB_OUTPUT
123132
fi
124133
125-
publish_development:
126-
name: Publish (Development)
134+
publish:
135+
name: Publish (${{ needs.context.outputs.type }})
127136
environment: dockerhub-torrust
128137
needs: context
129-
if: needs.context.outputs.continue == 'true' && needs.context.outputs.type == 'development'
138+
if: needs.context.outputs.continue == 'true'
130139
runs-on: ubuntu-latest
131140
timeout-minutes: 30
132141

133142
steps:
134143
- name: Checkout
135144
uses: actions/checkout@v5
136145

137-
- name: Docker Meta
138-
id: meta
139-
uses: docker/metadata-action@v5
140-
with:
141-
images: |
142-
${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer
143-
tags: |
144-
type=ref,event=branch
145-
type=sha,prefix=dev-
146-
147-
- name: Login to Docker Hub
148-
uses: docker/login-action@v3
149-
with:
150-
username: ${{ env.DOCKER_HUB_USERNAME }}
151-
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
152-
153-
- name: Setup Docker Buildx
154-
uses: docker/setup-buildx-action@v3
155-
156-
- name: Build and Push
157-
uses: docker/build-push-action@v6
158-
with:
159-
context: .
160-
file: ./docker/deployer/Dockerfile
161-
target: release
162-
push: true
163-
tags: ${{ steps.meta.outputs.tags }}
164-
labels: ${{ steps.meta.outputs.labels }}
165-
cache-from: type=gha
166-
cache-to: type=gha,mode=max
167-
168-
publish_production:
169-
name: Publish (Production)
170-
environment: dockerhub-torrust
171-
needs: context
172-
if: needs.context.outputs.continue == 'true' && needs.context.outputs.type == 'production'
173-
runs-on: ubuntu-latest
174-
timeout-minutes: 30
175-
176-
steps:
177-
- name: Checkout
178-
uses: actions/checkout@v5
146+
- name: Configure Docker Tag Strategy
147+
id: tag_config
148+
run: |
149+
if [[ "${{ needs.context.outputs.type }}" == "develop" ]]; then
150+
{
151+
echo "tags<<EOF"
152+
echo "type=ref,event=branch"
153+
echo "type=sha,prefix=dev-"
154+
echo "EOF"
155+
} >> "$GITHUB_OUTPUT"
156+
elif [[ "${{ needs.context.outputs.type }}" == "main" ]]; then
157+
{
158+
echo "tags<<EOF"
159+
echo "type=raw,value=latest"
160+
echo "type=ref,event=branch"
161+
echo "type=sha"
162+
echo "EOF"
163+
} >> "$GITHUB_OUTPUT"
164+
elif [[ "${{ needs.context.outputs.type }}" == "release" ]]; then
165+
{
166+
echo "tags<<EOF"
167+
echo "type=semver,value=${{ needs.context.outputs.version }},pattern={{version}}"
168+
echo "EOF"
169+
} >> "$GITHUB_OUTPUT"
170+
else
171+
echo "Unsupported publish type: ${{ needs.context.outputs.type }}" >&2
172+
exit 1
173+
fi
179174
180175
- name: Docker Meta
181176
id: meta
182177
uses: docker/metadata-action@v5
183178
with:
184179
images: |
185180
${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer
186-
tags: |
187-
type=raw,value=latest
188-
type=ref,event=branch
189-
type=sha
181+
tags: ${{ steps.tag_config.outputs.tags }}
190182

191183
- name: Login to Docker Hub
192184
uses: docker/login-action@v3
@@ -208,3 +200,10 @@ jobs:
208200
labels: ${{ steps.meta.outputs.labels }}
209201
cache-from: type=gha
210202
cache-to: type=gha,mode=max
203+
204+
- name: Inspect Published Image
205+
if: needs.context.outputs.type == 'release'
206+
run: |
207+
version=$(echo "${{ needs.context.outputs.version }}" | sed 's/^v//')
208+
docker pull ${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer:"$version"
209+
docker image inspect ${{ env.DOCKER_HUB_USERNAME }}/tracker-deployer:"$version"

0 commit comments

Comments
 (0)