diff --git a/.github/workflows/prowler-release-preparation.yml b/.github/workflows/prowler-release-preparation.yml index 6008a25795..93ec5dee8f 100644 --- a/.github/workflows/prowler-release-preparation.yml +++ b/.github/workflows/prowler-release-preparation.yml @@ -59,25 +59,157 @@ jobs: BRANCH_NAME="v${MAJOR_VERSION}.${MINOR_VERSION}" echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_ENV}" - # Calculate UI version (1.X.X format - matches Prowler minor version) - UI_VERSION="1.${MINOR_VERSION}.${PATCH_VERSION}" - echo "UI_VERSION=${UI_VERSION}" >> "${GITHUB_ENV}" + # Function to extract the latest version from changelog + extract_latest_version() { + local changelog_file="$1" + if [ -f "$changelog_file" ]; then + # Extract the first version entry (most recent) from changelog + # Format: ## [version] (1.2.3) or ## [vversion] (v1.2.3) + local version=$(grep -m 1 '^## \[' "$changelog_file" | sed 's/^## \[\(.*\)\].*/\1/' | sed 's/^v//' | tr -d '[:space:]') + echo "$version" + else + echo "" + fi + } - # Calculate API version (1.X.X format - one minor version ahead) - API_MINOR_VERSION=$((MINOR_VERSION + 1)) - API_VERSION="1.${API_MINOR_VERSION}.${PATCH_VERSION}" + # Read actual versions from changelogs (source of truth) + UI_VERSION=$(extract_latest_version "ui/CHANGELOG.md") + API_VERSION=$(extract_latest_version "api/CHANGELOG.md") + SDK_VERSION=$(extract_latest_version "prowler/CHANGELOG.md") + + echo "UI_VERSION=${UI_VERSION}" >> "${GITHUB_ENV}" echo "API_VERSION=${API_VERSION}" >> "${GITHUB_ENV}" + echo "SDK_VERSION=${SDK_VERSION}" >> "${GITHUB_ENV}" + + if [ -n "$UI_VERSION" ]; then + echo "Read UI version from changelog: $UI_VERSION" + else + echo "Warning: No UI version found in ui/CHANGELOG.md" + fi + + if [ -n "$API_VERSION" ]; then + echo "Read API version from changelog: $API_VERSION" + else + echo "Warning: No API version found in api/CHANGELOG.md" + fi + + if [ -n "$SDK_VERSION" ]; then + echo "Read SDK version from changelog: $SDK_VERSION" + else + echo "Warning: No SDK version found in prowler/CHANGELOG.md" + fi echo "Prowler version: $PROWLER_VERSION" echo "Branch name: $BRANCH_NAME" echo "UI version: $UI_VERSION" echo "API version: $API_VERSION" + echo "SDK version: $SDK_VERSION" echo "Is minor release: $([ $PATCH_VERSION -eq 0 ] && echo 'true' || echo 'false')" else echo "Invalid version syntax: '$PROWLER_VERSION' (must be N.N.N)" >&2 exit 1 fi + - name: Extract changelog entries + run: | + set -e + + # Function to extract changelog for a specific version + extract_changelog() { + local file="$1" + local version="$2" + local output_file="$3" + + if [ ! -f "$file" ]; then + echo "Warning: $file not found, skipping..." + touch "$output_file" + return + fi + + # Extract changelog section for this version + awk -v version="$version" ' + /^## \[v?'"$version"'\]/ { found=1; next } + found && /^## \[v?[0-9]+\.[0-9]+\.[0-9]+\]/ { found=0 } + found && !/^## \[v?'"$version"'\]/ { print } + ' "$file" > "$output_file" + + # Remove --- separators + sed -i '/^---$/d' "$output_file" + + # Remove trailing empty lines + sed -i '/^$/d' "$output_file" + } + + # Calculate expected versions for this release + if [[ $PROWLER_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + EXPECTED_UI_VERSION="1.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" + EXPECTED_API_VERSION="1.$((${BASH_REMATCH[2]} + 1)).${BASH_REMATCH[3]}" + + echo "Expected UI version for this release: $EXPECTED_UI_VERSION" + echo "Expected API version for this release: $EXPECTED_API_VERSION" + fi + + # Determine if components have changes for this specific release + # UI has changes if its current version matches what we expect for this release + if [ -n "$UI_VERSION" ] && [ "$UI_VERSION" = "$EXPECTED_UI_VERSION" ]; then + echo "HAS_UI_CHANGES=true" >> $GITHUB_ENV + echo "✓ UI changes detected - version matches expected: $UI_VERSION" + extract_changelog "ui/CHANGELOG.md" "$UI_VERSION" "ui_changelog.md" + else + echo "HAS_UI_CHANGES=false" >> $GITHUB_ENV + echo "ℹ No UI changes for this release (current: $UI_VERSION, expected: $EXPECTED_UI_VERSION)" + touch "ui_changelog.md" + fi + + # API has changes if its current version matches what we expect for this release + if [ -n "$API_VERSION" ] && [ "$API_VERSION" = "$EXPECTED_API_VERSION" ]; then + echo "HAS_API_CHANGES=true" >> $GITHUB_ENV + echo "✓ API changes detected - version matches expected: $API_VERSION" + extract_changelog "api/CHANGELOG.md" "$API_VERSION" "api_changelog.md" + else + echo "HAS_API_CHANGES=false" >> $GITHUB_ENV + echo "ℹ No API changes for this release (current: $API_VERSION, expected: $EXPECTED_API_VERSION)" + touch "api_changelog.md" + fi + + # SDK has changes if its current version matches the input version + if [ -n "$SDK_VERSION" ] && [ "$SDK_VERSION" = "$PROWLER_VERSION" ]; then + echo "HAS_SDK_CHANGES=true" >> $GITHUB_ENV + echo "✓ SDK changes detected - version matches input: $SDK_VERSION" + extract_changelog "prowler/CHANGELOG.md" "$PROWLER_VERSION" "prowler_changelog.md" + else + echo "HAS_SDK_CHANGES=false" >> $GITHUB_ENV + echo "ℹ No SDK changes for this release (current: $SDK_VERSION, input: $PROWLER_VERSION)" + touch "prowler_changelog.md" + fi + + # Combine changelogs in order: UI, API, SDK + > combined_changelog.md + + if [ "$HAS_UI_CHANGES" = "true" ] && [ -s "ui_changelog.md" ]; then + echo "## UI" >> combined_changelog.md + echo "" >> combined_changelog.md + cat ui_changelog.md >> combined_changelog.md + echo "" >> combined_changelog.md + fi + + if [ "$HAS_API_CHANGES" = "true" ] && [ -s "api_changelog.md" ]; then + echo "## API" >> combined_changelog.md + echo "" >> combined_changelog.md + cat api_changelog.md >> combined_changelog.md + echo "" >> combined_changelog.md + fi + + if [ "$HAS_SDK_CHANGES" = "true" ] && [ -s "prowler_changelog.md" ]; then + echo "## SDK" >> combined_changelog.md + echo "" >> combined_changelog.md + cat prowler_changelog.md >> combined_changelog.md + echo "" >> combined_changelog.md + fi + + echo "Combined changelog preview:" + cat combined_changelog.md + - name: Checkout existing branch for patch release if: ${{ env.PATCH_VERSION != '0' }} run: | @@ -114,6 +246,7 @@ jobs: echo "✓ prowler/config/config.py version: $CURRENT_VERSION" - name: Verify version in api/pyproject.toml + if: ${{ env.HAS_API_CHANGES == 'true' }} run: | CURRENT_API_VERSION=$(grep '^version = ' api/pyproject.toml | sed -E 's/version = "([^"]+)"/\1/' | tr -d '[:space:]') API_VERSION_TRIMMED=$(echo "$API_VERSION" | tr -d '[:space:]') @@ -124,7 +257,7 @@ jobs: echo "✓ api/pyproject.toml version: $CURRENT_API_VERSION" - name: Verify prowler dependency in api/pyproject.toml - if: ${{ env.PATCH_VERSION != '0' }} + if: ${{ env.PATCH_VERSION != '0' && env.HAS_API_CHANGES == 'true' }} run: | CURRENT_PROWLER_REF=$(grep 'prowler @ git+https://github.com/prowler-cloud/prowler.git@' api/pyproject.toml | sed -E 's/.*@([^"]+)".*/\1/' | tr -d '[:space:]') BRANCH_NAME_TRIMMED=$(echo "$BRANCH_NAME" | tr -d '[:space:]') @@ -135,6 +268,7 @@ jobs: echo "✓ api/pyproject.toml prowler dependency: $CURRENT_PROWLER_REF" - name: Verify version in api/src/backend/api/v1/views.py + if: ${{ env.HAS_API_CHANGES == 'true' }} run: | CURRENT_API_VERSION=$(grep 'spectacular_settings.VERSION = ' api/src/backend/api/v1/views.py | sed -E 's/.*spectacular_settings.VERSION = "([^"]+)".*/\1/' | tr -d '[:space:]') API_VERSION_TRIMMED=$(echo "$API_VERSION" | tr -d '[:space:]') @@ -162,12 +296,11 @@ jobs: CURRENT_PROWLER_REF=$(grep 'prowler @ git+https://github.com/prowler-cloud/prowler.git@' api/pyproject.toml | sed -E 's/.*@([^"]+)".*/\1/' | tr -d '[:space:]') BRANCH_NAME_TRIMMED=$(echo "$BRANCH_NAME" | tr -d '[:space:]') - # Create a temporary branch for the PR + # Create a temporary branch for the PR from the minor version branch TEMP_BRANCH="update-api-dependency-$BRANCH_NAME_TRIMMED-$(date +%s)" echo "TEMP_BRANCH=$TEMP_BRANCH" >> $GITHUB_ENV - # Switch back to master and create temp branch - git checkout master + # Create temp branch from the current minor version branch git checkout -b "$TEMP_BRANCH" # Minor release: update the dependency to use the release branch @@ -221,69 +354,6 @@ jobs: component/api no-changelog - - name: Extract changelog entries - run: | - set -e - - # Function to extract changelog for a specific version - extract_changelog() { - local file="$1" - local version="$2" - local output_file="$3" - - if [ ! -f "$file" ]; then - echo "Warning: $file not found, skipping..." - touch "$output_file" - return - fi - - # Extract changelog section for this version - awk -v version="$version" ' - /^## \[v?'"$version"'\]/ { found=1; next } - found && /^## \[v?[0-9]+\.[0-9]+\.[0-9]+\]/ { found=0 } - found && !/^## \[v?'"$version"'\]/ { print } - ' "$file" > "$output_file" - - # Remove --- separators - sed -i '/^---$/d' "$output_file" - - # Remove trailing empty lines - sed -i '/^$/d' "$output_file" - } - - # Extract changelogs - echo "Extracting changelog entries..." - extract_changelog "prowler/CHANGELOG.md" "$PROWLER_VERSION" "prowler_changelog.md" - extract_changelog "api/CHANGELOG.md" "$API_VERSION" "api_changelog.md" - extract_changelog "ui/CHANGELOG.md" "$UI_VERSION" "ui_changelog.md" - - # Combine changelogs in order: UI, API, SDK - > combined_changelog.md - - if [ -s "ui_changelog.md" ]; then - echo "## UI" >> combined_changelog.md - echo "" >> combined_changelog.md - cat ui_changelog.md >> combined_changelog.md - echo "" >> combined_changelog.md - fi - - if [ -s "api_changelog.md" ]; then - echo "## API" >> combined_changelog.md - echo "" >> combined_changelog.md - cat api_changelog.md >> combined_changelog.md - echo "" >> combined_changelog.md - fi - - if [ -s "prowler_changelog.md" ]; then - echo "## SDK" >> combined_changelog.md - echo "" >> combined_changelog.md - cat prowler_changelog.md >> combined_changelog.md - echo "" >> combined_changelog.md - fi - - echo "Combined changelog preview:" - cat combined_changelog.md - - name: Create draft release uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8 # v2.3.2 with: @@ -291,7 +361,7 @@ jobs: name: Prowler ${{ env.PROWLER_VERSION }} body_path: combined_changelog.md draft: true - target_commitish: ${{ env.PATCH_VERSION == '0' && 'master' || env.BRANCH_NAME }} + target_commitish: ${{ env.BRANCH_NAME }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}