3.3: Release Workflow Instructions
Release Workflow for AI Agents
Release Types in ASPICE
Release Categories:
- Development Releases: Internal testing (weekly/sprint)
- Release Candidates (RC): Pre-production validation (monthly)
- Production Releases: Customer delivery (quarterly, or as per contract)
- Hotfix Releases: Critical bug fixes (on-demand)
AI Agent Role: Generate release notes, compile artifacts (human approves and tags)
Semantic Versioning (SemVer)
Version Format: MAJOR.MINOR.PATCH
v1.2.3
│ │ └─ PATCH: Bug fixes (backward-compatible)
│ └─── MINOR: New features (backward-compatible)
└───── MAJOR: Breaking changes (not backward-compatible)
Examples:
v1.0.0: Initial releasev1.1.0: Added new feature (ACC speed control)v1.1.1: Fixed bug (CAN timeout issue)v2.0.0: Breaking change (AUTOSAR R4.3 → R4.4 migration)
Automotive Variants:
- ISO 26262 projects often add build number:
v1.2.3-build.456 - Safety-critical:
v1.2.3-ASIL-B
Release Preparation
1. Feature Freeze
Action: Stop merging new features, focus on bug fixes
Timeline:
Sprint N: Feature development
↓
Sprint N+1 Week 1-2: Feature freeze, bug fixes only
↓
Sprint N+1 Week 3: Release candidate (RC1)
↓
Sprint N+1 Week 4: Production release (v1.2.0)
Branch Strategy:
main
├─ feature/ASPICE-1234 (merged before freeze)
├─ feature/ASPICE-1235 (merged before freeze)
└─ release/v1.2.0 (created at freeze)
├─ fix/critical-bug-1 (cherry-picked from main)
└─ fix/critical-bug-2 (cherry-picked from main)
2. Generate Release Notes (AI Task)
Action: Compile changes since last release
Automated Release Notes Generation (Python):
import subprocess
import re
from collections import defaultdict
def generate_release_notes(previous_tag, new_version):
"""
Generate release notes from git commits
"""
# Get commits since last release
cmd = f"git log {previous_tag}..HEAD --pretty=format:'%h|%s|%an|%ad' --date=short"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
commits = result.stdout.strip().split('\n')
# Categorize commits by type
categories = defaultdict(list)
for commit in commits:
hash, message, author, date = commit.split('|')
# Parse conventional commit
match = re.match(r'(\w+)(\([\w-]+\))?: (.+)', message)
if match:
commit_type = match.group(1)
scope = match.group(2)[1:-1] if match.group(2) else ''
description = match.group(3)
# Map commit type to category
if commit_type == 'feat':
categories['Features'].append((hash, scope, description))
elif commit_type == 'fix':
categories['Bug Fixes'].append((hash, scope, description))
elif commit_type == 'docs':
categories['Documentation'].append((hash, scope, description))
elif commit_type in ['perf', 'refactor']:
categories['Improvements'].append((hash, scope, description))
# Generate Markdown
release_notes = f"# Release Notes: {new_version}\n\n"
release_notes += f"**Release Date**: {date}\n\n"
release_notes += "## What's Changed\n\n"
for category, items in categories.items():
release_notes += f"### {category}\n\n"
for hash, scope, desc in items:
scope_str = f"**{scope}**: " if scope else ""
release_notes += f"- {scope_str}{desc} ([{hash}](commit/{hash}))\n"
release_notes += "\n"
# Add traceability
release_notes += "## Traceability\n\n"
release_notes += generate_traceability_table(previous_tag)
# Add metrics
release_notes += "## Metrics\n\n"
release_notes += generate_metrics()
return release_notes
# Example usage
notes = generate_release_notes("v1.1.0", "v1.2.0")
print(notes)
Example Output (RELEASE_NOTES_v1.2.0.md):
# Release Notes: v1.2.0
**Release Date**: 2025-12-17
**Previous Version**: v1.1.0
## What's Changed
### Features
- **acc**: Implement obstacle distance calculation ([a3f5c21](commit/a3f5c21))
- **acc**: Add closing speed calculation ([b7e8d32](commit/b7e8d32))
- **acc**: Implement emergency brake trigger logic ([c9f1e43](commit/c9f1e43))
- **can**: Add CAN message filtering ([d2g3f54](commit/d2g3f54))
### Bug Fixes
- **can**: Fix timeout handling (sensor fault recovery) ([e4h5g65](commit/e4h5g65))
- **diagnostics**: Correct error code mapping ([f6i7h76](commit/f6i7h76))
### Documentation
- **srs**: Update requirements traceability matrix ([g8j9i87](commit/g8j9i87))
- **sad**: Add ACC architecture diagram ([h0k1j98](commit/h0k1j98))
## Traceability
| Requirement | Implementation | Test Cases | Status |
|-------------|----------------|------------|--------|
| [SWE-045-1] | src/acc_controller.c:45 | TC-SWE-045-1-1 to 6 | [PASS] Verified |
| [SWE-045-2] | src/acc_controller.c:78 | TC-SWE-045-2-1 to 4 | [PASS] Verified |
| [SWE-045-3] | src/acc_controller.c:120 | TC-SWE-045-3-1 to 8 | [PASS] Verified |
| [SWE-078-1] | src/can_driver.c:56 | TC-SWE-078-1-1 to 3 | [PASS] Verified |
## Metrics
- **Total Commits**: 42
- **Files Changed**: 28 files (+1,850 lines, -320 lines)
- **Contributors**: 5 (3 human, 2 AI agents)
- **Code Coverage**: 96.8% statement, 91.2% branch
- **MISRA Compliance**: 0 Required violations, 3 Advisory
- **Defects Fixed**: 12 bugs (6 critical, 6 minor)
## Quality Assurance
- [PASS] All unit tests passed (826/826)
- [PASS] Integration tests passed (45/45)
- [PASS] HIL tests passed (23/23)
- [PASS] MISRA C:2012 compliant (0 Required violations)
- [PASS] Code review: 100% reviewed, approved
- [PASS] Traceability: 100% (all requirements verified)
## Known Issues
1. **CAN-145**: Occasional CAN timeout (>1 second) under high bus load
- Workaround: Implemented retry logic (max 3 attempts)
- Fix planned: v1.2.1 (optimize CAN buffer management)
2. **ACC-089**: Lane keeping assist accuracy 92% (target: 95%)
- Impact: Minor (does not affect safety)
- Fix planned: v1.3.0 (retrain ML model with additional data)
## Upgrade Notes
**Breaking Changes**: None (backward-compatible with v1.1.0)
**Migration**: No action required (drop-in replacement)
**Compatibility**:
- AUTOSAR Classic R4.4.0
- TriCore TC397 (300 MHz)
- CAN 2.0B protocol
---
**Full Changelog**: [v1.1.0...v1.2.0](https://github.com/company/acc-ecu/compare/v1.1.0...v1.2.0)
[AI] Generated by AI Documentation Agent | ASPICE SUP.1
3. Build Release Artifacts
Action: Compile binaries, documentation, test reports
Release Artifacts:
release-v1.2.0/
├── firmware/
│ ├── acc_ecu_v1.2.0.elf # Binary (ELF format)
│ ├── acc_ecu_v1.2.0.hex # Binary (Intel HEX)
│ ├── acc_ecu_v1.2.0.s19 # Binary (Motorola S-record)
│ └── acc_ecu_v1.2.0.sha256 # Checksum
├── documentation/
│ ├── SRS_v1.2.0.pdf # Software Requirements Spec
│ ├── SAD_v1.2.0.pdf # Software Architecture Doc
│ ├── SDD_v1.2.0.pdf # Software Detailed Design
│ ├── Test_Report_v1.2.0.pdf # Verification report
│ └── Traceability_Matrix_v1.2.0.xlsx
├── source/
│ └── acc_ecu_v1.2.0_source.tar.gz # Source code archive
├── release_notes/
│ ├── RELEASE_NOTES_v1.2.0.md
│ └── CHANGELOG_v1.2.0.md
└── signatures/
├── firmware.elf.sig # Digital signature (code signing)
└── SBOM_v1.2.0.json # Software Bill of Materials
Automated Build:
# Build script: scripts/build_release.sh
#!/bin/bash
VERSION="v1.2.0"
RELEASE_DIR="release-$VERSION"
# Clean previous build
rm -rf $RELEASE_DIR
mkdir -p $RELEASE_DIR/{firmware,documentation,source,release_notes,signatures}
# Build firmware (multiple formats)
make clean
make all VERSION=$VERSION
cp build/firmware.elf $RELEASE_DIR/firmware/acc_ecu_$VERSION.elf
objcopy -O ihex build/firmware.elf $RELEASE_DIR/firmware/acc_ecu_$VERSION.hex
objcopy -O srec build/firmware.elf $RELEASE_DIR/firmware/acc_ecu_$VERSION.s19
# Generate checksum
sha256sum $RELEASE_DIR/firmware/acc_ecu_$VERSION.elf > $RELEASE_DIR/firmware/acc_ecu_$VERSION.sha256
# Package source code
git archive --format=tar.gz --prefix=acc_ecu_$VERSION/ HEAD > $RELEASE_DIR/source/acc_ecu_$VERSION_source.tar.gz
# Generate documentation (Doxygen → PDF)
doxygen Doxyfile
cd doxygen/latex && make
cp refman.pdf ../../$RELEASE_DIR/documentation/SDD_$VERSION.pdf
# Copy release notes
cp RELEASE_NOTES_$VERSION.md $RELEASE_DIR/release_notes/
# Sign firmware (if code signing enabled)
if [ -f "$CODE_SIGNING_KEY" ]; then
openssl dgst -sha256 -sign $CODE_SIGNING_KEY -out $RELEASE_DIR/signatures/firmware.elf.sig $RELEASE_DIR/firmware/acc_ecu_$VERSION.elf
fi
# Create archive
tar -czf release-$VERSION.tar.gz $RELEASE_DIR/
echo "[PASS] Release artifacts built: release-$VERSION.tar.gz"
4. Tag Release (Human Approval Required)
Action: Human release manager tags release in Git
Tagging Command (after human approval):
# Human verifies release artifacts
# - Firmware tested on target ECU
# - Documentation reviewed
# - All tests passed
# Create annotated tag
git tag -a v1.2.0 -m "Release v1.2.0: ACC obstacle detection feature
Features:
- Implement ACC obstacle distance calculation [SWE-045-1]
- Implement ACC closing speed calculation [SWE-045-2]
- Implement ACC emergency brake trigger [SWE-045-3]
Quality Metrics:
- Coverage: 96.8% statement, 91.2% branch
- MISRA C:2012: 0 Required violations
- Tests: 826/826 passed
Safety Class: ASIL-B
Approved-By: @release_manager (Alice Johnson)
Signed-off-by: Alice Johnson <alice@company.com>"
# Push tag to remote
git push origin v1.2.0
# Verify tag
git tag -l -n9 v1.2.0
5. Publish Release (GitHub/GitLab)
Action: Create release on GitHub/GitLab with artifacts
GitHub Release (via CLI):
# Create GitHub release
gh release create v1.2.0 \
--title "ACC ECU v1.2.0 - Obstacle Detection Feature" \
--notes-file RELEASE_NOTES_v1.2.0.md \
--target main \
release-v1.2.0.tar.gz \
release-v1.2.0/firmware/acc_ecu_v1.2.0.elf \
release-v1.2.0/firmware/acc_ecu_v1.2.0.hex
# Output:
# https://github.com/company/acc-ecu/releases/tag/v1.2.0
GitLab Release (via API):
import requests
def create_gitlab_release(project_id, version, release_notes, artifacts):
"""
Create GitLab release via API
"""
gitlab_url = "https://gitlab.com/api/v4"
access_token = os.getenv("GITLAB_TOKEN")
# Upload artifacts
artifact_links = []
for artifact in artifacts:
upload_response = requests.post(
f"{gitlab_url}/projects/{project_id}/uploads",
headers={"PRIVATE-TOKEN": access_token},
files={"file": open(artifact, "rb")}
)
artifact_url = upload_response.json()["url"]
artifact_links.append({
"name": os.path.basename(artifact),
"url": artifact_url
})
# Create release
payload = {
"tag_name": version,
"name": f"ACC ECU {version}",
"description": release_notes,
"assets": {
"links": artifact_links
}
}
response = requests.post(
f"{gitlab_url}/projects/{project_id}/releases",
headers={"PRIVATE-TOKEN": access_token},
json=payload
)
if response.status_code == 201:
print(f"[PASS] Release published: {response.json()['_links']['self']}")
else:
print(f"[FAIL] Release failed: {response.text}")
# Usage
create_gitlab_release(
project_id=42,
version="v1.2.0",
release_notes=open("RELEASE_NOTES_v1.2.0.md").read(),
artifacts=[
"release-v1.2.0/firmware/acc_ecu_v1.2.0.elf",
"release-v1.2.0/firmware/acc_ecu_v1.2.0.hex",
"release-v1.2.0.tar.gz"
]
)
Hotfix Release Workflow
Critical Bug Fix (Emergency Release)
Scenario: Production bug discovered, needs urgent fix
Hotfix Workflow:
# 1. Create hotfix branch from production tag
git checkout -b hotfix/v1.2.1-can-timeout v1.2.0
# 2. Fix bug
# (edit src/can_driver.c)
# 3. Commit fix
git add src/can_driver.c
git commit -m "fix(can): Fix timeout handling for sensor fault [HOTFIX-567]
Critical bug: CAN timeout not handled correctly, causes ECU reset
Fix: Add retry logic (max 3 attempts, 100ms interval)
Tested: HIL test bench (100 iterations, 0 failures)
ASIL-B Safety Impact: Medium (fail-safe behavior improved)
Approved-By: @safety_engineer"
# 4. Test hotfix
make test
# 5. Merge hotfix to main
git checkout main
git merge --no-ff hotfix/v1.2.1-can-timeout
# 6. Tag hotfix release
git tag -a v1.2.1 -m "Hotfix v1.2.1: CAN timeout handling
Critical Fix:
- Fix CAN timeout handling for sensor fault [HOTFIX-567]
Safety Class: ASIL-B
Approved-By: @release_manager"
# 7. Push to remote
git push origin main v1.2.1
# 8. Build and publish hotfix
./scripts/build_release.sh v1.2.1
gh release create v1.2.1 --notes "Hotfix: CAN timeout handling" release-v1.2.1.tar.gz
Hotfix Timeline: 4-8 hours (fast-track approval)
Release Checklist
Pre-Release Validation
Release Checklist (v1.2.0):
────────────────────────────────────────────────────
☐ Code Complete
☐ All planned features merged (ASPICE-1234, ASPICE-1235, ...)
☐ All critical bugs fixed
☐ No open P0/P1 issues
☐ Testing
☐ Unit tests: 826/826 passed [PASS]
☐ Integration tests: 45/45 passed [PASS]
☐ HIL tests: 23/23 passed [PASS]
☐ Regression tests: No new defects [PASS]
☐ Quality Assurance
☐ MISRA C:2012: 0 Required violations [PASS]
☐ Code review: 100% reviewed [PASS]
☐ Coverage: 96.8% (target: 95%) [PASS]
☐ Static analysis: 0 critical issues [PASS]
☐ Documentation
☐ Release notes generated [PASS]
☐ SRS updated (v1.2.0) [PASS]
☐ SAD updated (v1.2.0) [PASS]
☐ Traceability matrix updated [PASS]
☐ Test report generated [PASS]
☐ Artifacts
☐ Firmware compiled (ELF, HEX, S19) [PASS]
☐ Checksum generated (SHA-256) [PASS]
☐ Source code archived [PASS]
☐ Documentation packaged (PDF) [PASS]
☐ Firmware signed (code signing) [PASS]
☐ Approval
☐ Project manager approval [PASS]
☐ Safety engineer approval (ASIL-B) [PASS]
☐ Release manager approval [PASS]
Verdict: [PASS] APPROVED FOR RELEASE
Release Manager: Alice Johnson
Date: 2025-12-17
Summary
Release Workflow Key Steps:
- Feature Freeze: Stop new features, create release branch
- Generate Release Notes: AI compiles changes, traceability, metrics
- Build Artifacts: Firmware, documentation, source archive
- Tag Release: Human approves and tags (annotated tag)
- Publish Release: Upload artifacts to GitHub/GitLab
- Hotfix: Emergency bug fix, fast-track approval
AI Agent Role: Generate release notes, compile artifacts (human approves and tags)
Version Format: vMAJOR.MINOR.PATCH (SemVer)
Release Checklist: Code complete, tests pass, documentation updated, artifacts built, approvals obtained
Chapter 31 Complete: Workflow Instructions covers Git, Pull Requests, Testing, and Releases
Next: Chapter 32 - Prompt Templates (requirements, code generation, review, testing prompts)