Skip to content

feat: ACI-4571 Get benchmark phase#232

Open
zsolt-marta-bitrise wants to merge 14 commits intomainfrom
external-id
Open

feat: ACI-4571 Get benchmark phase#232
zsolt-marta-bitrise wants to merge 14 commits intomainfrom
external-id

Conversation

@zsolt-marta-bitrise
Copy link
Collaborator

No description provided.

@zsolt-marta-bitrise zsolt-marta-bitrise changed the title feat: ACI-4571 Add external CI identifiers feat: ACI-4571 Get benchmark phase Feb 26, 2026
return fmt.Errorf("failed to create xcrun wrapper script: %w", err)
}

pathContent := fmt.Sprintf("export PATH=%s:$PATH", binPath)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got refactored to a new package envexport

"BITRISE_BUILD_CACHE_AUTH_TOKEN": "token",
"BITRISE_BUILD_CACHE_WORKSPACE_ID": "abc123",
"GITHUB_PATH": filepath.Join(home, ".github_path"),
"GITHUB_ENV": filepath.Join(home, ".github_env"),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return TemplateInventory{}, fmt.Errorf(ErrFmtReadAuthConfig, err)
}

metadata := common.NewMetadata(envs,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously in the lower methods (e.g. commonTemplateInventory), I moved it up because we need it for the benchmark phasing

Phase string `json:"phase"`
}

func writeBenchmarkPhaseFile(phase string, logger log.Logger) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a fallback in case the env var export doesn't work

logger.Infof("(i) Benchmark phase: %s", phase)
exporter := envexport.New(envs, logger)
exporter.Export("BITRISE_BUILD_CACHE_BENCHMARK_PHASE", phase)
exporter.ExportToShellRC("Bitrise Benchmark Phase", "export BITRISE_BUILD_CACHE_BENCHMARK_PHASE="+phase)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would override the user's bashrc/zshrc but we don't support benchmark phasing for local builds anyway (see https://github.com/bitrise-io/bitrise-build-cache-cli/pull/232/changes#diff-c9e446e91766670af1e9940e37c9a12bd9568e2889a3e300e9dbd8b98e038115R98)

- content: |-
set -exo pipefail
(./gradlew compileDebugKotlin --info --stacktrace 2>&1) | tee "$BITRISE_DEPLOY_DIR/logs.txt"
(./gradlew assembleDebug --info --stacktrace 2>&1) | tee "$BITRISE_DEPLOY_DIR/logs.txt"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was failing frequently because there is only 1 cacheable task

@zsolt-marta-bitrise
Copy link
Collaborator Author

@zsolt-marta-bitrise zsolt-marta-bitrise marked this pull request as ready for review February 26, 2026 16:22
params.Set("external_workflow_name", metadata.ExternalWorkflowName)
}

requestURL := fmt.Sprintf("%s/build-cache/%s/invocations/gradle/command_benchmark_status?%s",
Copy link
Contributor

@imrekel imrekel Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build tool will need to change depending on the platform (later)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! We're doing it for Gradle only now but there's no blocker in supporting all tools in this method

@zsolt-marta-bitrise
Copy link
Collaborator Author

zsolt-marta-bitrise commented Feb 27, 2026

Summary

Added benchmark phase fetching from Bitrise API with support for external CI providers (CircleCI, GitHub Actions, GitLab CI). Refactored environment variable export logic into a new EnvExporter class. Enhanced cache metadata with external CI identifiers and JWT-based workspace ID extraction.

Walkthrough

File Summary
bitrise.yml Added gradle cache restore/save steps to three e2e test workflows and updated build command in feature-e2e-gradle-7
cmd/xcode/activate_xcode.go Refactored PATH export logic to use new EnvExporter class
internal/config/common/auth.go Added JWT extraction with workspace ID parsing and updated token formatting
internal/config/common/benchmark.go New file: BenchmarkPhaseClient to fetch benchmark phase from Bitrise API
internal/config/common/cache_config.go Added external CI provider detection and external CI identifiers to metadata
internal/config/gradle/activate_for_gradle_params.go Refactored to read auth config upfront and added benchmark phase fetching
internal/consts/consts.go Added BitriseWebsiteBaseURL constant
internal/envexport/envexport.go New file: EnvExporter for exporting variables to process and CI systems
internal/xcelerate/analytics/invocations.go, types.go Added external CI identifier fields to Invocation struct
Test and mock files Added comprehensive test coverage for new functionality

Copy link
Collaborator Author

@zsolt-marta-bitrise zsolt-marta-bitrise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI-generated review. Please review it carefully.

Actionable comments posted: 1

params.Set("external_workflow_name", metadata.ExternalWorkflowName)
}

requestURL := fmt.Sprintf("%s/build-cache/%s/invocations/gradle/command_benchmark_status?%s",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug

Missing validation for empty WorkspaceID. The function constructs a URL using c.authConfig.WorkspaceID without checking if it's empty first. This will result in a malformed URL (e.g., /build-cache//invocations/...) when WorkspaceID is empty. The test TestGetGradleBenchmarkPhase_EmptyWorkspaceID expects the function to return early with an empty string when WorkspaceID is empty, but the current implementation will attempt to make an HTTP request with an invalid URL instead.

🤖 Prompt for AI Agents:
In internal/config/common/benchmark.go at line 77, Add a check for empty WorkspaceID before constructing the URL. Return early with an empty string if WorkspaceID is empty, similar to how the function handles missing app IDs and workflow names.

Copy link
Collaborator Author

@zsolt-marta-bitrise zsolt-marta-bitrise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI-generated review. Please review it carefully.

Actionable comments posted: 1

params.Set("external_workflow_name", metadata.ExternalWorkflowName)
}

requestURL := fmt.Sprintf("%s/build-cache/%s/invocations/%s/command_benchmark_status?%s",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug

The WorkspaceID is used to construct the URL without validation. If WorkspaceID is empty (which can happen if JWT extraction fails or returns an empty value), this creates a malformed URL like "/build-cache//invocations/...". The function should validate that WorkspaceID is not empty before constructing the request URL.

🤖 Prompt for AI Agents:
In internal/config/common/benchmark.go at line 82, Add validation to check if WorkspaceID is empty before constructing the request URL. Return an error or empty string if WorkspaceID is missing.

Copy link
Collaborator Author

@zsolt-marta-bitrise zsolt-marta-bitrise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI-generated review. Please review it carefully.

Actionable comments posted: 1

func (c *BenchmarkPhaseClient) GetBenchmarkPhase(buildTool string, metadata CacheConfigMetadata) (string, error) {
params := url.Values{}

if c.authConfig.WorkspaceID == "" {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🐛 Bug

The function returns an error when WorkspaceID is empty, but the test TestGetBenchmarkPhase_EmptyWorkspaceID expects it to return an empty string with no error. This breaks the expected behavior where missing workspace ID should gracefully skip the benchmark phase check instead of failing.

🔄 Suggestion:

Suggested change
if c.authConfig.WorkspaceID == "" {
if c.authConfig.WorkspaceID == "" {
c.logger.Debugf("workspace ID is not available, skipping benchmark phase check")
return "", nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants