| #!/usr/bin/env bash |
| set -euo pipefail |
| shopt -s nullglob |
|
|
| |
| |
| echo "🔍 Auto-detecting version changes across all components..." |
|
|
| |
| CORE_NEEDS_RELEASE="false" |
| FRAMEWORK_NEEDS_RELEASE="false" |
| PLUGINS_NEED_RELEASE="false" |
| BIFROST_HTTP_NEEDS_RELEASE="false" |
| DOCKER_NEEDS_RELEASE="false" |
| CHANGED_PLUGINS="[]" |
|
|
| |
| CORE_VERSION=$(cat core/version) |
| FRAMEWORK_VERSION=$(cat framework/version) |
| TRANSPORT_VERSION=$(cat transports/version) |
|
|
| echo "📦 Current versions:" |
| echo " Core: $CORE_VERSION" |
| echo " Framework: $FRAMEWORK_VERSION" |
| echo " Transport: $TRANSPORT_VERSION" |
|
|
| START_FROM="none" |
|
|
| |
| echo "" |
| echo "🔧 Checking core..." |
| CORE_TAG="core/v${CORE_VERSION}" |
| if git rev-parse --verify "$CORE_TAG" >/dev/null 2>&1; then |
| echo " ⏭️ Tag $CORE_TAG already exists" |
| else |
| |
| CORE_BASE_VERSION=$(echo "$CORE_VERSION" | sed 's/-.*$//') |
| CORE_MAJOR_MINOR=$(echo "$CORE_BASE_VERSION" | cut -d. -f1,2) |
| echo " 🔍 Checking track: ${CORE_MAJOR_MINOR}.x" |
| |
| |
| LATEST_CORE_TAG=$(git tag -l "core/v${CORE_MAJOR_MINOR}.*" | sort -V | tail -1) |
| echo "🏷️ Latest core tag in track ${CORE_MAJOR_MINOR}.x: $LATEST_CORE_TAG" |
| if [ -z "$LATEST_CORE_TAG" ]; then |
| echo " ✅ First core release in track ${CORE_MAJOR_MINOR}.x: $CORE_VERSION" |
| CORE_NEEDS_RELEASE="true" |
| else |
| if [[ "$CORE_VERSION" == *"-"* ]]; then |
| |
| ALL_TAGS=$(git tag -l "core/v${CORE_MAJOR_MINOR}.*" | sort -V) |
| STABLE_TAGS=$(echo "$ALL_TAGS" | grep -v '\-') |
| PRERELEASE_TAGS=$(echo "$ALL_TAGS" | grep '\-' || true) |
| if [ -n "$STABLE_TAGS" ]; then |
| |
| LATEST_CORE_TAG=$(echo "$STABLE_TAGS" | tail -1) |
| echo "latest core tag (stable preferred): $LATEST_CORE_TAG" |
| else |
| |
| LATEST_CORE_TAG=$(echo "$PRERELEASE_TAGS" | tail -1) |
| echo "latest core tag (prerelease only): $LATEST_CORE_TAG" |
| fi |
| else |
| |
| LATEST_CORE_TAG=$(git tag -l "core/v${CORE_MAJOR_MINOR}.*" | grep -v '\-' | sort -V | tail -1) |
| echo "latest core tag (stable only): $LATEST_CORE_TAG" |
| fi |
| PREVIOUS_CORE_VERSION=${LATEST_CORE_TAG#core/v} |
| echo " 📋 Previous: $PREVIOUS_CORE_VERSION, Current: $CORE_VERSION" |
| |
| if [ "$(printf '%s\n' "$PREVIOUS_CORE_VERSION" "$CORE_VERSION" | sort -V | tail -1)" = "$CORE_VERSION" ] && [ "$PREVIOUS_CORE_VERSION" != "$CORE_VERSION" ]; then |
| echo " ✅ Core version incremented: $PREVIOUS_CORE_VERSION → $CORE_VERSION" |
| CORE_NEEDS_RELEASE="true" |
| else |
| echo " ⏭️ No core version increment" |
| fi |
| fi |
| fi |
|
|
| |
| echo "" |
| echo "📦 Checking framework..." |
| FRAMEWORK_TAG="framework/v${FRAMEWORK_VERSION}" |
| if git rev-parse --verify "$FRAMEWORK_TAG" >/dev/null 2>&1; then |
| echo " ⏭️ Tag $FRAMEWORK_TAG already exists" |
| else |
| |
| FRAMEWORK_BASE_VERSION=$(echo "$FRAMEWORK_VERSION" | sed 's/-.*$//') |
| FRAMEWORK_MAJOR_MINOR=$(echo "$FRAMEWORK_BASE_VERSION" | cut -d. -f1,2) |
| echo " 🔍 Checking track: ${FRAMEWORK_MAJOR_MINOR}.x" |
| |
| ALL_TAGS=$(git tag -l "framework/v${FRAMEWORK_MAJOR_MINOR}.*" | sort -V) |
| STABLE_TAGS=$(echo "$ALL_TAGS" | grep -v '\-') |
| PRERELEASE_TAGS=$(echo "$ALL_TAGS" | grep '\-' || true) |
| LATEST_FRAMEWORK_TAG="" |
| if [ -n "$STABLE_TAGS" ]; then |
| LATEST_FRAMEWORK_TAG=$(echo "$STABLE_TAGS" | tail -1) |
| echo "latest framework tag (stable preferred): $LATEST_FRAMEWORK_TAG" |
| else |
| LATEST_FRAMEWORK_TAG=$(echo "$PRERELEASE_TAGS" | tail -1) |
| echo "latest framework tag (prerelease only): $LATEST_FRAMEWORK_TAG" |
| fi |
| if [ -z "$LATEST_FRAMEWORK_TAG" ]; then |
| echo " ✅ First framework release in track ${FRAMEWORK_MAJOR_MINOR}.x: $FRAMEWORK_VERSION" |
| FRAMEWORK_NEEDS_RELEASE="true" |
| else |
| PREVIOUS_FRAMEWORK_VERSION=${LATEST_FRAMEWORK_TAG#framework/v} |
| echo " 📋 Previous: $PREVIOUS_FRAMEWORK_VERSION, Current: $FRAMEWORK_VERSION" |
| |
| if [ "$(printf '%s\n' "$PREVIOUS_FRAMEWORK_VERSION" "$FRAMEWORK_VERSION" | sort -V | tail -1)" = "$FRAMEWORK_VERSION" ] && [ "$PREVIOUS_FRAMEWORK_VERSION" != "$FRAMEWORK_VERSION" ]; then |
| echo " ✅ Framework version incremented: $PREVIOUS_FRAMEWORK_VERSION → $FRAMEWORK_VERSION" |
| FRAMEWORK_NEEDS_RELEASE="true" |
| else |
| echo " ⏭️ No framework version increment" |
| fi |
| fi |
| fi |
|
|
| |
| echo "" |
| echo "🔌 Checking plugins..." |
| PLUGIN_CHANGES=() |
|
|
| for plugin_dir in plugins/*/; do |
| if [ ! -d "$plugin_dir" ]; then |
| continue |
| fi |
|
|
| plugin_name=$(basename "$plugin_dir") |
| version_file="${plugin_dir}version" |
|
|
| if [ ! -f "$version_file" ]; then |
| echo " ⚠️ No version file for: $plugin_name" |
| continue |
| fi |
|
|
| current_version=$(cat "$version_file" | tr -d '\n\r') |
| if [ -z "$current_version" ]; then |
| echo " ⚠️ Empty version file for: $plugin_name" |
| continue |
| fi |
|
|
| tag_name="plugins/${plugin_name}/v${current_version}" |
| echo " 📦 Plugin: $plugin_name (v$current_version)" |
|
|
| if git rev-parse --verify "$tag_name" >/dev/null 2>&1; then |
| echo " ⏭️ Tag already exists" |
| continue |
| fi |
|
|
| |
| plugin_base_version=$(echo "$current_version" | sed 's/-.*$//') |
| plugin_major_minor=$(echo "$plugin_base_version" | cut -d. -f1,2) |
| echo " 🔍 Checking track: ${plugin_major_minor}.x" |
|
|
| if [[ "$current_version" == *"-"* ]]; then |
| |
| ALL_TAGS=$(git tag -l "plugins/${plugin_name}/v${plugin_major_minor}.*" | sort -V) |
| STABLE_TAGS=$(echo "$ALL_TAGS" | grep -v '\-' || true) |
| PRERELEASE_TAGS=$(echo "$ALL_TAGS" | grep '\-' || true) |
| |
| if [ -n "$STABLE_TAGS" ]; then |
| |
| LATEST_PLUGIN_TAG=$(echo "$STABLE_TAGS" | tail -1) |
| echo "latest plugin tag (stable preferred): $LATEST_PLUGIN_TAG" |
| else |
| |
| LATEST_PLUGIN_TAG=$(echo "$PRERELEASE_TAGS" | tail -1) |
| echo "latest plugin tag (prerelease only): $LATEST_PLUGIN_TAG" |
| fi |
| else |
| |
| LATEST_PLUGIN_TAG=$(git tag -l "plugins/${plugin_name}/v${plugin_major_minor}.*" | grep -v '\-' | sort -V | tail -1 || true) |
| echo "latest plugin tag (stable only): $LATEST_PLUGIN_TAG" |
| fi |
|
|
| latest_tag=$LATEST_PLUGIN_TAG |
| if [ -z "$latest_tag" ]; then |
| echo " ✅ First release in track ${plugin_major_minor}.x" |
| PLUGIN_CHANGES+=("$plugin_name") |
| else |
| previous_version=${latest_tag#plugins/${plugin_name}/v} |
| echo "previous version: $previous_version" |
| echo "current version: $current_version" |
| echo "latest tag: $latest_tag" |
| if [ "$(printf '%s\n' "$previous_version" "$current_version" | sort -V | tail -1)" = "$current_version" ] && [ "$previous_version" != "$current_version" ]; then |
| echo " ✅ Version incremented: $previous_version → $current_version" |
| PLUGIN_CHANGES+=("$plugin_name") |
| else |
| echo " ⏭️ No version increment" |
| fi |
| fi |
| done |
|
|
| if [ ${#PLUGIN_CHANGES[@]} -gt 0 ]; then |
| PLUGINS_NEED_RELEASE="true" |
| echo " 🔄 Plugins with changes: ${PLUGIN_CHANGES[*]}" |
| else |
| echo " ⏭️ No plugin changes detected" |
| fi |
|
|
| |
| echo "" |
| echo "🚀 Checking bifrost-http..." |
| TRANSPORT_TAG="transports/v${TRANSPORT_VERSION}" |
| DOCKER_TAG_EXISTS="false" |
|
|
| |
| GIT_TAG_EXISTS="false" |
| if git rev-parse --verify "$TRANSPORT_TAG" >/dev/null 2>&1; then |
| echo " ⏭️ Git tag $TRANSPORT_TAG already exists" |
| GIT_TAG_EXISTS="true" |
| fi |
|
|
| |
| echo " 🐳 Checking DockerHub for tag v${TRANSPORT_VERSION}..." |
| DOCKER_CHECK_RESPONSE=$(curl -s "https://registry.hub.docker.com/v2/repositories/maximhq/bifrost/tags/v${TRANSPORT_VERSION}/" 2>/dev/null || echo "") |
| if [ -n "$DOCKER_CHECK_RESPONSE" ] && echo "$DOCKER_CHECK_RESPONSE" | grep -q '"name"'; then |
| echo " ⏭️ Docker tag v${TRANSPORT_VERSION} already exists on DockerHub" |
| DOCKER_TAG_EXISTS="true" |
| else |
| echo " ❌ Docker tag v${TRANSPORT_VERSION} not found on DockerHub" |
| fi |
|
|
| |
| if [ "$GIT_TAG_EXISTS" = "true" ] && [ "$DOCKER_TAG_EXISTS" = "true" ]; then |
| echo " ⏭️ Both Git tag and Docker image exist - no release needed" |
| else |
| |
| TRANSPORT_BASE_VERSION=$(echo "$TRANSPORT_VERSION" | sed 's/-.*$//') |
| TRANSPORT_MAJOR_MINOR=$(echo "$TRANSPORT_BASE_VERSION" | cut -d. -f1,2) |
| echo " 🔍 Checking track: ${TRANSPORT_MAJOR_MINOR}.x" |
| |
| |
| ALL_TRANSPORT_TAGS=$(git tag -l "transports/v${TRANSPORT_MAJOR_MINOR}.*" | sort -V) |
| |
| |
| get_base_version() { |
| echo "$1" | sed 's/-.*$//' |
| } |
| |
| |
| LATEST_TRANSPORT_TAG="" |
| LATEST_BASE_VERSION="" |
| |
| for tag in $ALL_TRANSPORT_TAGS; do |
| version=${tag#transports/v} |
| base_version=$(get_base_version "$version") |
| |
| |
| if [ -z "$LATEST_BASE_VERSION" ] || \ |
| [ "$(printf '%s\n' "$LATEST_BASE_VERSION" "$base_version" | sort -V | tail -1)" = "$base_version" ]; then |
| |
| if [ "$base_version" = "$LATEST_BASE_VERSION" ]; then |
| |
| if [[ "$version" != *"-"* ]]; then |
| |
| LATEST_TRANSPORT_TAG="$tag" |
| elif [[ "${LATEST_TRANSPORT_TAG#transports/v}" == *"-"* ]]; then |
| |
| LATEST_TRANSPORT_TAG="$tag" |
| fi |
| else |
| |
| LATEST_TRANSPORT_TAG="$tag" |
| LATEST_BASE_VERSION="$base_version" |
| fi |
| fi |
| done |
| |
| if [ -n "$LATEST_TRANSPORT_TAG" ]; then |
| echo " 🏷️ Latest transport tag: $LATEST_TRANSPORT_TAG" |
| fi |
| if [ -z "$LATEST_TRANSPORT_TAG" ]; then |
| echo " ✅ First transport release in track ${TRANSPORT_MAJOR_MINOR}.x: $TRANSPORT_VERSION" |
| if [ "$GIT_TAG_EXISTS" = "false" ]; then |
| echo " 🏷️ Git tag missing - transport release needed" |
| BIFROST_HTTP_NEEDS_RELEASE="true" |
| fi |
| else |
| PREVIOUS_TRANSPORT_VERSION=${LATEST_TRANSPORT_TAG#transports/v} |
| echo " 📋 Previous: $PREVIOUS_TRANSPORT_VERSION, Current: $TRANSPORT_VERSION" |
| |
| |
| |
| version_less_than() { |
| local v1="$1" |
| local v2="$2" |
| |
| |
| local base1=$(echo "$v1" | sed 's/-.*$//') |
| local base2=$(echo "$v2" | sed 's/-.*$//') |
| |
| |
| if [ "$base1" != "$base2" ]; then |
| |
| [ "$(printf '%s\n' "$base1" "$base2" | sort -V | head -1)" = "$base1" ] |
| return $? |
| fi |
| |
| |
| local pre1=$(echo "$v1" | grep -o '\-.*$' || echo "") |
| local pre2=$(echo "$v2" | grep -o '\-.*$' || echo "") |
| |
| if [ -z "$pre1" ] && [ -n "$pre2" ]; then |
| |
| return 1 |
| elif [ -n "$pre1" ] && [ -z "$pre2" ]; then |
| |
| return 0 |
| elif [ -n "$pre1" ] && [ -n "$pre2" ]; then |
| |
| [ "$(printf '%s\n' "$pre1" "$pre2" | sort -V | head -1)" = "$pre1" ] |
| return $? |
| else |
| |
| return 1 |
| fi |
| } |
| |
| |
| if version_less_than "$PREVIOUS_TRANSPORT_VERSION" "$TRANSPORT_VERSION"; then |
| echo " ✅ Transport version incremented: $PREVIOUS_TRANSPORT_VERSION → $TRANSPORT_VERSION" |
| if [ "$GIT_TAG_EXISTS" = "false" ]; then |
| echo " 🏷️ Git tag missing - transport release needed" |
| BIFROST_HTTP_NEEDS_RELEASE="true" |
| fi |
| else |
| echo " ⏭️ No transport version increment" |
| fi |
| fi |
| fi |
| |
| |
| if [ "$DOCKER_TAG_EXISTS" = "false" ]; then |
| echo " 🐳 Docker image missing - docker release needed" |
| DOCKER_NEEDS_RELEASE="true" |
| fi |
|
|
|
|
| |
| if [ ${#PLUGIN_CHANGES[@]} -eq 0 ]; then |
| CHANGED_PLUGINS_JSON="[]" |
| else |
| CHANGED_PLUGINS_JSON=$(printf '%s\n' "${PLUGIN_CHANGES[@]}" | jq -R . | jq -s -c .) |
| fi |
|
|
| echo "CHANGED_PLUGINS_JSON: $CHANGED_PLUGINS_JSON" |
|
|
| |
| echo "" |
| echo "📋 Release Summary:" |
| echo " Core: $CORE_NEEDS_RELEASE (v$CORE_VERSION)" |
| echo " Framework: $FRAMEWORK_NEEDS_RELEASE (v$FRAMEWORK_VERSION)" |
| echo " Plugins: $PLUGINS_NEED_RELEASE (${#PLUGIN_CHANGES[@]} plugins)" |
| echo " Bifrost HTTP: $BIFROST_HTTP_NEEDS_RELEASE (v$TRANSPORT_VERSION)" |
| echo " Docker: $DOCKER_NEEDS_RELEASE (v$TRANSPORT_VERSION)" |
|
|
| |
| if [ -n "${GITHUB_OUTPUT:-}" ]; then |
| { |
| echo "core-needs-release=$CORE_NEEDS_RELEASE" |
| echo "framework-needs-release=$FRAMEWORK_NEEDS_RELEASE" |
| echo "plugins-need-release=$PLUGINS_NEED_RELEASE" |
| echo "bifrost-http-needs-release=$BIFROST_HTTP_NEEDS_RELEASE" |
| echo "docker-needs-release=$DOCKER_NEEDS_RELEASE" |
| echo "changed-plugins=$CHANGED_PLUGINS_JSON" |
| echo "core-version=$CORE_VERSION" |
| echo "framework-version=$FRAMEWORK_VERSION" |
| echo "transport-version=$TRANSPORT_VERSION" |
| } >> "$GITHUB_OUTPUT" |
| else |
| echo "ℹ️ GITHUB_OUTPUT not set; skipping outputs write (local run)" |
| fi |