clrf cleanup
This commit is contained in:
+6
-15
@@ -1,14 +1,10 @@
|
||||
# Release model
|
||||
|
||||
Each app release gets one document that keeps its version, build information,
|
||||
and public changelog together in one place. We are building this new release
|
||||
model alongside the existing production workflows so we can try it safely
|
||||
before using it for a real release.
|
||||
Each app release gets one document that keeps its version, build information, and public changelog together in one place.
|
||||
|
||||
## Identity
|
||||
|
||||
The workflow accepts one version in strict `x.y.z` format and derives all other
|
||||
identifiers from it:
|
||||
The workflow accepts one version in strict `x.y.z` format and derives all other identifiers from it:
|
||||
|
||||
| Resource | Format |
|
||||
| --- | --- |
|
||||
@@ -22,8 +18,7 @@ Callers must not supply these derived identifiers independently.
|
||||
|
||||
## Prepared state
|
||||
|
||||
The preparation workflow creates the document before freezing the native
|
||||
candidate. At this stage, only `releaseVersion` is required:
|
||||
The preparation workflow creates the document before freezing the native candidate. At this stage, only `releaseVersion` is required:
|
||||
|
||||
```md
|
||||
---
|
||||
@@ -43,8 +38,7 @@ releaseVersion: 1.131.1
|
||||
|
||||
## Final state
|
||||
|
||||
After both native builds succeed, the workflow records the frozen source and
|
||||
artifact-derived build numbers. A finalized document requires every field:
|
||||
After both native builds succeed, the workflow records the frozen source and artifact-derived build numbers. A finalized document requires every field:
|
||||
|
||||
```yaml
|
||||
releaseVersion: 1.131.1
|
||||
@@ -54,9 +48,6 @@ iosBuildNumber: 1662
|
||||
androidVersionCode: 1110
|
||||
```
|
||||
|
||||
`sourceTag` must equal `releaseVersion`, `sourceSha` must be a full Git object
|
||||
ID, and both build numbers must be positive integers.
|
||||
`sourceTag` must equal `releaseVersion`, `sourceSha` must be a full Git object ID, and both build numbers must be positive integers.
|
||||
|
||||
Each successful OTA adds exactly one contiguous section (`OTA 1`, `OTA 2`, and
|
||||
so on) inside the public changelog delimiters. GitHub Release text is extracted
|
||||
only from those delimiters; operational frontmatter is never published.
|
||||
Each successful OTA adds exactly one contiguous section (`OTA 1`, `OTA 2`, and so on) inside the public changelog delimiters. GitHub Release text is extracted only from those delimiters; operational frontmatter is never published.
|
||||
|
||||
@@ -30,6 +30,10 @@ function fail(message) {
|
||||
throw new ReleaseError(message)
|
||||
}
|
||||
|
||||
function normalizeLineEndings(markdown) {
|
||||
return markdown.replace(/\r\n?/g, '\n')
|
||||
}
|
||||
|
||||
export function assertReleaseVersion(version) {
|
||||
if (typeof version !== 'string' || !VERSION_PATTERN.test(version)) {
|
||||
fail(`Release version must use strict x.y.z format; found '${version}'.`)
|
||||
@@ -49,7 +53,7 @@ export function deriveReleaseIdentity(version) {
|
||||
}
|
||||
|
||||
function parseFrontmatter(markdown) {
|
||||
const normalized = markdown.replace(/\r\n/g, '\n')
|
||||
const normalized = normalizeLineEndings(markdown)
|
||||
if (!normalized.startsWith('---\n')) {
|
||||
fail('Release file must start with YAML frontmatter.')
|
||||
}
|
||||
@@ -249,7 +253,8 @@ export function extractPublicChangelog(markdown) {
|
||||
}
|
||||
|
||||
export function appendOtaChangelog(markdown, sequence, changelog) {
|
||||
const parsed = parseReleaseDocument(markdown)
|
||||
const normalized = normalizeLineEndings(markdown)
|
||||
const parsed = parseReleaseDocument(normalized)
|
||||
const expectedSequence = parsed.sections.length
|
||||
if (!Number.isSafeInteger(sequence) || sequence !== expectedSequence) {
|
||||
fail(`Next OTA sequence must be ${expectedSequence}; found '${sequence}'.`)
|
||||
@@ -258,22 +263,29 @@ export function appendOtaChangelog(markdown, sequence, changelog) {
|
||||
if (!content) fail('OTA changelog cannot be empty.')
|
||||
|
||||
const delimiter = `\n\n${PUBLIC_CHANGELOG_END}`
|
||||
if (!normalized.includes(delimiter)) {
|
||||
fail('Could not find the public changelog end delimiter to append the OTA.')
|
||||
}
|
||||
const replacement = `\n\n## OTA ${sequence}\n\n${content}${delimiter}`
|
||||
const updated = markdown.replace(delimiter, replacement)
|
||||
const updated = normalized.replace(delimiter, replacement)
|
||||
parseReleaseDocument(updated)
|
||||
return updated
|
||||
}
|
||||
|
||||
export function finalizeReleaseDocument(markdown, finalMetadata) {
|
||||
const parsed = parseReleaseDocument(markdown)
|
||||
const normalized = normalizeLineEndings(markdown)
|
||||
const parsed = parseReleaseDocument(normalized)
|
||||
const metadata = {...parsed.metadata, ...finalMetadata}
|
||||
validateMetadata(metadata, 'final')
|
||||
|
||||
const frontmatter = FRONTMATTER_KEYS.map(
|
||||
key => `${key}: ${metadata[key]}`,
|
||||
).join('\n')
|
||||
const updated = markdown.replace(
|
||||
/^---\n[\s\S]*?\n---\n/,
|
||||
const frontmatterPattern = /^---\n[\s\S]*?\n---\n/
|
||||
if (!frontmatterPattern.test(normalized))
|
||||
fail('Could not replace the release frontmatter.')
|
||||
const updated = normalized.replace(
|
||||
frontmatterPattern,
|
||||
`---\n${frontmatter}\n---\n`,
|
||||
)
|
||||
parseReleaseDocument(updated, {stage: 'final'})
|
||||
|
||||
Reference in New Issue
Block a user