Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Git integration tests #38337

Merged
merged 4 commits into from
Dec 24, 2024
Merged

test: Git integration tests #38337

merged 4 commits into from
Dec 24, 2024

Conversation

nidhi-nair
Copy link
Contributor

@nidhi-nair nidhi-nair commented Dec 24, 2024

Description

Tip

Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team).

Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR.

Fixes #Issue Number
or
Fixes Issue URL

Warning

If no issue exists, please create an issue first, and check with the maintainers if the issue is valid.

Automation

/ok-to-test tags="@tag.Git"

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/12479113304
Commit: bebfa2a
Cypress dashboard.
Tags: @tag.Git
Spec:


Tue, 24 Dec 2024 09:11:23 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features

    • Added a method to set the name of artifacts.
    • Introduced a new integration test class for validating Git workflows.
    • Added new classes for managing Git context and test templates.
  • Bug Fixes

    • Improved error handling in branch deletion logic to ensure proper resource management.
  • Tests

    • Added various utility classes and extensions for testing Git operations and artifact management.
  • Chores

    • Introduced new test utilities for managing Git and artifact operations.

@nidhi-nair nidhi-nair requested a review from a team as a code owner December 24, 2024 04:06
Copy link
Contributor

coderabbitai bot commented Dec 24, 2024

Walkthrough

This pull request introduces a comprehensive set of changes to the Git-related testing infrastructure in the Appsmith server. The modifications focus on enhancing the testing capabilities for Git operations, including new utility classes, test contexts, and extensions that support more robust and flexible integration testing of Git workflows for artifacts.

Changes

File Change Summary
app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ArtifactCE.java Added setName() method to the ArtifactCE interface
app/server/appsmith-server/src/main/java/com/appsmith/server/git/common/CommonGitServiceCEImpl.java Improved error handling in deleteBranch method by ensuring file lock release
app/server/appsmith-server/src/test/it/com/appsmith/server/git/... New integration test classes and contexts for Git branch testing
app/server/appsmith-server/src/test/utils/com/appsmith/server/git/... Added utility classes for Git artifact testing, including ArtifactBuilderContext, ArtifactBuilderExtension, GitTestUtils, etc.

Sequence Diagram

sequenceDiagram
    participant Test as Integration Test
    participant GitContext as Git Context
    participant GitServer as Git Server
    participant ArtifactBuilder as Artifact Builder
    
    Test->>GitContext: Initialize Context
    GitContext->>ArtifactBuilder: Create Workspace
    ArtifactBuilder-->>GitContext: Return Workspace ID
    GitContext->>GitServer: Create Repository
    GitServer-->>GitContext: Repository Created
    Test->>GitContext: Perform Git Operations
    Test->>GitContext: Validate Outcomes
Loading

Suggested labels

skip-changelog, Test, Git Product, Task, ok-to-test

Poem

🌿 Git branches dance and sway,
Code commits find their way,
Testing magic unfurls bright,
Artifacts take their flight!
Appsmith's testing prowess gleams ✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added skip-changelog Adding this label to a PR prevents it from being listed in the changelog Test labels Dec 24, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (11)
app/server/appsmith-server/src/test/it/com/appsmith/server/git/GitBranchesIT.java (3)

167-170: Resolve the TODO comments.
There are follow-up TODO items to move filePath variables to be relative and to consider using the controller layer. Address these to maintain clarity and ensure test consistency.


217-227: Avoid using Thread.sleep in tests.
Polling with Thread.sleep can introduce flaky behavior and unnecessary delays. Consider using reactive constructs (e.g., StepVerifier or Mono/Flux time-bound methods) or a condition-based wait for improved reliability.


431-436: Automate branch checkout.
Manually performing a checkout before deleting a branch reflects a potential usability gap. Consider implementing a logic that automatically checks out a different branch or warns the user before attempting deletion.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitTestUtils.java (1)

14-19: Prepare for artifact type expansions.
Currently, getArtifactSpecificUtils() always returns gitApplicationTestUtils. If future artifact types are introduced, additional logic or classes may be necessary.

