diff --git a/.github/workflows/pre-merge.yml b/.github/workflows/pre-merge.yml index f4959d046..2f363aff5 100644 --- a/.github/workflows/pre-merge.yml +++ b/.github/workflows/pre-merge.yml @@ -11,6 +11,11 @@ on: description: 'Release tag to build' required: true type: string + publish_image: + description: 'Publish Docker image to GHCR' + required: false + type: boolean + default: false outputs: docker_image_urls: description: 'Array of Docker image URLs that were published' @@ -60,7 +65,7 @@ jobs: platform: ${{ matrix.platform }} registry_username: ${{ github.actor }} registry_password: ${{ secrets.GITHUB_TOKEN }} - publish_image: ${{ vars.PUBLISH_IMAGE }} + publish_image: ${{ inputs.publish_image || vars.PUBLISH_IMAGE }} registry_repository: ${{ format('ghcr.io/{0}', github.repository) }} release_tag: ${{ inputs.release_tag }} diff --git a/.github/workflows/release_build_and_test.yml b/.github/workflows/release_build_and_test.yml index bfbdfe31a..41299fb8d 100644 --- a/.github/workflows/release_build_and_test.yml +++ b/.github/workflows/release_build_and_test.yml @@ -57,6 +57,7 @@ jobs: secrets: inherit with: release_tag: ${{ github.event.inputs.release_tag }} + publish_image: true merge-back-to-release-branch: needs: [prepare-release, build-and-test] diff --git a/.github/workflows/release_publish.yml b/.github/workflows/release_publish.yml index 53656054f..c57fe9d24 100644 --- a/.github/workflows/release_publish.yml +++ b/.github/workflows/release_publish.yml @@ -11,6 +11,8 @@ on: workflow_uuid: description: 'Optional UUID to identify this workflow run' required: false + pr_to_official_library: + default: false env: TARGET_OFFICIAL_IMAGES_REPO: docker-library/official-images @@ -76,7 +78,7 @@ jobs: uses: actions/checkout@v4 with: path: official-images - repository: ${{ env.TARGET_OFFICIAL_IMAGES_REPO }} + repository: ${{ github.event.inputs.pr_to_official_library == 'true' && env.TARGET_OFFICIAL_IMAGES_REPO || env.FORKED_OFFICIAL_IMAGES_REPO }} - name: Generate stackbrew library content env: @@ -102,7 +104,7 @@ jobs: with: token: ${{ secrets.GH_TOKEN_FOR_PR }} draft: true - push-to-fork: ${{ env.FORKED_OFFICIAL_IMAGES_REPO }} + push-to-fork: ${{ github.event.inputs.pr_to_official_library == 'true' && env.FORKED_OFFICIAL_IMAGES_REPO || '' }} path: official-images branch: redis-${{ steps.parse-release.outputs.release_version }} commit-message: "Redis: Update to ${{ steps.parse-release.outputs.release_version }}" @@ -158,4 +160,4 @@ jobs: . ${GITHUB_WORKSPACE}/.github/actions/common/func.sh slack_format_failure_message "Docker PR failed for Redis: ${{ steps.parse-release.outputs.release_version || 'unknown'}}" "$workflow_url" "$footer" \ - | curl -s --fail-with-body -d@- "${{ secrets.SLACK_WEB_HOOK_URL }}" \ No newline at end of file + | curl -s --fail-with-body -d@- "${{ secrets.SLACK_WEB_HOOK_URL }}" diff --git a/release-automation/src/stackbrew_generator/git_operations.py b/release-automation/src/stackbrew_generator/git_operations.py index 14dab035c..493c7e4a4 100644 --- a/release-automation/src/stackbrew_generator/git_operations.py +++ b/release-automation/src/stackbrew_generator/git_operations.py @@ -67,7 +67,7 @@ def list_remote_tags(self, major_version: int) -> List[Tuple[str, str]]: console.print(f"[dim]Listing remote tags for v{major_version}.*[/dim]") cmd = [ - "git", "ls-remote", "--refs", "--tags", + "git", "ls-remote", "--tags", self.remote, f"refs/tags/v{major_version}.*" ] @@ -76,11 +76,28 @@ def list_remote_tags(self, major_version: int) -> List[Tuple[str, str]]: if not result.stdout.strip(): raise GitOperationError(f"No tags found for major version {major_version}") - tags = [] + tag_commits = {} + + # always use peeled commits for annotated tags + # for annotated tags git ls-remote prints tag object hash, then actual commit hash with ^{} suffix + # https://stackoverflow.com/a/25996877 for line in result.stdout.strip().split('\n'): if line: commit, ref = line.split('\t', 1) - tags.append((commit, ref)) + if ref.endswith('^{}'): + # This is a peeled ref - extract the tag name + # always rewrite tag commits with peeled ref commits + tag_name = ref[:-3] # Remove '^{}' + tag_commits[tag_name] = commit + else: + # This is a regular tag + # rewrite only if not yet exists + if ref not in tag_commits: + tag_commits[ref] = commit + + tags = [] + for tag_ref, commit in tag_commits.items(): + tags.append((commit, tag_ref)) console.print(f"[dim]Found {len(tags)} tags[/dim]") return tags diff --git a/release-automation/tests/test_git_operations.py b/release-automation/tests/test_git_operations.py new file mode 100644 index 000000000..fddf2f4cb --- /dev/null +++ b/release-automation/tests/test_git_operations.py @@ -0,0 +1,41 @@ +"""Tests for git operations.""" + +from unittest.mock import Mock, patch + +from stackbrew_generator.git_operations import GitClient + + +class TestGitClient: + """Tests for GitClient class.""" + + @patch('stackbrew_generator.git_operations.console') + @patch.object(GitClient, '_run_command') + def test_list_remote_tags(self, mock_run_command, mock_console): + """ + Test that list_remote_tags returns the expected format for peeled refs. + + For tags with ^{} suffix, use the commit hash from that line. + For tags without ^{} suffix, use the commit hash from the tag line. + """ + mock_result = Mock() + mock_result.stdout = """101262a8cf05b98137d88bc17e77db90c24cc783\trefs/tags/v8.0.3 +2277e5ead99f0caacbd90e0d04693adb27ebfaa6\trefs/tags/v8.0.4^{} +c0125f5be8786d556a9d3edd70f51974fe045c1a\trefs/tags/v8.0.4 +f76d8a1cc979be6202aed93efddd2a0ebbfa0209\trefs/tags/v8.2.2 +c5846c13383c8b284897ff171e0c946868ed4c8c\trefs/tags/v8.2.2^{}""" + mock_run_command.return_value = mock_result + + client = GitClient() + result = client.list_remote_tags(8) + + # Expected behavior: + # - v8.0.3 has no peeled ref, so use the tag commit + # - v8.0.4 has a peeled ref, so use the peeled commit (2277e5ead99f0caacbd90e0d04693adb27ebfaa6) + # - v8.2.2 has a peeled ref, so use the peeled commit (c5846c13383c8b284897ff171e0c946868ed4c8c) + expected_result = [ + ("101262a8cf05b98137d88bc17e77db90c24cc783", "refs/tags/v8.0.3"), # No peeled ref + ("2277e5ead99f0caacbd90e0d04693adb27ebfaa6", "refs/tags/v8.0.4"), # Use peeled ref + ("c5846c13383c8b284897ff171e0c946868ed4c8c", "refs/tags/v8.2.2") # Use peeled ref + ] + + assert result == expected_result