- ALM Octane plugins utilize the long-polling technique in order to fetch tasks from the ALM Octane server (the CI plugin periodically sends HTTP requests to the ALM Octane server).
- When the task result is ready - the CI plugin sends another HTTP request in order to notify ALM Octane with the result.
- In addition, the CI plugin sends build-time life-cycle events.
- Pipeline start/end events.
- Pipeline node start/end.
- SCM events.
- Requests are never directly sent from ALM Octane to the CI plugin.
- No continuously running processes can be added by Azure DevOps extensions
- The only allowed custom code execution is running custom build tasks contributed by extensions.
- Conclusion: the long-polling technique is not applicable to Azure DevOps.
- Service Endpoint types. Every service endpoint is:
- Filled out through auto-generated UI forms.
- Persisted at the project level.
- Can be passed as a parameter to any build task (builtin and custom).
- Can be queried for data in the task code.
- Custom Task types. Every custom task:
- Contains an executable code.
- Can be added to a build job.
- Can receive parameters.
- Pipeline Decorators. Every decorator adds a YML fragment that can:
- Contain any pipeline-related definitions.
- Be automatically added to the beginning of every job.
- Be automatically added to the end of every job.
- Depend on a condition.
In the current scope the following capabilities should be either disabled or reimplemented for the Azure DevOps CI Server type:
- Get list of CI servers available for connection (disabled by definition).
- Get list of pipelines for a particular CI server (disabled by definition).
- Get details of a particular pipeline (internal action - should be reimplemented).
- Start a particular pipeline (should be disabled).
Currently, actions triggered by Octane have the default implementation of queueing the appropriate tasks to be collected by the CI server plugins. Since this default implementation doesn't meet our needs, we suggest to develop "per CI server type" implementations where the fallback implementation is the default one.
Every implementation will be instantiated by a factory class based on the CI server type name. For example (pseudo-code):
In our case, the default task processor should keep queueing the tasks to wait for being collected by a CI server plugin while the Azure DevOps task processor should apply its own logic (fortunately for the upcoming release we don't need to invoke the Azure DevOps API).
TaskProcessor processor = TaskProcessorFactory.getTaskProcessor(ciServerType); if(processor != null) { processor.processTask(task); } else { TaskProcessorFactory.getDefaultProcessor().processTask(task); }
- The integration flow is driven by custom tasks auto-injected in runtime into every pipeline (utilizing the pipeline decorator capabilities).
- The tasks are written in TypeScript and compiled to JavaScript, following Microsoft's guidelines.
- @microfocus/alm-octane-js-rest-sdk node.js REST-client library is used in order to communicate with the ALM Octane server from the tasks' code.
- microsoft/azure-devops-node-api node.js REST-client library is used in order to communicate with the Azure DevOps server from the tasks' code.
- The user creates a new service endpoint of type "ALM Octane Server Connection" in the project settings. He provides the following attributes:
- Name
- Octane Server URL
- API Client ID
- API Client Secret
- CI Server Instance ID (optional)
- The user starts a build
- The build starts
- Two tasks, PipelineStartTask and PipelineEndTask, are auto-injected by the pipeline decorator to the beginning and the end of the pipeline accordingly.
- The first task executed by the build is the PipelineStartTask task. It takes care of:
- Creating the CI Server and Pipeline entities in ALM Octane if they don't exist.
- Sending pipeline start event to ALM Octane.
- The last task executed by the build is the PipelineEndTask task. It takes case of:
- Collecting test results from the build.
- Injecting test results.
- Sending pipeline end event to ALM Octane.
Action | Implementation |
---|---|
Check whether a CI Server already exists in Octane | Call Octane REST API |
Create a CI Server in Octane | Call Octane REST API |
Check whether a pipeline already exists in Octane | Call Octane REST API |
Create a pipeline in Octane | Call Octane REST API |
Send pipeline start event | Call Octane Internal API |
Action | Implementation |
---|---|
Collect test results | Call Azure Devops REST API |
Inject test results | Call Octane Internal API |
Send pipeline end event | Call Octane Internal API |
We need to find how to let a fragments injected by the pipeline decorator determine if it's the first task, the last task or an internal one.