The "Relay Race" Pattern: Syncing Gradle Builds with Ansible in Tekton
In a modern CI/CD pipeline, passing a dynamic build number from a Gradle build to an Ansible deployment is like a relay race. The "baton" is your version string (e.g., 1.2.345), and if it’s dropped between the build stage and the deploy stage, the whole race stops.
Since you are running this inside Tekton, you have a structured way to hand off this data. Here is the architectural "story" of how to bridge that gap.
Step 1: The Producer (Gradle)
First, your Gradle build needs to "vocalize" the version it just created. Since your RPM task already knows the ${version}, we add a small helper task to write that specific string to a dedicated file in the workspace.
In your build.gradle:
// Create a simple task to 'announce' the version
task exportBuildMetadata {
doLast {
def versionFile = new File(projectDir, "build_metadata.txt")
versionFile.text = project.version.toString()
println ">>> Exported Version: ${project.version}"
}
}
// Ensure this runs automatically after your RPM is ready
buildRpm.finalizedBy exportBuildMetadata
Step 2: The Hand-Off (Tekton Results)
In Tekton, containers are ephemeral—they vanish after they finish. To keep the version string alive for the next step, we use Tekton Results. This acts as a "global variable" for the entire pipeline.
In your Tekton Task YAML:
spec:
results:
- name: rpm-version
description: "The dynamic build number generated by Gradle"
steps:
- name: run-gradle-build
image: gradle:jdk17
script: |
gradle buildRpm exportBuildMetadata
# 'cat' the file content into the special Tekton results path
cat build_metadata.txt > $(results.rpm-version.path)
Step 3: The Consumer (Ansible)
Now that the version is saved in the Pipeline's memory, we pass it into the Ansible task as a parameter. This removes the need for Ansible to "guess" the filename.
In your Tekton Pipeline YAML:
tasks:
- name: deploy-to-env
taskRef:
name: ansible-deploy-task
params:
- name: build_number
value: $(tasks.run-gradle-build.results.rpm-version)
- name: rpm_prefix
value: "comet-bridge"
In your Ansible Playbook (deploy.yml):
Inside Ansible, you can now construct the exact filename using the variable passed from Tekton.
- name: Deploy the COMET RPM
hosts: target_servers
vars:
# Construct the full name using the prefix and the build_number from Tekton
rpm_filename: "{{ rpm_prefix }}-{{ build_number }}.rpm"
rpm_source_path: "/workspace/source/build/distributions/{{ rpm_filename }}"
tasks:
- name: Ensure RPM is present on the target
ansible.builtin.copy:
src: "{{ rpm_source_path }}"
dest: "/tmp/{{ rpm_filename }}"
- name: Install the specific build
ansible.builtin.yum:
name: "/tmp/{{ rpm_filename }}"
state: present
Why This is the "Gold Standard" for LightSpeed
- Single Source of Truth: The version is defined in one place (Gradle) and pushed forward. You never have to update your Ansible code when the version increments.
- Audit Trail: Because you used a Tekton Result, you can look at the Tekton Dashboard and see exactly which version was passed between tasks without opening logs.
- Loose Coupling: Ansible doesn't need to know how Gradle built the file; it just needs to know the "ID" of the result.
Pro-Tip for the "Picking" Alternative
If you cannot change your Tekton YAML, you can make Ansible "find" the file by looking for the prefix. In your Playbook, use the find module:
- name: Locate the newest RPM
ansible.builtin.find:
paths: "/workspace/source/build/distributions"
patterns: "comet-bridge-*.rpm"
register: rpm_files
- name: Identify the latest file
set_fact:
latest_rpm: "{{ rpm_files.files | sort(attribute='mtime') | last }}"
- name: Install discovered RPM
ansible.builtin.yum:
name: "{{ latest_rpm.path }}"
state: present
This "Picking" method is a great safety net if your build numbers aren't perfectly sequential or if you are running manual tests!
Top comments (0)