# GitRelease Extension Specification

GitRelease is a release management extension for the GitMsg protocol (name: `release`, version: `0.1.0`).

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

## 1. Messages

### 1.1. Types

- `release`: Version release

### 1.2. Fields

- `artifact-url`: Base URL for externally hosted artifacts
- `artifacts`: Comma-separated list of artifact filenames
- `checksums`: Checksums filename stored alongside artifacts (e.g., `SHA256SUMS`)
- `prerelease`: Boolean indicating pre-release status (`true` or `false`)
- `sbom`: SBOM filename stored alongside artifacts (e.g., `sbom.spdx.json`)
- `signed-by`: Key fingerprint for release signature (GPG or SSH)
- `tag`: Git tag name (e.g., `v1.0.0`)
- `version`: Release version (semver format, e.g., `1.0.0`)

Field order: `artifact-url`, `artifacts`, `checksums`, `prerelease`, `sbom`, `signed-by`, `tag`, `version`.

### 1.3. Message Rules

- The `version` field MUST follow semantic versioning (major.minor.patch)
- The `tag` field SHOULD match an existing git tag
- Releases with `prerelease="true"` SHOULD NOT be treated as stable
- The `artifacts` field MUST contain filenames only; storage location is determined by Section 3
- The `sbom` field SHOULD use OpenSSF naming conventions: `*.spdx.json` for SPDX or `*.cdx.json` for CycloneDX
- Subject lines SHOULD describe the release (e.g., version number or codename)

### 1.4. Editing and Retracting

Releases MAY be edited or retracted using core versioning (GITMSG.md Section 1.5). Implementations SHOULD display an edit indicator on modified releases.

Retracted releases SHOULD be hidden from release listings but MAY remain accessible for audit purposes. Retracting a release SHOULD NOT delete stored artifacts.

### 1.5. Comments

Implementations MUST use GitSocial for release comments. The `original` field references the release commit:

```
Looks great, shipping to production now.

GitMsg: ext="social"; type="comment"; original="#commit:abc123456789@gitmsg/release"; v="0.1.0"
GitMsg-Ref: ext="release"; type="release"; author="Alice"; email="alice@example.com"; time="2025-01-06T10:00:00Z"; ref="#commit:abc123456789@gitmsg/release"; v="0.1.0"
 > Release v1.0.0
```

## 2. Config

Configuration MUST be stored at `refs/gitmsg/release/config`:

```json
{
  "version": "0.1.0",
  "branch": "gitmsg/release",
  "require-signature": false,
  "checksum-algorithm": "sha256"
}
```

Configuration MUST include: `version`.

Configuration SHOULD include: `branch`. Default: `gitmsg/release`.

Configuration MAY include: `require-signature`, `checksum-algorithm` (one of: `sha256`, `sha512`).

## 3. Artifact Storage

Implementations SHOULD use git-based storage (Section 3.1) for artifact discoverability. Implementations MAY use external storage by specifying the `artifact-url` field (Section 3.2).

### 3.1. Git Storage

Release artifacts SHOULD be stored at `refs/gitmsg/release/<version>/artifacts/*`:

```
refs/gitmsg/release/v1.0.0/artifacts/
├── app-linux-x64.tar.gz      (Git LFS pointer)
├── app-darwin-arm64.tar.gz   (Git LFS pointer)
├── app-windows-x64.zip       (Git LFS pointer)
└── SHA256SUMS                (plaintext)
```

### 3.2. External Storage

Implementations MAY host artifacts externally (CDN, object storage, package registry) by setting the `artifact-url` field to the base URL. The full artifact URL is `<artifact-url>/<filename>` where filenames come from the `artifacts` field.

When `artifact-url` is present, implementations MUST NOT require git-based storage for that release.

### 3.3. SBOM Storage

SBOM files MUST be stored in the same artifact ref as other release artifacts. The `sbom` field contains the filename; the format is inferred from the file extension:

- `.spdx.json` — SPDX (ISO/IEC 5962)
- `.cdx.json` — CycloneDX (ECMA-424)

```
refs/gitmsg/release/v1.0.0/artifacts/
├── app-linux-x64.tar.gz
├── app-linux-x64.tar.gz.spdx.json   (per-artifact SBOM)
├── sbom.spdx.json                    (standalone SBOM)
├── SHA256SUMS
```

Implementations MAY support per-artifact SBOMs (named `<artifact>.spdx.json` or `<artifact>.cdx.json`) alongside a standalone SBOM. The `sbom` field SHOULD reference the standalone SBOM when both are present.

SBOM content is generated by external tools (e.g., Syft, Trivy, cdxgen). GitRelease stores and distributes the output; it does not generate SBOMs.

### 3.4. Artifact Requirements

- Git-stored artifacts larger than 1MB SHOULD use Git LFS
- Releases SHOULD include a checksums file (`SHA256SUMS` or `SHA512SUMS`)
- Releases MAY include detached signatures (`.sig` or `.asc` files)

### 3.5. Checksum File Format

```
abc123def456...  app-linux-x64.tar.gz
def456abc789...  app-darwin-arm64.tar.gz
ghi789def012...  app-windows-x64.zip
```

## Appendix: Manifest

```json
{
  "name": "release",
  "version": "0.1.0",
  "display": "GitRelease",
  "description": "Release management extension for GitMsg",
  "types": ["release"],
  "fields": ["artifact-url", "artifacts", "checksums", "prerelease", "sbom", "signed-by", "tag", "version"]
}
```

## Appendix: Validation

- Version format: semver (`^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$`)
- Tag format: `^[a-zA-Z0-9._-]+$`
- Artifact names: `^[a-zA-Z0-9._-]+$`
- SBOM filename: `^.+\.(spdx\.json|cdx\.json)$`
- Checksum algorithms: `sha256|sha512`

## Appendix: Examples

### Create Release

```
Release v1.0.0

GitMsg: ext="release"; type="release"; tag="v1.0.0"; version="1.0.0"; v="0.1.0"
```

### Create Pre-release

```
Release v2.0.0-beta.1

GitMsg: ext="release"; type="release"; prerelease="true"; tag="v2.0.0-beta.1"; version="2.0.0-beta.1"; v="0.1.0"
```

### Create Release with Artifacts

```
Release v1.0.0

Pre-built binaries for Linux, macOS, and Windows.

GitMsg: ext="release"; type="release"; artifacts="app-linux-x64.tar.gz,app-darwin-arm64.tar.gz,app-windows-x64.zip"; checksums="SHA256SUMS"; sbom="sbom.spdx.json"; signed-by="SHA256:abc123..."; tag="v1.0.0"; version="1.0.0"; v="0.1.0"
```

### Edit Release

```
Release v1.0.0

Updated release description with additional context.

GitMsg: ext="release"; type="release"; edits="#commit:abc123456789@gitmsg/release"; tag="v1.0.0"; version="1.0.0"; v="0.1.0"
```

### Retract Release

```
GitMsg: ext="release"; edits="#commit:abc123456789@gitmsg/release"; retracted="true"; v="0.1.0"
```

### Release Referencing PM Issue

```
Release v1.0.0

Implements #commit:abc123456789@gitmsg/pm.

GitMsg: ext="release"; type="release"; tag="v1.0.0"; version="1.0.0"; v="0.1.0"
GitMsg-Ref: ext="pm"; type="issue"; author="Alice"; email="alice@example.com"; time="2025-01-06T10:00:00Z"; ref="#commit:abc123456789@gitmsg/pm"; v="0.1.0"
 > Add dark mode support
```
