diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 567ebff..32eba91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - run: bash -n scripts/*.sh - run: ./scripts/check-docs.sh compile-tests: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 3ff48bf..b9da6e9 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ Read the [documentation index](docs/README.md) for template syntax, async web re ## Development and releases ```bash +./scripts/bump-version.sh vMAJOR.MINOR.PATCH +# Replace the generated CHANGELOG TODO with the release summary. ./scripts/test.sh compile --platform esp8266 ./scripts/test.sh compile --platform esp32 ./scripts/check-docs.sh diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 5bb508e..d815511 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -2,9 +2,11 @@ Released applications should use a public Git tag. While changing DFTE with a sibling library, select a local `symlink://` or `file://` dependency from an ignored PlatformIO override rather than changing tracked application dependencies. -Before a release, update `library.json`, `CHANGELOG.md`, and the relevant guides, then run: +Start a release with `bump-version.sh`. It updates package metadata and canonical installation snippets, then creates the changelog section. Replace its generated TODO with the release summary and update any behavioural documentation before running: ```bash +./scripts/bump-version.sh vMAJOR.MINOR.PATCH +# Replace the generated CHANGELOG TODO with the release summary. ./scripts/check-docs.sh ./scripts/test.sh compile --platform esp8266 ./scripts/test.sh compile --platform esp32 diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..8cca1d7 --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + echo "Usage: $0 vMAJOR.MINOR.PATCH" >&2 + exit 2 +} + +tag="${1:-}" +[[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || usage + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +version="${tag#v}" +repo_url="https://github.com/alexhopeoconnor/DFTE.git" +reference_files=(README.md) + +current_version="$(sed -n 's/.*"version": "\([^"]*\)".*/\1/p' "$root/library.json" | head -n 1)" +[[ "$current_version" != "$version" ]] || { + echo "library.json already declares $version; choose a new version." >&2 + exit 1 +} +grep -q "^## $version$" "$root/CHANGELOG.md" && { + echo "CHANGELOG.md already has a $version section; choose a new version." >&2 + exit 1 +} + +sed -i -E '0,/"version": "[0-9]+\.[0-9]+\.[0-9]+"/s//"version": "'"$version"'"/' "$root/library.json" +for file in "${reference_files[@]}"; do + sed -i -E "s|${repo_url}#v[0-9]+\.[0-9]+\.[0-9]+|${repo_url}#v${version}|g" "$root/$file" +done + +temp_file="$(mktemp)" +trap 'rm -f "$temp_file"' EXIT +{ + IFS= read -r changelog_heading < "$root/CHANGELOG.md" + [[ "$changelog_heading" == "# Changelog" ]] || { + echo "CHANGELOG.md must begin with # Changelog" >&2 + exit 1 + } + printf '%s\n\n## %s\n\n- TODO: Describe this release.\n' "$changelog_heading" "$version" + tail -n +2 "$root/CHANGELOG.md" +} > "$temp_file" +mv "$temp_file" "$root/CHANGELOG.md" + +echo "Updated DFTE declarations and canonical install references to $tag." +echo "Replace the generated changelog TODO with the release summary, then run scripts/check-docs.sh and scripts/prepare-release.sh $tag." diff --git a/scripts/prepare-release.sh b/scripts/prepare-release.sh index 32977bb..af495f9 100755 --- a/scripts/prepare-release.sh +++ b/scripts/prepare-release.sh @@ -32,12 +32,30 @@ if ! grep -q "^## ${version}$" "$root/CHANGELOG.md"; then exit 1 fi +if awk -v heading="## $version" ' + $0 == heading { found = 1; next } + found && /^## / { exit } + found { print } +' "$root/CHANGELOG.md" | grep -Fq 'TODO: Describe this release.'; then + echo "CHANGELOG.md still has the generated TODO for $version" >&2 + exit 1 +fi +repo_url="https://github.com/alexhopeoconnor/DFTE.git" +validate_reference() { + local file="$1" + local reference_count + reference_count="$(grep -F "$repo_url#v" "$root/$file" | wc -l)" + [[ "$reference_count" -eq 1 ]] || { echo "$file must contain exactly one canonical release reference" >&2; exit 1; } + grep -Fq "$repo_url#$tag" "$root/$file" || { echo "$file does not reference $tag" >&2; exit 1; } +} +validate_reference README.md + git -C "$root" diff --check package_dir="$(mktemp -d)" trap 'rm -rf "$package_dir"' EXIT pio pkg pack "$root" --output "$package_dir/package.tar.gz" >/dev/null -echo "Validated PlatformIO package for $tag" +echo "Validated release metadata and PlatformIO package for $tag" if [[ "${2:-}" == "--tag" ]]; then git -C "$root" diff --quiet