Skip to content

SED-4555 local-execution-of-ap-with-keyword-accessing-the-ap-content-is-not-supported-30#602

Open
david-stephan wants to merge 6 commits intomasterfrom
SED-4555-local-execution-of-ap-with-keyword-accessing-the-ap-content-is-not-supported-30
Open

SED-4555 local-execution-of-ap-with-keyword-accessing-the-ap-content-is-not-supported-30#602
david-stephan wants to merge 6 commits intomasterfrom
SED-4555-local-execution-of-ap-with-keyword-accessing-the-ap-content-is-not-supported-30

Conversation

@david-stephan
Copy link
Contributor

No description provided.

… for step 29 (#598)

* SED-4555 Local execution of AP with Keyword accessing the AP content is not supported

* SED-4555 PR feedback and cleanup

* SED-4555 ClassLoaderArchiver must exclude signature files

* SED-4555 switching to sequential unzip

* SED-4555 PR feedbacks

* SED-4562 Support Junit AP tests with Keyword accessing the AP content for Step 29

* SED-4562 PR feedbacks

* SED-4562 fixing cases where operation mode is null in execution context
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new LOCAL_AUTOMATION_PACKAGE operation mode to better differentiate local execution contexts for automation packages. It refactors the handling of classpath-based automation packages by removing the isClasspathBased flag and updating related classes to implicitly manage classloader archiving. A dedicated LocalFunctionHandler is added for local function execution, and JUnit runners are updated to leverage the new operation mode. These changes streamline local automation package execution, improve clarity in operation modes, and enhance resource handling.

Highlights

  • New Operation Mode for Local Automation Packages: Introduced a new LOCAL_AUTOMATION_PACKAGE enum value in OperationMode to specifically distinguish local execution contexts for automation packages, separate from general local execution.
  • Refactored Classpath-Based Automation Package Handling: The isClasspathBased boolean parameter has been removed from various classes including AutomationPackageUpdateParameter, AutomationPackageManager, and AutomationPackageReader, simplifying the API and internal logic by implicitly managing classloader-based package handling.
  • Updated Automation Package Provider: The AutomationPackageFromClassLoaderProvider no longer requires a ClassLoader in its constructor; it now internally creates an archive from the current application classloader.
  • Dedicated Local Function Handler: A new LocalFunctionHandler is introduced to specifically manage local functions, including the creation and extraction of automation package archives from the classloader for local execution.
  • JUnit Integration Updates: JUnit integration classes (JUnitPlansProvider, Step.java, StepJUnit5.java) are updated to explicitly use the new LOCAL_AUTOMATION_PACKAGE operation mode when configuring the ExecutionEngine.
  • Consolidated Local Mode Checks: A static helper method OperationMode.isLocal(OperationMode operationMode) is added to centralize checks for any local execution mode (LOCAL or LOCAL_AUTOMATION_PACKAGE), improving code readability and maintainability across plugins.
  • Enhanced Automation Package File Extraction: The retrieveAndExtractAutomationPackageFile method in AbstractFunctionHandler is refactored to use a new extractAutomationPackageFile helper, and the unzipping process now incorporates a resource filter from ClassLoaderArchiver.
  • New Test Keyword for AP Content Access: A new keyword MyKeywordUsingAutomationPackageFile has been added to MyKeywordLibraryAutopack to demonstrate and test accessing automation package content during local execution.
Changelog
  • pom.xml
    • Added a temporary local overwrite dependency for exense-basic-commons.
  • step-automation-packages/step-automation-packages-junit-core/src/main/java/step/automation/packages/junit/JUnitPlansProvider.java
    • Modified constructor for AutomationPackageFromClassLoaderProvider and removed withClasspathBased(true).
  • step-automation-packages/step-automation-packages-junit-core/src/main/java/step/engine/plugins/AutomationPackageLocalOSPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use isLocal(context.getOperationMode()).
  • step-automation-packages/step-automation-packages-junit-core/src/main/java/step/engine/plugins/ParameterManagerLocalPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use !isLocal(executionEngineContext.getOperationMode()).
  • step-automation-packages/step-automation-packages-junit/src/main/java/step/junit/runner/Step.java
    • Imported OperationMode and set withOperationMode(OperationMode.LOCAL_AUTOMATION_PACKAGE) in ExecutionEngine.builder().
  • step-automation-packages/step-automation-packages-junit5/src/main/java/step/junit5/runner/StepJUnit5.java
    • Imported OperationMode and set withOperationMode(OperationMode.LOCAL_AUTOMATION_PACKAGE) in ExecutionEngine.builder().
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageFromClassLoaderProvider.java
    • Removed classLoader field and constructor parameter.
    • Updated getAutomationPackageArchive to use a parameterless JavaAutomationPackageArchive constructor.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageManager.java
    • Removed isClasspathBased parameter from readAutomationPackage calls.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageReader.java
    • Removed isClasspathBased parameter from readAutomationPackage methods and buildAutomationPackage method.
    • Updated archive.getOriginalFileName() to archive.getAutomationPackageName() in descriptor reading.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageResourceManager.java
    • Removed conditional block related to originalFile == null for local execution.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageUpdateParameter.java
    • Removed isClasspathBased field and constructor parameter.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/AutomationPackageUpdateParameterBuilder.java
    • Removed isClasspathBased field and withClasspathBased method.
    • Removed isClasspathBased assignment in forRedeployPackage and build methods.
  • step-automation-packages/step-automation-packages-manager/src/main/java/step/automation/packages/JavaAutomationPackageReader.java
    • Removed isClasspathBased parameter from fillAutomationPackageWithAnnotatedKeywordsAndPlans and extractAnnotatedKeywords methods.
    • Updated log messages to use archive.getAutomationPackageName().
    • Simplified keyword creation logic by removing the isClasspathBased condition.
  • step-automation-packages/step-automation-packages-samples/step-automation-packages-sample-junit/src/main/java/step/automation/packages/functions/MyKeywordLibraryAutopack.java
    • Added imports for File, Arrays, Objects.
    • Added a new keyword MyKeywordUsingAutomationPackageFile to test automation package file retrieval.
  • step-automation-packages/step-automation-packages-samples/step-automation-packages-sample-junit/src/main/resources/plans.yml
    • Added a call to the new MyKeywordUsingAutomationPackageFile keyword.
  • step-automation-packages/step-automation-packages-yaml/src/main/java/step/automation/packages/yaml/AutomationPackageDescriptorReader.java
    • Renamed packageFileName parameter to packageName in several methods and updated log messages accordingly.
  • step-core/src/main/java/step/automation/packages/AutomationPackageArchive.java
    • Removed the constructor that took only type and set originalFile and keywordLibFile to null.
  • step-core/src/main/java/step/automation/packages/ClassLoaderResourceFilesystem.java
    • Modified extractDirectory to correctly handle directories when copying resources.
  • step-core/src/main/java/step/automation/packages/JavaAutomationPackageArchive.java
    • Added imports for ClassLoaderArchiver and FileHelper.
    • Added a new parameterless constructor that creates an archive from the classloader.
    • Simplified createAnnotationScanner to always use forSpecificJarFromURLClassLoader.
  • step-functions-plugins/step-functions-plugins-composite/step-functions-plugins-local-composite/src/main/java/step/plugins/functions/types/LocalCompositeFunctionPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use isLocal(operationMode).
    • Added a conditional check to saveLocalFunctions() to only run if not in LOCAL_AUTOMATION_PACKAGE mode.
  • step-functions-plugins/step-functions-plugins-java/step-functions-plugins-java-def/src/main/java/step/plugins/java/GeneralScriptFunctionPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use isLocal(context.getOperationMode()).
  • step-functions-plugins/step-functions-plugins-jmeter/step-functions-plugins-jmeter-def/src/main/java/step/plugins/jmeter/JMeterFunctionTypeLocalPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use isLocal(context.getOperationMode()).
  • step-functions-plugins/step-functions-plugins-node/step-functions-plugins-node-def/src/main/java/step/plugins/node/NodeLocalPlugin.java
    • Imported OperationMode.isLocal and updated if condition to use isLocal(context.getOperationMode()).
  • step-functions/step-functions-handler/src/main/java/step/functions/handler/AbstractFunctionHandler.java
    • Imported ClassLoaderArchiver and Nullable.
    • Refactored retrieveAndExtractAutomationPackageFile to call a new extractAutomationPackageFile method.
    • Updated FileHelper.unzip to use ClassLoaderArchiver.getResourceFilter().
  • step-plans/step-plans-base-artefacts/src/main/java/step/artefacts/handlers/CallFunctionHandler.java
    • Imported OperationMode.isLocal and updated forceLocalToken assignment to use isLocal(context.getOperationMode()).
  • step-plans/step-plans-base-artefacts/src/main/java/step/engine/plugins/LocalFunctionHandler.java
    • Added a new file LocalFunctionHandler.java which extends KeywordHandler and overrides retrieveAndExtractAutomationPackageFile and containsAutomationPackageFileReference to handle local function archives.
  • step-plans/step-plans-base-artefacts/src/main/java/step/engine/plugins/LocalFunctionPlugin.java
    • Removed import for KeywordHandler.
    • Imported OperationMode.isLocal.
    • Updated initializeExecutionEngineContext to use isLocal(operationMode) and conditionally save local functions.
    • Changed getHandlerChain to return LocalFunctionHandler.class.getName().
  • step-plans/step-plans-core/src/main/java/step/core/execution/OperationMode.java
    • Added new enum value LOCAL_AUTOMATION_PACKAGE.
    • Added a static helper method isLocal(OperationMode operationMode).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the local execution of Automation Packages, particularly for JUnit runners, to better support keywords that need to access AP content. It introduces a new LOCAL_AUTOMATION_PACKAGE operation mode and a mechanism to create a temporary physical archive from the classpath. This allows local executions to behave more like remote ones. The isClasspathBased flag has been removed, and many parts of the code have been updated to use the new OperationMode.isLocal() helper.

My review has identified a critical issue in pom.xml where a temporary snapshot dependency must be removed before merging. I also found an opportunity to improve null handling in a new sample keyword by adhering to our non-null contract guidelines, and a minor issue with silent error handling during temporary file cleanup. The rest of the changes appear to be a solid and consistent implementation of the new local execution strategy.

Comment on lines +408 to +413
<!-- TODO local overwrite of exense-commons, delete before merge -->
<dependency>
<groupId>ch.exense.commons</groupId>
<artifactId>exense-basic-commons</artifactId>
<version>0.0.0-SED-4555-SNAPSHOT</version>
</dependency>

Choose a reason for hiding this comment

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

critical

This temporary dependency and the associated TODO comment should be removed before this pull request is merged. Leaving snapshot dependencies, especially with local overwrites, can cause build instability and conflicts for other developers.

output.startMeasure("retrieving AP content");
File automationPackageFile = retrieveAndExtractAutomationPackage();
output.stopMeasure();
String[] list = Objects.requireNonNull(automationPackageFile.list());

Choose a reason for hiding this comment

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

high

According to repository guidelines, we prefer enforcing non-null contracts for critical parameters by fixing callers, rather than adding defensive null checks. The retrieveAndExtractAutomationPackage() method should ideally not return null if an automation package is expected. Please investigate why retrieveAndExtractAutomationPackage() can return null and address the root cause, either by ensuring it never returns null under valid conditions or by clearly defining its nullability contract and handling it at the appropriate level, potentially upstream. If automationPackageFile.list() can return null, it suggests automationPackageFile might not be a valid directory, which also points to an issue in the package retrieval/extraction logic.

References
  1. Prefer enforcing non-null contracts for critical parameters (e.g., execution context, execution ID) by fixing callers, rather than adding defensive null checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does not make sense, the requireNonNull is applied to the results of File.list on which we have no control.

Comment on lines +44 to +48
public void close() {
if (temporaryFile != null && temporaryFile.exists()) {
temporaryFile.delete();
}
}

Choose a reason for hiding this comment

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

medium

The close() method silently ignores the return value of temporaryFile.delete(). If the file deletion fails (e.g., due to permissions or the file being in use), it would be beneficial to log a warning. This would help in diagnosing issues with leftover temporary files.

import java.io.IOException;
import java.util.Map;

public class LocalFunctionHandler extends KeywordHandler {
Copy link
Contributor

Choose a reason for hiding this comment

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

I have the impression that this class isn't required anymore

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