mirror of
https://github.com/metabarcoding/obitools4.git
synced 2026-03-25 05:20:52 +00:00
Refactor jjpush workflow and enhance release notes generation
Split the jjpush target into multiple sub-targets (jjpush-describe, jjpush-bump, jjpush-push, jjpush-tag) for better modularity and control. Enhance release notes generation by: - Using git log with full commit messages instead of GitHub API for pre-release mode - Adding robust JSON parsing with fallbacks for release notes - Including detailed installation instructions in release notes - Supporting both pre-release and published release modes Update release_notes.sh to handle pre-release mode, improve commit message fetching, and add installation section to release notes. Add .PHONY declarations for new sub-targets.
This commit is contained in:
70
Makefile
70
Makefile
@@ -128,40 +128,58 @@ jjnew:
|
|||||||
@echo "$(GREEN)✓ New commit created$(NC)"
|
@echo "$(GREEN)✓ New commit created$(NC)"
|
||||||
|
|
||||||
jjpush:
|
jjpush:
|
||||||
@echo "$(YELLOW)→ Pushing commit to repository...$(NC)"
|
@$(MAKE) jjpush-describe
|
||||||
|
@$(MAKE) jjpush-bump
|
||||||
|
@$(MAKE) jjpush-push
|
||||||
|
@$(MAKE) jjpush-tag
|
||||||
|
@echo "$(GREEN)✓ Release complete$(NC)"
|
||||||
|
|
||||||
|
jjpush-describe:
|
||||||
@echo "$(BLUE)→ Documenting current commit...$(NC)"
|
@echo "$(BLUE)→ Documenting current commit...$(NC)"
|
||||||
@jj auto-describe
|
@jj auto-describe
|
||||||
|
|
||||||
|
jjpush-bump:
|
||||||
@echo "$(BLUE)→ Creating new commit for version bump...$(NC)"
|
@echo "$(BLUE)→ Creating new commit for version bump...$(NC)"
|
||||||
@jj new
|
@jj new
|
||||||
@previous_version=$$(cat version.txt); \
|
@$(MAKE) bump-version
|
||||||
$(MAKE) bump-version; \
|
@echo "$(BLUE)→ Documenting version bump commit...$(NC)"
|
||||||
version=$$(cat version.txt); \
|
@jj auto-describe
|
||||||
|
|
||||||
|
jjpush-push:
|
||||||
|
@echo "$(BLUE)→ Pushing commits...$(NC)"
|
||||||
|
@jj git push --change @
|
||||||
|
|
||||||
|
jjpush-tag:
|
||||||
|
@version=$$(cat version.txt); \
|
||||||
tag_name="Release_$$version"; \
|
tag_name="Release_$$version"; \
|
||||||
previous_tag="Release_$$previous_version"; \
|
echo "$(BLUE)→ Generating release notes for $$tag_name...$(NC)"; \
|
||||||
echo "$(BLUE)→ Documenting version bump commit...$(NC)"; \
|
release_message="Release $$version"; \
|
||||||
jj auto-describe; \
|
|
||||||
echo "$(BLUE)→ Generating release notes from $$previous_tag to current commit...$(NC)"; \
|
|
||||||
if command -v orla >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then \
|
if command -v orla >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then \
|
||||||
release_json=$$(ORLA_MAX_TOOL_CALLS=50 jj log -r "$$previous_tag::@" -T 'commit_id.short() ++ " " ++ description' | \
|
previous_tag=$$(git describe --tags --abbrev=0 --match 'Release_*' HEAD^ 2>/dev/null); \
|
||||||
orla agent -m ollama:qwen3-coder-next:latest \
|
if [ -z "$$previous_tag" ]; then \
|
||||||
"Summarize the following commits into a GitHub release note for version $$version. Ignore commits related to version bumps, .gitignore changes, or any internal housekeeping that is irrelevant to end users. Describe each user-facing change precisely without exposing code. Eliminate redundancy. Output strictly valid JSON with no surrounding text, using this exact schema: {\"title\": \"<short release title>\", \"body\": \"<detailed markdown release notes>\"}"); \
|
echo "$(YELLOW)⚠ No previous Release tag found, skipping release notes$(NC)"; \
|
||||||
release_json=$$(echo "$$release_json" | sed -n '/^{/,/^}/p'); \
|
|
||||||
release_title=$$(echo "$$release_json" | jq -r '.title // empty') ; \
|
|
||||||
release_body=$$(echo "$$release_json" | jq -r '.body // empty') ; \
|
|
||||||
if [ -n "$$release_title" ] && [ -n "$$release_body" ]; then \
|
|
||||||
release_message="$$release_title"$$'\n\n'"$$release_body"; \
|
|
||||||
else \
|
else \
|
||||||
echo "$(YELLOW)⚠ JSON parsing failed, falling back to raw output$(NC)"; \
|
raw_output=$$(git log --format="%h %B" "$$previous_tag..HEAD" | \
|
||||||
release_message="Release $$version"$$'\n\n'"$$release_json"; \
|
ORLA_MAX_TOOL_CALLS=50 orla agent -m ollama:qwen3-coder-next:latest \
|
||||||
|
"Summarize the following commits into a GitHub release note for version $$version. Ignore commits related to version bumps, .gitignore changes, or any internal housekeeping that is irrelevant to end users. Describe each user-facing change precisely without exposing code. Eliminate redundancy. Output strictly valid JSON with no surrounding text, using this exact schema: {\"title\": \"<short release title>\", \"body\": \"<detailed markdown release notes>\"}" 2>/dev/null) || true; \
|
||||||
|
if [ -n "$$raw_output" ]; then \
|
||||||
|
sanitized=$$(echo "$$raw_output" | sed -n '/^{/,/^}/p' | tr -d '\000-\011\013-\014\016-\037'); \
|
||||||
|
release_title=$$(echo "$$sanitized" | jq -r '.title // empty' 2>/dev/null) ; \
|
||||||
|
release_body=$$(echo "$$sanitized" | jq -r '.body // empty' 2>/dev/null) ; \
|
||||||
|
if [ -n "$$release_title" ] && [ -n "$$release_body" ]; then \
|
||||||
|
release_message="$$release_title"$$'\n\n'"$$release_body"; \
|
||||||
|
else \
|
||||||
|
echo "$(YELLOW)⚠ JSON parsing failed, using default release message$(NC)"; \
|
||||||
|
fi; \
|
||||||
|
fi; \
|
||||||
fi; \
|
fi; \
|
||||||
else \
|
|
||||||
release_message="Release $$version"; \
|
|
||||||
fi; \
|
fi; \
|
||||||
echo "$(BLUE)→ Pushing commits and creating tag $$tag_name...$(NC)"; \
|
install_section=$$'\n## Installation\n\n### Pre-built binaries\n\nDownload the appropriate archive for your system from the\n[release assets](https://github.com/metabarcoding/obitools4/releases/tag/Release_'"$$version"')\nand extract it:\n\n#### Linux (AMD64)\n```bash\ntar -xzf obitools4_'"$$version"'_linux_amd64.tar.gz\n```\n\n#### Linux (ARM64)\n```bash\ntar -xzf obitools4_'"$$version"'_linux_arm64.tar.gz\n```\n\n#### macOS (Intel)\n```bash\ntar -xzf obitools4_'"$$version"'_darwin_amd64.tar.gz\n```\n\n#### macOS (Apple Silicon)\n```bash\ntar -xzf obitools4_'"$$version"'_darwin_arm64.tar.gz\n```\n\nAll OBITools4 binaries are included in each archive.\n\n### From source\n\nYou can also compile and install OBITools4 directly from source using the\ninstallation script:\n\n```bash\ncurl -L https://raw.githubusercontent.com/metabarcoding/obitools4/master/install_obitools.sh | bash -s -- --version '"$$version"'\n```\n\nBy default binaries are installed in `/usr/local/bin`. Use `--install-dir` to\nchange the destination and `--obitools-prefix` to add a prefix to command names:\n\n```bash\ncurl -L https://raw.githubusercontent.com/metabarcoding/obitools4/master/install_obitools.sh | \\\n bash -s -- --version '"$$version"' --install-dir ~/local --obitools-prefix k\n```\n'; \
|
||||||
jj git push --change @; \
|
release_message="$$release_message$$install_section"; \
|
||||||
git tag -a "$$tag_name" -m "$$release_message" 2>/dev/null || echo "Tag $$tag_name already exists"; \
|
echo "$(BLUE)→ Creating tag $$tag_name...$(NC)"; \
|
||||||
git push origin "$$tag_name" 2>/dev/null || echo "Tag already pushed"
|
git tag -a "$$tag_name" -m "$$release_message" 2>/dev/null || echo "$(YELLOW)⚠ Tag $$tag_name already exists$(NC)"; \
|
||||||
@echo "$(GREEN)✓ Commits and tag pushed to repository$(NC)"
|
echo "$(BLUE)→ Pushing tag $$tag_name...$(NC)"; \
|
||||||
|
git push origin "$$tag_name" 2>/dev/null || echo "$(YELLOW)⚠ Tag push failed or already pushed$(NC)"
|
||||||
|
|
||||||
jjfetch:
|
jjfetch:
|
||||||
@echo "$(YELLOW)→ Pulling latest commits...$(NC)"
|
@echo "$(YELLOW)→ Pulling latest commits...$(NC)"
|
||||||
@@ -169,5 +187,5 @@ jjfetch:
|
|||||||
@jj new master@origin
|
@jj new master@origin
|
||||||
@echo "$(GREEN)✓ Latest commits pulled$(NC)"
|
@echo "$(GREEN)✓ Latest commits pulled$(NC)"
|
||||||
|
|
||||||
.PHONY: all obitools update-deps obitests githubtests jjnew jjpush jjfetch bump-version .FORCE
|
.PHONY: all obitools update-deps obitests githubtests jjnew jjpush jjpush-describe jjpush-bump jjpush-push jjpush-tag jjfetch bump-version .FORCE
|
||||||
.FORCE:
|
.FORCE:
|
||||||
|
|||||||
167
release_notes.sh
167
release_notes.sh
@@ -21,6 +21,74 @@ LLM_MODEL="ollama:qwen3-coder-next:latest"
|
|||||||
|
|
||||||
die() { echo "Error: $*" >&2; exit 1; }
|
die() { echo "Error: $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
next_patch() {
|
||||||
|
local v="$1"
|
||||||
|
local major minor patch
|
||||||
|
major=$(echo "$v" | cut -d. -f1)
|
||||||
|
minor=$(echo "$v" | cut -d. -f2)
|
||||||
|
patch=$(echo "$v" | cut -d. -f3)
|
||||||
|
echo "${major}.${minor}.$(( patch + 1 ))"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Strip "pre-" prefix to get the bare version number for installation section
|
||||||
|
bare_version() {
|
||||||
|
echo "$1" | sed 's/^pre-//'
|
||||||
|
}
|
||||||
|
|
||||||
|
installation_section() {
|
||||||
|
local v
|
||||||
|
v=$(bare_version "$1")
|
||||||
|
cat <<INSTALL_EOF
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Pre-built binaries
|
||||||
|
|
||||||
|
Download the appropriate archive for your system from the
|
||||||
|
[release assets](https://github.com/metabarcoding/obitools4/releases/tag/Release_${v})
|
||||||
|
and extract it:
|
||||||
|
|
||||||
|
#### Linux (AMD64)
|
||||||
|
\`\`\`bash
|
||||||
|
tar -xzf obitools4_${v}_linux_amd64.tar.gz
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
#### Linux (ARM64)
|
||||||
|
\`\`\`bash
|
||||||
|
tar -xzf obitools4_${v}_linux_arm64.tar.gz
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
#### macOS (Intel)
|
||||||
|
\`\`\`bash
|
||||||
|
tar -xzf obitools4_${v}_darwin_amd64.tar.gz
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
#### macOS (Apple Silicon)
|
||||||
|
\`\`\`bash
|
||||||
|
tar -xzf obitools4_${v}_darwin_arm64.tar.gz
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
All OBITools4 binaries are included in each archive.
|
||||||
|
|
||||||
|
### From source
|
||||||
|
|
||||||
|
You can also compile and install OBITools4 directly from source using the
|
||||||
|
installation script:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
curl -L https://raw.githubusercontent.com/metabarcoding/obitools4/master/install_obitools.sh | bash -s -- --version ${v}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
By default binaries are installed in \`/usr/local/bin\`. Use \`--install-dir\` to
|
||||||
|
change the destination and \`--obitools-prefix\` to add a prefix to command names:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
curl -L https://raw.githubusercontent.com/metabarcoding/obitools4/master/install_obitools.sh | \\
|
||||||
|
bash -s -- --version ${v} --install-dir ~/local --obitools-prefix k
|
||||||
|
\`\`\`
|
||||||
|
INSTALL_EOF
|
||||||
|
}
|
||||||
|
|
||||||
display_help() {
|
display_help() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $(basename "$0") [OPTIONS]
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
@@ -81,49 +149,74 @@ all_versions=$(fetch_versions)
|
|||||||
[ -z "$all_versions" ] && die "Could not fetch versions from GitHub"
|
[ -z "$all_versions" ] && die "Could not fetch versions from GitHub"
|
||||||
|
|
||||||
if [ -z "$VERSION" ]; then
|
if [ -z "$VERSION" ]; then
|
||||||
VERSION=$(echo "$all_versions" | head -1)
|
# ── Pre-release mode: local HEAD vs latest GitHub tag ──────────────────
|
||||||
echo "Using latest version: $VERSION" >&2
|
PRE_RELEASE=true
|
||||||
fi
|
previous_tag="Release_${latest_version}"
|
||||||
|
VERSION="pre-$(next_patch "$latest_version")"
|
||||||
|
|
||||||
tag_name="Release_${VERSION}"
|
echo "Pre-release mode: $previous_tag -> HEAD (as $VERSION)" >&2
|
||||||
|
|
||||||
# Verify the requested version exists
|
# Need to be in a git repo
|
||||||
if ! echo "$all_versions" | grep -qx "$VERSION"; then
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||||
die "Version $VERSION not found. Use -l to list available versions."
|
die "Not inside a git repository. Pre-release mode requires a local git repo."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Find the previous version (the one right after in the sorted-descending list)
|
# Check that the previous tag exists locally
|
||||||
previous_version=$(echo "$all_versions" | grep -A1 -x "$VERSION" | tail -1)
|
if ! git rev-parse "$previous_tag" >/dev/null 2>&1; then
|
||||||
|
echo "Tag $previous_tag not found locally, fetching..." >&2
|
||||||
|
git fetch --tags 2>/dev/null || true
|
||||||
|
if ! git rev-parse "$previous_tag" >/dev/null 2>&1; then
|
||||||
|
die "Tag $previous_tag not found locally or remotely"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$previous_version" = "$VERSION" ] || [ -z "$previous_version" ]; then
|
# Get local commits from the tag to HEAD (full messages)
|
||||||
previous_tag=""
|
commit_list=$(git log --format="%h %B" "${previous_tag}..HEAD" 2>/dev/null)
|
||||||
echo "No previous version found -- will include all commits for $tag_name" >&2
|
|
||||||
else
|
|
||||||
previous_tag="Release_${previous_version}"
|
|
||||||
echo "Generating notes: $previous_tag -> $tag_name" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Fetch commit messages between tags via GitHub compare API ────────────
|
if [ -z "$commit_list" ]; then
|
||||||
|
die "No local commits found since $previous_tag"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# ── Published release mode: between two GitHub tags ────────────────────
|
||||||
|
PRE_RELEASE=false
|
||||||
|
tag_name="Release_${VERSION}"
|
||||||
|
|
||||||
if [ -n "$previous_tag" ]; then
|
# Verify the requested version exists
|
||||||
commits_json=$(curl -sf "${GITHUB_API}/compare/${previous_tag}...${tag_name}")
|
if ! echo "$all_versions" | grep -qx "$VERSION"; then
|
||||||
if [ -z "$commits_json" ]; then
|
die "Version $VERSION not found. Use -l to list available versions."
|
||||||
die "Could not fetch commit comparison from GitHub"
|
fi
|
||||||
fi
|
|
||||||
commit_list=$(echo "$commits_json" \
|
|
||||||
| jq -r '.commits[] | (.sha[:8] + " " + (.commit.message | split("\n")[0]))' 2>/dev/null)
|
|
||||||
else
|
|
||||||
# First release: get commits up to this tag
|
|
||||||
commits_json=$(curl -sf "${GITHUB_API}/commits?sha=${tag_name}&per_page=50")
|
|
||||||
if [ -z "$commits_json" ]; then
|
|
||||||
die "Could not fetch commits from GitHub"
|
|
||||||
fi
|
|
||||||
commit_list=$(echo "$commits_json" \
|
|
||||||
| jq -r '.[] | (.sha[:8] + " " + (.commit.message | split("\n")[0]))' 2>/dev/null)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$commit_list" ]; then
|
# Find the previous version
|
||||||
die "No commits found between $previous_tag and $tag_name"
|
previous_version=$(echo "$all_versions" | grep -A1 -x "$VERSION" | tail -1)
|
||||||
|
|
||||||
|
if [ "$previous_version" = "$VERSION" ] || [ -z "$previous_version" ]; then
|
||||||
|
previous_tag=""
|
||||||
|
echo "No previous version found -- will include all commits for $tag_name" >&2
|
||||||
|
else
|
||||||
|
previous_tag="Release_${previous_version}"
|
||||||
|
echo "Generating notes: $previous_tag -> $tag_name" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch commit messages between tags via GitHub compare API
|
||||||
|
if [ -n "$previous_tag" ]; then
|
||||||
|
commits_json=$(curl -sf "${GITHUB_API}/compare/${previous_tag}...${tag_name}")
|
||||||
|
if [ -z "$commits_json" ]; then
|
||||||
|
die "Could not fetch commit comparison from GitHub"
|
||||||
|
fi
|
||||||
|
commit_list=$(echo "$commits_json" \
|
||||||
|
| jq -r '.commits[] | (.sha[:8] + " " + .commit.message)' 2>/dev/null)
|
||||||
|
else
|
||||||
|
commits_json=$(curl -sf "${GITHUB_API}/commits?sha=${tag_name}&per_page=50")
|
||||||
|
if [ -z "$commits_json" ]; then
|
||||||
|
die "Could not fetch commits from GitHub"
|
||||||
|
fi
|
||||||
|
commit_list=$(echo "$commits_json" \
|
||||||
|
| jq -r '.[] | (.sha[:8] + " " + .commit.message)' 2>/dev/null)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$commit_list" ]; then
|
||||||
|
die "No commits found between $previous_tag and $tag_name"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── LLM prompt (shared by context mode and summarization) ────────────────
|
# ── LLM prompt (shared by context mode and summarization) ────────────────
|
||||||
@@ -144,6 +237,7 @@ if [ "$RAW_MODE" = true ]; then
|
|||||||
echo "$commit_list" | while IFS= read -r line; do
|
echo "$commit_list" | while IFS= read -r line; do
|
||||||
echo "- ${line}"
|
echo "- ${line}"
|
||||||
done
|
done
|
||||||
|
installation_section "$VERSION"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -193,6 +287,7 @@ if [ -n "$release_title" ] && [ -n "$release_body" ]; then
|
|||||||
echo "# ${release_title}"
|
echo "# ${release_title}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "$release_body"
|
echo "$release_body"
|
||||||
|
installation_section "$VERSION"
|
||||||
else
|
else
|
||||||
echo "Warning: JSON parsing failed, falling back to raw mode" >&2
|
echo "Warning: JSON parsing failed, falling back to raw mode" >&2
|
||||||
exec "$0" -r -v "$VERSION"
|
exec "$0" -r -v "$VERSION"
|
||||||
|
|||||||
Reference in New Issue
Block a user