app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/contexts/GitContext.java (2)

33-35: Use invocationIndex in displayName for clarity.
Appending invocationIndex in the returned displayName can aid in debugging test iterations.

 public String getDisplayName(int invocationIndex) {
-    return fileName;
+    return fileName + " [#" + invocationIndex + "]";
 }

59-63: Refine parameter resolution.
Currently, supportsParameter always returns true, leading to potential confusion for parameters the extension does not expect. Narrow the condition or add additional checks.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java (1)

95-103: Ensure consistent cleanup in case of partial failures.
After deleting applications, consider verifying that the workspace itself is archived successfully, especially when encountering unexpected errors mid-flow.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitServerInitializerExtension.java (2)

59-96: Add error handling for repo creation.
When attaching SSH keys and creating the repository, if the repository already exists or the API call fails, consider raising a clearer error for debugging.


110-112: Stop container only if running check is reliable.
Linger checks might be helpful to ensure the Git server has had time to shut down completely, preventing possible conflicts in subsequent tests if the container lingers.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderContext.java (2)

7-8: Add interface documentation.

Consider adding Javadoc to describe the purpose of this interface and its role in Git integration testing.

+/**
+ * Context for building artifacts during Git integration tests.
+ * Extends ExtensionContext to provide artifact-specific metadata and management capabilities
+ * within test execution contexts.
+ */
 public interface ArtifactBuilderContext extends ExtensionContext {

15-21: Consider adding parameter validation.

The setter methods should validate their input parameters to prevent null or empty strings from being set.

-    void setWorkspaceId(String workspaceId);
+    /**
+     * Sets the workspace ID for the artifact context.
+     * @param workspaceId must not be null or empty
+     * @throws IllegalArgumentException if workspaceId is null or empty
+     */
+    void setWorkspaceId(String workspaceId);

-    void setArtifactId(String artifactId);
+    /**
+     * Sets the artifact ID for the context.
+     * @param artifactId must not be null or empty
+     * @throws IllegalArgumentException if artifactId is null or empty
+     */
+    void setArtifactId(String artifactId);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc38ee7 and bebfa2a.

📒 Files selected for processing (11)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ArtifactCE.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/git/common/CommonGitServiceCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/test/it/com/appsmith/server/git/GitBranchesIT.java (1 hunks)
  • app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/contexts/GitContext.java (1 hunks)
  • app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/providers/GitBranchesTestTemplateProvider.java (1 hunks)
  • app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/providers/ce/GitBranchesTestTemplateProviderCE.java (1 hunks)
  • app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderContext.java (1 hunks)
  • app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java (1 hunks)
  • app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitArtifactTestUtils.java (1 hunks)
  • app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitServerInitializerExtension.java (1 hunks)
  • app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitTestUtils.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/providers/GitBranchesTestTemplateProvider.java
🔇 Additional comments (10)
app/server/appsmith-server/src/test/it/com/appsmith/server/git/GitBranchesIT.java (2)

346-349: Validate error message handling.
Ensure that all error messages (e.g., “Cannot commit to protected branch”) are localized or handled consistently if there is any plan for internationalization or user-facing logs.


493-495: Investigate the persistent diff after discard.
A repeated diff is being triggered by an “on page load” event. Confirm whether this is expected or a bug to avoid false positives in test results.

app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ce/ArtifactCE.java (1)

16-17: Method addition looks good.
The setter method for artifact name aligns well with existing getters. This provides better control over artifact properties.

app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/providers/ce/GitBranchesTestTemplateProviderCE.java (1)

14-31: Parameterized test provider looks good.
This test template provider correctly sets up GitContext for parameterized testing. No issues found.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitArtifactTestUtils.java (1)

28-51: Handle plugin lookup failures.
If the “restapi-plugin” is unavailable, pluginService.findByPackageName(...) may return null, leading to potential NullPointerExceptions. Consider defensive checks or fallback mechanisms.

+if (plugin == null) {
+   return Mono.error(new IllegalStateException("Plugin 'restapi-plugin' not found"));
+}
app/server/appsmith-server/src/test/it/com/appsmith/server/git/templates/contexts/GitContext.java (1)

22-30: Reuse of ExtensionContext.Store is good; carefully consider impacts of writing to the same namespace.
Storing data in the same namespace as ArtifactBuilderExtension is logically consistent. Nonetheless, ensure no collisions if multiple extensions use the same keys.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java (1)

72-83: Consider concurrency checks for artifact creation.
While you create and import a new artifact in the workspace, watch for concurrency scenarios where multiple tests create artifacts simultaneously.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/GitServerInitializerExtension.java (1)

48-52: Confirm container readiness in test environments.
While the container’s readiness check is set to wait on port 4200, consider handling slow startups gracefully and logging extended delays if the container fails to start.

app/server/appsmith-server/src/main/java/com/appsmith/server/git/common/CommonGitServiceCEImpl.java (1)

2190-2200: Proper lock release on failed branch deletion is commendable.
Returning after calling releaseFileLock ensures no leftover locks remain when the branch cannot be deleted. This prevents resource contention in subsequent operations.

app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderContext.java (1)

1-6: LGTM! Clean imports and proper package structure.

Comment on lines +157 to +227
void test(GitContext gitContext, ExtensionContext extensionContext) throws IOException, GitAPIException, InterruptedException {

ExtensionContext.Store contextStore = extensionContext.getStore(ExtensionContext.Namespace.create(ArtifactBuilderExtension.class));
String artifactId = contextStore.get(FieldName.ARTIFACT_ID, String.class);

GitConnectDTO connectDTO = new GitConnectDTO();
connectDTO.setRemoteUrl(gitServerInitializerExtension.getGitSshUrl("test" + artifactId));
GitProfile gitProfile = new GitProfile("foo bar", "[email protected]", null);
connectDTO.setGitProfile(gitProfile);

// TODO:
// - Move the filePath variable to be relative, so that template name and repo name is prettier
// - Is it possible to use controller layer here? Might help with also including web filters in IT
Artifact artifact = commonGitService.connectArtifactToGit(artifactId, connectDTO, ORIGIN, gitContext.getArtifactType())
.block();

assertThat(artifact).isNotNull();

ArtifactType artifactType = artifact.getArtifactType();
GitArtifactMetadata artifactMetadata = artifact.getGitArtifactMetadata();
GitArtifactHelper<?> artifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType);
Path repoSuffix = artifactHelper.getRepoSuffixPath(
artifact.getWorkspaceId(),
artifactMetadata.getDefaultArtifactId(),
artifactMetadata.getRepoName());

// Auto-commit should be turned on by default
assertThat(artifactMetadata.getAutoCommitConfig().getEnabled()).isTrue();

Path path = Path.of(gitServiceConfig.getGitRootPath()).resolve(repoSuffix);
String branch;
ObjectId topOfCommits;

try (Git git = Git.open(path.toFile())) {
branch = git.log().getRepository().getBranch();
assertThat(branch).isEqualTo(artifactMetadata.getBranchName());

// Assert only single system generated commit exists on FS
Iterable<RevCommit> commits = git.log().call();
Iterator<RevCommit> commitIterator = commits.iterator();
assertThat(commitIterator.hasNext()).isTrue();

RevCommit firstCommit = commitIterator.next();
assertThat(firstCommit.getFullMessage()).isEqualTo(DEFAULT_COMMIT_MESSAGE + GitDefaultCommitMessage.CONNECT_FLOW.getReason());
topOfCommits = firstCommit.getId();

assertThat(commitIterator.hasNext()).isFalse();

// Assert that git directory is clean
Status status = git.status().call();
assertThat(status.isClean()).isTrue();
}

// Assert that the artifact does have auto-commit requirements, and auto-commit gets initiated
AutoCommitResponseDTO autoCommitResponseDTO = autoCommitService.autoCommitApplication(artifactId).block();

assertThat(autoCommitResponseDTO).isNotNull();
AutoCommitResponseDTO.AutoCommitResponse autoCommitProgress = autoCommitResponseDTO.getAutoCommitResponse();
assertThat(autoCommitProgress).isEqualTo(AutoCommitResponseDTO.AutoCommitResponse.PUBLISHED);

// Wait for auto-commit to complete
// This should not take more than 2 seconds, we're checking every 500 ms
long startTime = System.currentTimeMillis(), currentTime = System.currentTimeMillis();
while (!autoCommitProgress.equals(AutoCommitResponseDTO.AutoCommitResponse.IDLE)) {
Thread.sleep(500);
if (currentTime - startTime > 2000) {
fail("Auto-commit took too long");
}
autoCommitProgress = getAutocommitProgress(artifactId, artifact, artifactMetadata);
currentTime = System.currentTimeMillis();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider splitting the test for better maintainability.
This single test method is quite long and covers a broad range of scenarios. Splitting it into multiple focused tests would improve readability, reduce complexity, and make it easier to locate and isolate failures.

Comment on lines +106 to +116
private Mono<? extends ArtifactExchangeJson> createArtifactJson(String filePath, Class<? extends ArtifactExchangeJson> exchangeJsonType) throws IOException {

ClassPathResource classPathResource = new ClassPathResource(filePath);

String artifactJson = classPathResource.getContentAsString(Charset.defaultCharset());

ArtifactExchangeJson artifactExchangeJson =
objectMapper.copy().disable(MapperFeature.USE_ANNOTATIONS).readValue(artifactJson, exchangeJsonType);

return jsonSchemaMigration.migrateArtifactExchangeJsonToLatestSchema(artifactExchangeJson, null, null);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate artifact JSON before migration.
Consider adding pre-validation steps to handle malformed or incompatible artifact files gracefully, protecting against potential I/O or parsing exceptions at runtime.

Comment on lines +9 to +13
ArtifactType getArtifactType();

Class<? extends ArtifactExchangeJson> getArtifactJsonType();

String getArtifactJsonPath();
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Add Javadoc to clarify these critical artifact interface methods

These methods are widely used throughout the codebase for Git operations, artifact handling, and import/export functionality. Documentation is essential as they are part of a core interface.

  • getArtifactType(): Returns the type of artifact (e.g., Application) being processed
  • getArtifactJsonType(): Specifies the JSON structure class for artifact serialization
  • getArtifactJsonPath(): Defines the file path for storing the artifact's JSON representation
🔗 Analysis chain

Document artifact-related methods.

Add Javadoc to clarify the purpose of these methods. Also, verify the implementation in test classes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find implementations to ensure proper usage
ast-grep --pattern 'class $_ implements ArtifactBuilderContext {
  $$$
  getArtifactType() {
    $$$
  }
  $$$
}'

Length of output: 115


Script:

#!/bin/bash
# Let's try a different approach to find implementations and usages
# First, find all files that might contain the interface or implementations
rg -l "ArtifactBuilderContext" 

# Then look for the actual interface definition and its usages
rg -A 5 "interface ArtifactBuilderContext"

# Search for implementations with a simpler pattern
rg -A 5 "implements ArtifactBuilderContext"

# Look for usages of these methods
rg "getArtifactType\(\)"
rg "getArtifactJsonType\(\)"
rg "getArtifactJsonPath\(\)"

Length of output: 13463

@nidhi-nair nidhi-nair added the ok-to-test Required label for CI label Dec 24, 2024
@nidhi-nair nidhi-nair merged commit f2733c6 into release Dec 24, 2024
63 of 65 checks passed
@nidhi-nair nidhi-nair deleted the test/git-it branch December 24, 2024 09:50
NandanAnantharamu pushed a commit that referenced this pull request Dec 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Required label for CI skip-changelog Adding this label to a PR prevents it from being listed in the changelog Test
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants