From 2b3c181eaa73ca27b0cfa3fd12148d6b69e35311 Mon Sep 17 00:00:00 2001 From: Daniel Robbins Date: Sun, 2 Nov 2025 11:54:40 -0500 Subject: [PATCH] Release 2.9.8: Fix tarball to include all necessary files - Fixed release tarball generation to include bash completion script, Makefile, source files, and other essential components - Improved tarball generation to use git archive as source of truth, eliminating manual file inventory - Added bash completion information to man page - GitHub workflow plumbing work for new /dist tarball location, Makefile and CI fixes --- .github/workflows/release.yml | 7 ++-- .gitignore | 2 +- ChangeLog.md | 18 ++++++++++ Makefile | 26 +++++++-------- VERSION | 2 +- docs/release-steps.md | 14 ++++---- keychain.pod | 6 ++++ scripts/release-create.sh | 2 +- scripts/release-orchestrate.sh | 60 +++++++++++++++++++++------------- scripts/release-refresh.sh | 2 +- 10 files changed, 90 insertions(+), 49 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7bc2f5a..c8df6f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,9 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Fix git ownership for container + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" - name: Verify tag/version consistency id: ver run: | @@ -34,7 +37,7 @@ jobs: - name: Build run: | make clean - make keychain-$(cat VERSION).tar.gz + make dist/keychain-$(cat VERSION).tar.gz - name: Test space-in-home handling run: | ver=$(cat VERSION) @@ -52,7 +55,7 @@ jobs: with: name: keychain-${{ steps.ver.outputs.version }}-artifacts path: | - keychain-${{ steps.ver.outputs.version }}.tar.gz + dist/keychain-${{ steps.ver.outputs.version }}.tar.gz keychain keychain.1 .release-notes.md diff --git a/.gitignore b/.gitignore index 6b3058a..e2a4e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ keychain.txt keychain.spec .specstory/ .ci-artifacts*/ -/keychain-*.tar.gz +dist/ diff --git a/ChangeLog.md b/ChangeLog.md index add5a44..ffe46e3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,23 @@ # ChangeLog for Keychain - https://github.com/danielrobbins/keychain +## keychain 2.9.8 (2 Nov 2025) + +This release fixes the release tarball to include all necessary files for building and using keychain. + +Bug fixes: + +* Fixed release tarball generation to include bash completion script (`completions/keychain.bash`), + Makefile, source files, and other essential components. Previous release (2.9.7) tarball was + missing these files. +* Improved tarball generation to use `git archive` as source of truth, eliminating manual file + inventory and preventing future omissions. +* Updated release logic to use `dist/` directory for archive generation. GitHub workflow plumbing + work for new `/dist` tarball location, associated `Makefile` and CI fixes. + +Documentation: + +* Added bash completion information to keychain man page (NOTES section). + ## keychain 2.9.7 (31 Oct 2025) This release fixes critical issues with spaces in HOME directories and usernames, and adds official Git Bash on Windows compatibility. diff --git a/Makefile b/Makefile index 16ef5f0..42a0410 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,6 @@ Y ?= $(shell date +'%Y') PREFIX ?= /usr/local COMPLETIONSDIR ?= $(PREFIX)/share/bash-completion/completions -TARBALL_CONTENTS=keychain README.md ChangeLog.md COPYING.txt MAINTAINERS.txt keychain.pod keychain.1 keychain.spec - all: keychain.1 keychain keychain.spec .PHONY : tmpclean @@ -23,10 +21,10 @@ tmpclean: clean: tmpclean rm -rf keychain.1 keychain keychain.spec -keychain.spec: keychain.spec.in keychain.sh +keychain.spec: keychain.spec.in keychain.sh VERSION sed 's/KEYCHAIN_VERSION/$V/' keychain.spec.in > keychain.spec -keychain.1: keychain.pod keychain.sh +keychain.1: keychain.pod keychain.sh VERSION pod2man --name=keychain --release=$V \ --center='https://github.com/danielrobbins/keychain' \ keychain.pod keychain.1 @@ -61,20 +59,22 @@ keychain: keychain.sh keychain.txt VERSION MAINTAINERS.txt keychain.txt: keychain.pod pod2text keychain.pod keychain.txt -keychain-$V.tar.gz: $(TARBALL_CONTENTS) - mkdir keychain-$V - cp $(TARBALL_CONTENTS) keychain-$V - /bin/tar czvf keychain-$V.tar.gz keychain-$V - rm -rf keychain-$V - ls -l keychain-$V.tar.gz +dist/keychain-$V.tar.gz: keychain keychain.1 keychain.spec + mkdir -p dist + rm -rf dist/keychain-$V + git archive --format=tar --prefix=keychain-$V/ HEAD | tar -xf - -C dist/ + cp keychain keychain.1 keychain.spec dist/keychain-$V/ + tar -C dist -czf dist/keychain-$V.tar.gz keychain-$V + rm -rf dist/keychain-$V + ls -l dist/keychain-$V.tar.gz # --- Release Automation Helpers --- .PHONY: release release-refresh -RELEASE_ASSETS=keychain-$V.tar.gz keychain keychain.1 +RELEASE_ASSETS=dist/keychain-$V.tar.gz keychain keychain.1 # "release" will orchestrate a tagged release with CI artifact validation & confirmation. -release: $(RELEASE_ASSETS) +release: clean $(RELEASE_ASSETS) @echo "Orchestrating release $(V)"; \ if [ -z "$$GITHUB_TOKEN" ]; then \ echo "GITHUB_TOKEN not set; export a repo-scoped token to proceed." >&2; exit 1; \ @@ -82,7 +82,7 @@ release: $(RELEASE_ASSETS) ./scripts/release-orchestrate.sh create $(V) # "release-refresh" updates assets of an existing GitHub release (e.g. fixups) with CI validation. -release-refresh: $(RELEASE_ASSETS) +release-refresh: clean $(RELEASE_ASSETS) @echo "Orchestrating release-refresh $(V)"; \ if [ -z "$$GITHUB_TOKEN" ]; then \ echo "GITHUB_TOKEN not set; export a repo-scoped token to proceed." >&2; exit 1; \ diff --git a/VERSION b/VERSION index 1020118..d8589d1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.9.7 +2.9.8 diff --git a/docs/release-steps.md b/docs/release-steps.md index dacf84c..f20d391 100644 --- a/docs/release-steps.md +++ b/docs/release-steps.md @@ -17,7 +17,7 @@ This document defines the standard release process. Releases use **numeric tags ## 3. Build Artifacts Manual build (optional; `make release` now auto-rebuilds prerequisites): ``` -make clean && make keychain-$(cat VERSION).tar.gz +make clean && make dist/keychain-$(cat VERSION).tar.gz ``` `make release` or `make release-refresh` will ensure these artifacts exist automatically. @@ -26,7 +26,7 @@ Artifacts: - `keychain.1` (man page) - `keychain.spec` - `keychain.txt` -- `keychain-.tar.gz` +- `dist/keychain-.tar.gz` ## 4. Local Sanity Tests ``` @@ -62,7 +62,7 @@ You will see: 3. Normalized comparison phase (LOCAL vs CI build): * `keychain` – raw sha256 digest compare. * `keychain.1` – raw hash first; if different, re-compare with the Pod::Man auto-generated first line stripped. A normalized match counts as a match (header differences ignored). - * `keychain-.tar.gz` – unpack both tarballs; compare sorted file list and per-file sha256 (man page internally also normalized on first line). Blob-level tar/gzip metadata differences (mtime, uid, compression variance) are ignored if internal contents match. + * `dist/keychain-.tar.gz` – unpack both tarballs; compare sorted file list and per-file sha256 (man page internally also normalized on first line). Blob-level tar/gzip metadata differences (mtime, uid, compression variance) are ignored if internal contents match. Outcome: - If all artifacts match (raw or normalized) -> Release uses the CI artifact files directly (local artifacts remain untouched for auditing). - If any real content mismatch exists -> Abort. @@ -92,7 +92,7 @@ Both require `GITHUB_TOKEN` (repo scope) exported in the environment. If you forgot something (docs only, same version): ``` # Edit ChangeLog.md (if you need to adjust text; refresh will regenerate release notes from current ChangeLog plus provenance.) -# Rebuild if needed (optional): make keychain-$(cat VERSION).tar.gz +# Rebuild if needed (optional): make dist/keychain-$(cat VERSION).tar.gz make release-refresh ``` You will again get CI fetch attempt, comparisons, preview, and prompt. @@ -121,16 +121,16 @@ awk -v ver="$version" '/^## keychain 'ver' /{f=1;print;next} /^## keychain /&&f ## 13. Verification Matrix | Item | Location | Must Match | -|------|----------|-----------| +|------|----------|------------| | Version tag | git tag | `VERSION` file | | Wrapper script | `keychain` | contains version string | | Man page header | `keychain.1` | version/date/center URL | -| Tarball name | `keychain-.tar.gz` | version | +| Tarball name | `dist/keychain-.tar.gz` | version | ## 14. Minimal Quick Release Recap ``` $EDITOR ChangeLog.md VERSION -make clean && make keychain-$(cat VERSION).tar.gz +make clean && make dist/keychain-$(cat VERSION).tar.gz ./keychain --version git tag -s $(cat VERSION) -m "$(cat VERSION)" git push && git push --tags diff --git a/keychain.pod b/keychain.pod index 985726a..dd2c73f 100644 --- a/keychain.pod +++ b/keychain.pod @@ -737,5 +737,11 @@ Keychain was created and is currently maintained by Daniel Robbins. To report a bug or request an enhancement, use the issue tracker at L. +Keychain includes bash completion support for command-line options, SSH keys, +GPG keys, and extended mode prefixes (C, C, C). The +completion script is included in the source tarball at +C. For installation instructions, see the README +file or run C. + The former Funtoo Linux wiki page is preserved only as an historical reference: L. diff --git a/scripts/release-create.sh b/scripts/release-create.sh index f8c35d0..a4f8f26 100755 --- a/scripts/release-create.sh +++ b/scripts/release-create.sh @@ -13,7 +13,7 @@ notes_file=$(mktemp) # Artifact path vars (provided by orchestrator if using CI artifacts) ASSET_KEYCHAIN=${KEYCHAIN_ASSET_KEYCHAIN:-keychain} ASSET_MAN=${KEYCHAIN_ASSET_MAN:-keychain.1} -ASSET_TARBALL=${KEYCHAIN_ASSET_TARBALL:-keychain-$VER.tar.gz} +ASSET_TARBALL=${KEYCHAIN_ASSET_TARBALL:-dist/keychain-$VER.tar.gz} echo "Creating release $VER" json=$(mktemp) diff --git a/scripts/release-orchestrate.sh b/scripts/release-orchestrate.sh index e614dce..028f131 100755 --- a/scripts/release-orchestrate.sh +++ b/scripts/release-orchestrate.sh @@ -35,9 +35,9 @@ if [ "$MODE" = create ]; then fi # 1. Ensure local assets exist -for f in keychain-$VER.tar.gz keychain keychain.1; do +for f in dist/keychain-$VER.tar.gz keychain keychain.1; do [ -f "$f" ] || { echo "Missing local asset: $f" >&2; exit 1; } - done +done # 2. Fetch CI artifacts (MANDATORY) CI_DIR=".ci-artifacts-$VER" @@ -89,6 +89,9 @@ compare_tar_content() { h2=$(tail -n +2 "$tmp_ci/$root/$rel" | sha256sum | awk '{print $1}') if [ "$h1" != "$h2" ]; then echo " keychain-$VER.tar.gz: content mismatch in $rel (beyond header)" >&2 + echo "--- LOCAL: $rel" >&2 + echo "+++ CI: $rel" >&2 + diff -u <(tail -n +2 "$tmp_local/$root/$rel") <(tail -n +2 "$tmp_ci/$root/$rel") | head -20 >&2 mismatch=1 fi else @@ -96,6 +99,9 @@ compare_tar_content() { h2=$(sha256sum "$tmp_ci/$root/$rel" | awk '{print $1}') if [ "$h1" != "$h2" ]; then echo " keychain-$VER.tar.gz: content mismatch in $rel" >&2 + echo "--- LOCAL: $rel" >&2 + echo "+++ CI: $rel" >&2 + diff -u "$tmp_local/$root/$rel" "$tmp_ci/$root/$rel" | head -20 >&2 mismatch=1 fi fi @@ -111,48 +117,56 @@ EOF } # Process artifacts with specialized logic -for artifact in keychain keychain.1 keychain-$VER.tar.gz; do - if [ ! -f "$CI_DIR/$artifact" ]; then - printf ' %-20s CI copy missing; comparison failed (abort)\n' "$artifact" +for artifact in keychain keychain.1 dist/keychain-$VER.tar.gz; do + # Get basename for CI comparison + basename_artifact=$(basename "$artifact") + # Determine CI path (tarball is in dist/ subdirectory) + if [ "$basename_artifact" = "keychain-$VER.tar.gz" ]; then + ci_artifact_path="$CI_DIR/dist/$basename_artifact" + else + ci_artifact_path="$CI_DIR/$basename_artifact" + fi + if [ ! -f "$ci_artifact_path" ]; then + printf ' %-20s CI copy missing; comparison failed (abort)\n' "$basename_artifact" diff_flag=1 continue fi - case "$artifact" in + case "$basename_artifact" in keychain) - L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$CI_DIR/$artifact") + L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$ci_artifact_path") if [ "$L" = "$R" ]; then - printf ' %-20s %s (match)\n' "$artifact" "$L" + printf ' %-20s %s (match)\n' "$basename_artifact" "$L" else - printf ' %-20s LOCAL %s != CI %s *DIFF*\n' "$artifact" "$L" "$R" + printf ' %-20s LOCAL %s != CI %s *DIFF*\n' "$basename_artifact" "$L" "$R" diff_flag=1 fi ;; keychain.1) # Direct hash first - L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$CI_DIR/$artifact") + L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$ci_artifact_path") if [ "$L" = "$R" ]; then - printf ' %-20s %s (match)\n' "$artifact" "$L" + printf ' %-20s %s (match)\n' "$basename_artifact" "$L" else # Normalize and compare ignoring Pod::Man header line. - if diff -u <(tail -n +2 "$artifact") <(tail -n +2 "$CI_DIR/$artifact") >/dev/null 2>&1; then - printf ' %-20s (normalized match ignoring Pod::Man header)\n' "$artifact" + if diff -u <(tail -n +2 "$artifact") <(tail -n +2 "$ci_artifact_path") >/dev/null 2>&1; then + printf ' %-20s (normalized match ignoring Pod::Man header)\n' "$basename_artifact" else - printf ' %-20s LOCAL %s != CI %s *DIFF* (content mismatch beyond header)\n' "$artifact" "$L" "$R" + printf ' %-20s LOCAL %s != CI %s *DIFF* (content mismatch beyond header)\n' "$basename_artifact" "$L" "$R" diff_flag=1 fi fi ;; "keychain-$VER.tar.gz") - if compare_tar_content "$artifact" "$CI_DIR/$artifact"; then + if compare_tar_content "$artifact" "$ci_artifact_path"; then # If tar blob hash matches display it; else note normalized match. - L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$CI_DIR/$artifact") + L=$(calc_sha256 "$artifact"); R=$(calc_sha256 "$ci_artifact_path") if [ "$L" = "$R" ]; then - printf ' %-20s %s (match)\n' "$artifact" "$L" + printf ' %-20s %s (match)\n' "$basename_artifact" "$L" else - printf ' %-20s (content match; tar/gzip metadata differ)\n' "$artifact" + printf ' %-20s (content match; tar/gzip metadata differ)\n' "$basename_artifact" fi else - printf ' %-20s *CONTENT DIFF* (see above messages)\n' "$artifact" + printf ' %-20s *CONTENT DIFF* (see above messages)\n' "$basename_artifact" diff_flag=1 fi ;; @@ -168,8 +182,8 @@ if [ $diff_flag -ne 0 ]; then echo " VER=$VER; CI_DIR=$CI_DIR" >&2 echo " diff -u keychain \"$CI_DIR/keychain\"" >&2 echo " diff -u keychain.1 \"$CI_DIR/keychain.1\"" >&2 - echo " diff -u <(tar tzf keychain-$VER.tar.gz | sort) <(tar tzf $CI_DIR/keychain-$VER.tar.gz | sort)" >&2 - echo " mkdir -p /tmp/kc-local /tmp/kc-ci && tar xzf keychain-$VER.tar.gz -C /tmp/kc-local && tar xzf $CI_DIR/keychain-$VER.tar.gz -C /tmp/kc-ci && diff -ru /tmp/kc-local/keychain-$VER /tmp/kc-ci/keychain-$VER" >&2 + echo " diff -u <(tar tzf dist/keychain-$VER.tar.gz | sort) <(tar tzf $CI_DIR/dist/keychain-$VER.tar.gz | sort)" >&2 + echo " mkdir -p /tmp/kc-local /tmp/kc-ci && tar xzf dist/keychain-$VER.tar.gz -C /tmp/kc-local && tar xzf $CI_DIR/dist/keychain-$VER.tar.gz -C /tmp/kc-ci && diff -ru /tmp/kc-local/keychain-$VER /tmp/kc-ci/keychain-$VER" >&2 echo if [ "${KEYCHAIN_FORCE_LOCAL:-}" = 1 ]; then echo "KEYCHAIN_FORCE_LOCAL=1 set: proceeding using LOCAL artifacts despite mismatches." >&2 @@ -182,13 +196,13 @@ fi if [ "${KEYCHAIN_FORCE_LOCAL:-}" = 1 ]; then KEYCHAIN_ASSET_KEYCHAIN="keychain" KEYCHAIN_ASSET_MAN="keychain.1" - KEYCHAIN_ASSET_TARBALL="keychain-$VER.tar.gz" + KEYCHAIN_ASSET_TARBALL="dist/keychain-$VER.tar.gz" echo "Source selection: USING LOCAL artifacts (override)." >&2 else # All artifacts matched (raw or normalized) -> use CI versions KEYCHAIN_ASSET_KEYCHAIN="$CI_DIR/keychain" KEYCHAIN_ASSET_MAN="$CI_DIR/keychain.1" - KEYCHAIN_ASSET_TARBALL="$CI_DIR/keychain-$VER.tar.gz" + KEYCHAIN_ASSET_TARBALL="$CI_DIR/dist/keychain-$VER.tar.gz" echo "Source selection: USING CI artifacts (canonical)." >&2 fi export KEYCHAIN_ASSET_KEYCHAIN KEYCHAIN_ASSET_MAN KEYCHAIN_ASSET_TARBALL diff --git a/scripts/release-refresh.sh b/scripts/release-refresh.sh index 28234b0..d947726 100755 --- a/scripts/release-refresh.sh +++ b/scripts/release-refresh.sh @@ -22,7 +22,7 @@ done echo "Uploading replacement assets..." ASSET_KEYCHAIN=${KEYCHAIN_ASSET_KEYCHAIN:-keychain} ASSET_MAN=${KEYCHAIN_ASSET_MAN:-keychain.1} -ASSET_TARBALL=${KEYCHAIN_ASSET_TARBALL:-keychain-$VER.tar.gz} +ASSET_TARBALL=${KEYCHAIN_ASSET_TARBALL:-dist/keychain-$VER.tar.gz} # (Note: By default we do not modify existing release notes. Set KEYCHAIN_UPDATE_NOTES=1 to rebuild.)