Skip to content
Snippets Groups Projects
Commit cdd72233 authored by Dan Allen's avatar Dan Allen
Browse files

update release process; automate management of release and tool version attributes

parent a8d8e729
No related branches found
No related tags found
Loading
Pipeline #680136224 passed
......@@ -16,6 +16,7 @@ This project utilizes semantic versioning.
* *content-classifier*: Add guard to prevent `ContentCatalog#registerSiteStartPage` from registering alias loop (#1020)
* *redirect-producer*: Preserve target when creating static route if target is an absolute URL (#1024)
* *site-generator*: Look for IS_TTY on `playbook.env` in site generator to decouple check from process environment
* release process: Automatically populate version and release attributes during release (#1011)
== 3.1.1 (2022-09-20)
......
......@@ -24,7 +24,7 @@ ifdef::env-gitlab[:outfilesuffix: .adoc]
:url-git-credential-store: https://git-scm.com/docs/git-credential-store
// Versions:
:version-node-major: 16
:version-node: {version-node-major}.16.0
:version-node: 16.18.0
{url-project}[Antora] is a modular, multi-repository site generator designed for creating documentation sites from content composed in AsciiDoc(R) and processed with {url-asciidoctor}[Asciidoctor].
......
......@@ -4,14 +4,16 @@ prerelease: false
title: Antora
asciidoc:
attributes:
release-date: 2022-09-20
release-tag: latest
release-version: '3.1.1'
source-language: asciidoc@
xrefstyle: short@
example-caption: false
listing-caption: Example@
patch: '.2'
version-node-major: '16'
version-node: '16.17.0'
version-npm: '8.15.0'
version-node: '16.18.0'
version-npm: '8.19.2'
url-node-releases: https://nodejs.org/en/about/releases/
url-chat: https://chat.antora.org
url-repo: https://gitlab.com/antora/antora
......
......@@ -72,8 +72,8 @@ If the installation is successful, the command will report the version of the An
[subs=+attributes]
$ npx antora -v
@antora/cli: {page-component-version}{patch}
@antora/site-generator: {page-component-version}{patch}
@antora/cli: {release-version}
@antora/site-generator: {release-version}
These versions can also be found in [.path]_package.json_, which you can use to upgrade Antora.
......
......@@ -10,7 +10,7 @@ Each major release line of the Antora Core components is typically supported for
|Release Line |Latest Release |Status |GA |Maintenance |EOL
|Antora 3
|{page-component-version}{patch}
|{release-version}
|Active
|2021/12/25
|TBD
......@@ -22,7 +22,6 @@ Each major release line of the Antora Core components is typically supported for
|2018/12/25
|2022/01/25
|2022/02/25
|===
General Availability (GA):: A release line, such as Antora 2.x, enters general availability on the date the initial, final major version (e.g., Antora 2.0.0) of the software is released and available for download.
......
......@@ -81,7 +81,7 @@ Verify the `antora` command is available through `npx` by running `npx antora -v
This command should report the version of the Antora CLI in the terminal.
[subs=attributes+]
@antora/cli: {page-component-version}{patch}
@antora/cli: {release-version}
@antora/site-generator: not installed
The `npx` command will look for the `antora` command installed within the playbook project or any parent directory of the playbook project.
......@@ -111,8 +111,8 @@ Antora's CLI will look for the site generator package in this folder first befor
Now when you run `npx antora -v`, you should see the version of both the Antora CLI and the site generator printed in the terminal.
[subs=attributes+]
@antora/cli: {page-component-version}{patch}
@antora/site-generator: {page-component-version}{patch}
@antora/cli: {release-version}
@antora/site-generator: {release-version}
If you open [.path]_package.json_, you'll see the version of these packages listed there too, as development dependencies.
......@@ -120,8 +120,8 @@ If you open [.path]_package.json_, you'll see the version of these packages list
----
{
"devDependencies": {
"@antora/cli": "{page-component-version}{patch}",
"@antora/site-generator": "{page-component-version}{patch}"
"@antora/cli": "{release-version}",
"@antora/site-generator": "{release-version}"
}
}
----
......@@ -153,8 +153,8 @@ If installation was successful, the command should report the version of the Ant
[subs=attributes+]
$ antora -v
@antora/cli: {page-component-version}{patch}
@antora/site-generator: {page-component-version}{patch}
@antora/cli: {release-version}
@antora/site-generator: {release-version}
The benefit of installing Antora globally is that it is always available in your terminal, no matter what directory you are in.
While this may seem convenient at first, there are problems with this strategy.
......
......@@ -7,7 +7,7 @@ On this page, you'll learn:
* [x] How to upgrade Antora globally.
* [x] How to upgrade the Antora CLI and site generator individually.
NOTE: If you're already on Antora 3.0 and ready to upgrade to Antora {page-component-version}{patch}, skip the next section and go directly to <<node,Upgrade Node.js>>.
NOTE: If you're already on Antora 3.0 and ready to upgrade to Antora {page-component-version}, skip the next section and go directly to <<node,Upgrade Node.js>>.
include::partial$upgrade-checklist.adoc[]
......@@ -59,8 +59,8 @@ The `npm i` command will consult this file to determine which packages and which
----
{
"devDependencies": {
"@antora/cli": "{page-component-version}{patch}",
"@antora/site-generator": "{page-component-version}{patch}"
"@antora/cli": "{release-version}",
"@antora/site-generator": "{release-version}"
}
}
----
......@@ -104,8 +104,8 @@ If you've installed the Antora CLI and site generator globally, you'll see them
[subs=attributes+]
....
/home/user/.nvm/versions/node/v{version-node}/lib
├── @antora/cli@{page-component-version}{patch}
├── @antora/site-generator@{page-component-version}{patch}
├── @antora/cli@{release-version}
├── @antora/site-generator@{release-version}
├── npm@{version-npm}
└── ...
....
......
'use strict'
const { promises: fsp } = require('fs')
const README_SRC = 'README.adoc'
const README_HIDDEN = '.' + README_SRC
const README_DEST = 'README.md'
......
'use strict'
const { promises: fsp } = require('fs')
const ospath = require('path')
const PROJECT_ROOT_DIR = ospath.join(__dirname, '..')
const DOCS_CONFIG_FILE = ospath.join(PROJECT_ROOT_DIR, 'docs/antora.yml')
const VERSION = process.env.npm_package_version
function updateDocsDesc () {
const hyphenIdx = VERSION.indexOf('-')
const main = ~hyphenIdx ? VERSION.substr(0, hyphenIdx) : VERSION
const prerelease = ~hyphenIdx ? VERSION.substr(hyphenIdx + 1) : undefined
const [major, minor, patch] = main.split('.')
return fsp.readFile(DOCS_CONFIG_FILE, 'utf8').then((desc) => {
desc = desc
.replace(/^version: \S+$/m, `version: ${q(major + '.' + minor)}`)
.replace(/^prerelease: \S+$/m, `prerelease: ${prerelease ? q('.' + patch + '-' + prerelease) : 'false'}`)
return fsp.writeFile(DOCS_CONFIG_FILE, desc, 'utf8')
})
}
function q (str) {
return `'${str}'`
}
;(async () => {
await updateDocsDesc()
})()
'use strict'
const { promises: fsp } = require('fs')
const README_SRC = 'README.adoc'
const README_HIDDEN = '.' + README_SRC
const README_DEST = 'README.md'
......
......@@ -7,17 +7,17 @@ if [ -z "$RELEASE_DEPLOY_KEY" ]; then
exit 1
fi
fi
if [ -z $RELEASE_NPM_TOKEN ]; then
if [ -z "$RELEASE_NPM_TOKEN" ]; then
declare -n RELEASE_NPM_TOKEN="RELEASE_NPM_TOKEN_$GITLAB_USER_LOGIN"
if [ -z $RELEASE_NPM_TOKEN ]; then
if [ -z "$RELEASE_NPM_TOKEN" ]; then
echo No release npm token \(RELEASE_NPM_TOKEN or RELEASE_NPM_TOKEN_$GITLAB_USER_LOGIN\) defined. Halting release.
exit 1
fi
fi
RELEASE_BRANCH=$CI_COMMIT_BRANCH
export RELEASE_BRANCH=${CI_COMMIT_BRANCH:-main}
# RELEASE_VERSION can be a version number (exact) or increment keyword (next in sequence)
if [ -z $RELEASE_VERSION ]; then RELEASE_VERSION=prerelease; fi
if [ -z $RELEASE_NPM_TAG ]; then
if [ -z "$RELEASE_VERSION" ]; then RELEASE_VERSION=prerelease; fi
if [ -z "$RELEASE_NPM_TAG" ]; then
if case $RELEASE_VERSION in major|minor|patch) ;; *) false;; esac; then
RELEASE_NPM_TAG=latest
elif case $RELEASE_VERSION in pre*) ;; *) false;; esac; then
......@@ -54,13 +54,13 @@ git fetch --depth ${GIT_DEPTH:-5} --update-shallow origin $RELEASE_BRANCH
# make sure the release branch exists as a local branch
git checkout -b $RELEASE_BRANCH -t origin/$RELEASE_BRANCH
if [ "$(git rev-parse $RELEASE_BRANCH)" != $CI_COMMIT_SHA ]; then
if [ "$(git rev-parse $RELEASE_BRANCH)" != "$CI_COMMIT_SHA" ]; then
echo $RELEASE_BRANCH moved forward from $CI_COMMIT_SHA. Halting release.
exit 1
fi
# configure npm client for publishing
echo -e "access=public\ntag=$RELEASE_NPM_TAG\n//registry.npmjs.org/:_authToken=$RELEASE_NPM_TOKEN" > .npmrc
echo -e "//registry.npmjs.org/:_authToken=$RELEASE_NPM_TOKEN" > $HOME/.npmrc
# release!
(
......@@ -68,20 +68,22 @@ echo -e "access=public\ntag=$RELEASE_NPM_TAG\n//registry.npmjs.org/:_authToken=$
npm version --workspaces --include-workspace-root --no-git-tag-version $RELEASE_VERSION
RELEASE_VERSION=$(npm exec -c 'echo -n $npm_package_version')
if case $RELEASE_VERSION in 1.0.0-*) ;; *) false;; esac; then
sed -i "s/^tag=$RELEASE_NPM_TAG$/tag=latest/" .npmrc
RELEASE_NPM_TAG=latest
fi
git commit -a -m "release $RELEASE_VERSION [skip ci]"
git commit -a -m "release $RELEASE_VERSION"
git tag -m "version $RELEASE_VERSION" v$RELEASE_VERSION
git push origin $(git describe --tags --exact-match)
npm publish $(node npm/publish-workspace-args.js)
npm publish --access public --tag $RELEASE_NPM_TAG $(node npm/publish-workspace-args.js)
npm run prepareForDev
git commit -a -m "prepare branch for development [skip ci]"
git push origin $RELEASE_BRANCH
)
exit_code=$?
# nuke npm settings
unlink .npmrc
unlink $HOME/.npmrc
# check for any uncommitted files
git status -s -b
# kill the ssh-agent
......
'use strict'
const { exec } = require('child_process')
const { promises: fsp } = require('fs')
const https = require('https')
const ospath = require('path')
const { promisify } = require('util')
const NODEJS_RELEASES_URL = 'https://nodejs.org/dist/index.json'
const PROJECT_ROOT_DIR = ospath.join(__dirname, '..')
const CHANGELOG_FILE = ospath.join(PROJECT_ROOT_DIR, 'CHANGELOG.adoc')
const DOCS_CONFIG_FILE = ospath.join(PROJECT_ROOT_DIR, 'docs/antora.yml')
const PACKAGE_LOCK_FILE = ospath.join(PROJECT_ROOT_DIR, 'package-lock.json')
const PACKAGES_DIR = ospath.join(PROJECT_ROOT_DIR, 'packages')
const README_FILE = ospath.join(PROJECT_ROOT_DIR, 'README.adoc')
const VERSION = process.env.npm_package_version
function compareSemVer (a, b) {
const componentsA = a.split('.')
const componentsB = b.split('.')
for (let i = 0; i < 3; i++) {
const numA = Number(componentsA[i])
const numB = Number(componentsB[i])
if (numA > numB) return 1
if (numB > numA) return -1
}
return 0
}
function getCurrentDate () {
const now = new Date()
return new Date(now.getTime() - now.getTimezoneOffset() * 60000)
}
function updateDocsConfig () {
const hyphenIdx = VERSION.indexOf('-')
const base = ~hyphenIdx ? VERSION.substr(0, hyphenIdx) : VERSION
const [major, minor, patch] = base.split('.')
const prerelease = ~hyphenIdx ? VERSION.substr(hyphenIdx + 1) : undefined
return fsp
.readFile(DOCS_CONFIG_FILE, 'utf8')
.then((desc) =>
fsp.writeFile(
DOCS_CONFIG_FILE,
desc
.replace(/^version: \S+$/m, `version: ${q(major + '.' + minor)}`)
.replace(/^prerelease: \S+$/m, `prerelease: ${prerelease ? q('.' + patch + '-' + prerelease) : 'false'}`),
'utf8'
)
)
.then(() => promisify(exec)('git add docs/antora.yml', { cwd: PROJECT_ROOT_DIR }))
function getToolVersions (major) {
return readFromURL(NODEJS_RELEASES_URL)
.then(JSON.parse)
.then((data) => {
data.forEach((it) => {
if (it.version.charAt() === 'v') it.version = it.version.substr(1)
})
data.sort(({ version: a }, { version: b }) => compareSemVer(b, a))
const { version, npm } = data.find(major ? ({ version }) => version.startsWith(major + '.') : ({ lts }) => lts)
return { nodeVersion: version, npmVersion: npm }
})
}
function readFromURL (url) {
return new Promise((resolve, reject) => {
const buffer = []
https
.get(url, (response) => {
response.on('data', (chunk) => buffer.push(chunk.toString()))
response.on('end', () => resolve(buffer.join('').trimRight()))
})
.on('error', reject)
})
}
function updateDocsDesc (releaseDate) {
return getToolVersions('16').then(({ nodeVersion, npmVersion }) =>
Promise.all([
fsp.readFile(DOCS_CONFIG_FILE, 'utf8').then((contents) => {
const prerelease = ~VERSION.indexOf('-')
contents = contents
.replace(/^(version:) \S+$/m, `$1 ${q(VERSION)}`)
.replace(/^(prerelease:) \S+$/m, `$1 ${prerelease ? 'true' : 'false'}`)
.replace(/^( {4}release-version:) \S+$/m, `$1 ${q(VERSION)}`)
.replace(/^( {4}release-tag:) \S+$/m, `$1 ${prerelease ? 'testing' : 'latest'}`)
.replace(/^( {4}release-date:) \S+$/m, `$1 ${releaseDate}`)
.replace(/^( {4}version-node-major:) \S+$/m, `$1 ${q(nodeVersion.split('.')[0])}`)
.replace(/^( {4}version-node:) \S+$/m, `$1 ${q(nodeVersion)}`)
.replace(/^( {4}version-npm:) \S+$/m, `$1 ${q(npmVersion)}`)
return fsp.writeFile(DOCS_CONFIG_FILE, contents, 'utf8')
}),
fsp.readFile(README_FILE, 'utf8').then((contents) => {
contents = contents
.replace(/^(:version-node-major:) \S+$/m, `$1 ${nodeVersion.split('.')[0]}`)
.replace(/^(:version-node:) \S+$/m, `$1 ${nodeVersion}`)
return fsp.writeFile(README_FILE, contents, 'utf8')
}),
])
)
}
function updateChangelog (releaseDate) {
const releaseDateString = releaseDate.toISOString().split('T')[0]
return fsp
.readFile(CHANGELOG_FILE, 'utf8')
.then((changelog) =>
fsp.writeFile(
CHANGELOG_FILE,
changelog.replace(/^== (?:(Unreleased)|\d.*)$/m, (currentLine, replace) => {
const newLine = `== ${VERSION} (${releaseDateString})`
return replace ? newLine : [newLine, '_No changes since previous release._', currentLine].join('\n\n')
})
)
return fsp.readFile(CHANGELOG_FILE, 'utf8').then((changelog) =>
fsp.writeFile(
CHANGELOG_FILE,
changelog.replace(/^== (?:(Unreleased)|\d.*)$/m, (currentLine, replace) => {
const newLine = `== ${VERSION} (${releaseDate})`
return replace ? newLine : [newLine, '_No changes since previous release._', currentLine].join('\n\n')
})
)
.then(() => promisify(exec)('git add CHANGELOG.adoc', { cwd: PROJECT_ROOT_DIR }))
)
}
function updatePackageLock () {
......@@ -86,9 +127,7 @@ function updatePackageLock () {
}
}
writes.push(fsp.writeFile(PACKAGE_LOCK_FILE, JSON.stringify(packageLock, undefined, 2) + '\n', 'utf8'))
return Promise.all(writes).then(() =>
promisify(exec)(`git add ${gitAddPaths.join(' ')}`, { cwd: PROJECT_ROOT_DIR })
)
return Promise.all(writes)
})
}
......@@ -97,8 +136,8 @@ function q (str) {
}
;(async () => {
const now = getCurrentDate()
await updateDocsConfig()
await updateChangelog(now)
const releaseDate = getCurrentDate().toISOString().split('T')[0]
await updateDocsDesc(releaseDate)
await updateChangelog(releaseDate)
await updatePackageLock()
})()
......@@ -16,6 +16,7 @@
"deps": "node npm/validate-deps.js",
"format": "node npm/format.js packages/${npm_config_package},npm",
"lint": "eslint \"{docs,npm}/**/*.js\" \"packages/${npm_config_package:-*}/{lib,test}/**/*.js\"",
"prepareForDev": "node npm/prepare-for-dev.js",
"test": "_mocha",
"version": "node npm/version.js"
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment