diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..8168687 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,149 @@ +name: release + +on: + push: + tags: + - 'v*.*.*' # Triggert auf Semantic Versioning Tags (v1.0.0, v2.1.3, etc.) + +permissions: + contents: write + packages: write + +jobs: + release: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + + - name: Load versions from .env.versions + id: versions + run: | + set -a + source .env.versions + set +a + + echo "node_version=${NODE_VERSION}" >> "$GITHUB_OUTPUT" + echo "go_version=${GO_VERSION}" >> "$GITHUB_OUTPUT" + echo "hugo_version=${HUGO_VERSION}" >> "$GITHUB_OUTPUT" + + echo "Node: ${NODE_VERSION}" + echo "Go: ${GO_VERSION}" + echo "Hugo: ${HUGO_VERSION}" + + - name: Extract version from tag + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "Version: ${VERSION}" + + - name: Repository meta + id: repository + run: | + registry=${{ github.server_url }} + registry=${registry##http*://} + echo "registry=${registry}" >> "$GITHUB_OUTPUT" + echo "registry=${registry}" + repository="$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')" + echo "repository=${repository}" >> "$GITHUB_OUTPUT" + echo "repository=${repository}" + + - name: Docker meta + uses: docker/metadata-action@v5 + id: docker + with: + images: ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest + + - name: Login to registry + uses: docker/login-action@v3 + with: + registry: ${{ steps.repository.outputs.registry }} + username: "${{ secrets.PACKAGES_USER }}" + password: "${{ secrets.PACKAGES_TOKEN }}" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + buildkitd-flags: '--allow-insecure-entitlement network.host' + driver-opts: network=host + + - name: Build and push release images + uses: docker/build-push-action@v6 + with: + context: . + push: true + allow: network.host + network: host + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.docker.outputs.tags }} + labels: ${{ steps.docker.outputs.labels }} + build-args: | + NODE_VERSION=${{ steps.versions.outputs.node_version }} + GO_VERSION=${{ steps.versions.outputs.go_version }} + HUGO_VERSION=${{ steps.versions.outputs.hugo_version }} + + - name: Generate changelog + id: changelog + run: | + # Finde vorheriges Tag + PREVIOUS_TAG=$(git describe --abbrev=0 --tags ${GITHUB_REF}^ 2>/dev/null || echo "") + + if [ -z "$PREVIOUS_TAG" ]; then + echo "Erster Release - Changelog von Anfang an" + CHANGELOG=$(git log --pretty=format:"- %s (%h)" --no-merges) + else + echo "Changelog seit ${PREVIOUS_TAG}" + CHANGELOG=$(git log ${PREVIOUS_TAG}..${GITHUB_REF} --pretty=format:"- %s (%h)" --no-merges) + fi + + # Schreibe in Output-Datei (multiline) + { + echo 'changelog<> "$GITHUB_OUTPUT" + + - name: Create Forgejo/Gitea Release + uses: actions/forgejo-release@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + direction: upload + release-dir: . + title: "Release ${{ steps.version.outputs.version }}" + tag: ${{ github.ref_name }} + token: ${{ secrets.GITHUB_TOKEN }} + release-notes: | + # Release ${{ steps.version.outputs.version }} + + ## Docker Images + + Multi-platform images (linux/amd64, linux/arm64) sind verfügbar: + + ```bash + docker pull ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }}:${{ steps.version.outputs.version }} + docker pull ${{ steps.repository.outputs.registry }}/${{ steps.repository.outputs.repository }}:latest + ``` + + ## Build Versions + + - Node.js: ${{ steps.versions.outputs.node_version }} + - Go: ${{ steps.versions.outputs.go_version }} + - Hugo: ${{ steps.versions.outputs.hugo_version }} + + ## Changes + + ${{ steps.changelog.outputs.changelog }} diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..f435beb --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,207 @@ +# Release Process + +This document describes the release process for the IPCEI-CIS Developer Framework. + +## Overview + +The project uses **Semantic Versioning** (SemVer) for releases. Each release is triggered by a Git tag and automatically creates: + +- Multi-platform Docker images (linux/amd64, linux/arm64) +- Forgejo release with release notes +- Automatically generated changelog + +## Versioning Schema + +We follow [Semantic Versioning 2.0.0](https://semver.org/): + +- `MAJOR.MINOR.PATCH` (e.g., `v1.2.3`) +- **MAJOR**: Breaking changes (incompatible API changes) +- **MINOR**: New features (backwards compatible) +- **PATCH**: Bug fixes (backwards compatible) + +## Creating a Release + +### 1. Check Prerequisites + +Ensure that: + +- All tests are passing (`task test`) +- CI pipeline runs successfully +- All desired changes are in the `main` branch +- You have the latest version: `git pull origin main` + +### 2. Determine Version + +Determine the new version number based on the changes: + +```bash +# Show current tag +git describe --tags --abbrev=0 + +# Show commits since last release +git log $(git describe --tags --abbrev=0)..HEAD --oneline +``` + +### 3. Create Tag + +Create an annotated tag with the new version: + +```bash +# For a new patch release (e.g., v1.2.3 → v1.2.4) +git tag -a v1.2.4 -m "Release v1.2.4" + +# For a minor release (e.g., v1.2.3 → v1.3.0) +git tag -a v1.3.0 -m "Release v1.3.0" + +# For a major release (e.g., v1.2.3 → v2.0.0) +git tag -a v2.0.0 -m "Release v2.0.0" +``` + +### 4. Push Tag + +Push the tag to the repository - this triggers the release pipeline: + +```bash +git push origin v1.2.4 +``` + +### 5. Monitor Release Pipeline + +The release pipeline (`release.yaml`) starts automatically: + +1. Open the Actions tab in Forgejo +2. Monitor the `release` workflow +3. On success: Release is visible on the Releases page + +## What Happens Automatically? + +The release pipeline (`release.yaml`) performs the following steps: + +1. **Build Docker Images** + - Multi-platform build (AMD64 + ARM64) + - Images are tagged with: + - `vX.Y.Z` (exact version, e.g., `v1.2.3`) + - `vX.Y` (minor version, e.g., `v1.2`) + - `vX` (major version, e.g., `v1`) + - `latest` (latest release) + +2. **Push Images** + - To the container registry (Forgejo Packages) + +3. **Generate Changelog** + - Automatically from Git commits since last release + - Format: `- Commit Message (hash)` + +4. **Create Forgejo Release** + - With generated release notes + - Contains build versions (Node, Go, Hugo) + - Docker pull commands + - Changelog + +## Using Docker Images + +After a successful release, the images are available: + +```bash +# Specific version +docker pull /:v1.2.3 + +# Latest +docker pull /:latest + +# Major/Minor version +docker pull /:v1 +docker pull /:v1.2 +``` + +## Best Practices + +### Commit Messages + +Use meaningful commit messages, as they will appear in the changelog: + +```bash +# Good +git commit -m "fix: correct multi-platform Docker build for ARM64" +git commit -m "feat: add automatic release pipeline" +git commit -m "docs: update RELEASE.md" + +# Bad +git commit -m "fix stuff" +git commit -m "wip" +``` + +**Conventional Commits** help with categorization: + +- `feat:` - New features +- `fix:` - Bug fixes +- `docs:` - Documentation +- `chore:` - Maintenance +- `refactor:` - Code restructuring +- `test:` - Tests + +### Release Frequency + +- **Patch releases**: As needed (bug fixes) +- **Minor releases**: Regular (new features) +- **Major releases**: Rare (breaking changes) + +### Hotfixes + +For urgent bug fixes: + +1. Create branch from last release tag +2. Fix the bug +3. Create new patch release + +```bash +git checkout v1.2.3 +git checkout -b hotfix/critical-bug +# Implement fix +git commit -m "fix: critical bugfix" +git tag -a v1.2.4 -m "Release v1.2.4 - Hotfix" +git push origin v1.2.4 +``` + +## Troubleshooting + +### Release Pipeline Fails + +1. **Check Secrets**: `PACKAGES_USER`, `PACKAGES_TOKEN` must be set +2. **Check Logs**: Open the failed workflow in the Actions tab +3. **Local Test**: + + ```bash + task build:oci-image + task test:oci-image + ``` + +### Delete/Correct Tag + +**Locally:** + +```bash +git tag -d v1.2.3 +``` + +**Remote:** + +```bash +git push --delete origin v1.2.3 +``` + +⚠️ **Warning**: Releases should not be deleted after they have been published! + +### Edit Release Notes Afterwards + +Release notes can be manually edited in Forgejo: + +1. Go to Releases +2. Click on the release +3. Click "Edit" + +## Further Information + +- [Semantic Versioning](https://semver.org/) +- [Conventional Commits](https://www.conventionalcommits.org/) +- [Keep a Changelog](https://keepachangelog.com/)