feat: build and install Seriatim from source
This commit is contained in:
27
README.md
27
README.md
@@ -4,8 +4,8 @@ Installs the [Seriatim](https://gitea.maximumdirect.net/eric/seriatim)
|
|||||||
transcript processor from source. The role supports Ubuntu 26.04 on `amd64`
|
transcript processor from source. The role supports Ubuntu 26.04 on `amd64`
|
||||||
and `arm64` hosts and is independently usable outside the D&D pipeline role.
|
and `arm64` hosts and is independently usable outside the D&D pipeline role.
|
||||||
|
|
||||||
The role manages its build dependencies and a root-owned source checkout. At
|
The role manages its build dependencies and a root-owned source checkout,
|
||||||
this point binary installation is added by subsequent implementation work.
|
builds a native static executable, validates it, and safely installs it.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -49,6 +49,29 @@ provided independently through the managed host's Git configuration or SSH
|
|||||||
environment; this role does not manage credentials or accept unknown host
|
environment; this role does not manage credentials or accept unknown host
|
||||||
keys.
|
keys.
|
||||||
|
|
||||||
|
## Build and installation behavior
|
||||||
|
|
||||||
|
Builds run from the selected checkout with `GOWORK=off`,
|
||||||
|
`GOTOOLCHAIN=local`, `CGO_ENABLED=0`, the configured ordered build flags, and
|
||||||
|
the upstream version-injection linker flags. The resulting executable is
|
||||||
|
staged and must report the exact configured version before it atomically
|
||||||
|
replaces `seriatim_binary_path`. It is installed as `root:root` mode `0755`.
|
||||||
|
|
||||||
|
The role records readable inputs, their SHA-256 fingerprint, and the installed
|
||||||
|
binary checksum beneath `seriatim_build_state_dir`. A source commit, compiler
|
||||||
|
identity, Go path, version, flags, linker flags, package, or fixed environment
|
||||||
|
change triggers a rebuild. Missing or corrupt state, a modified binary, or an
|
||||||
|
incorrect installed version also triggers rebuilding. Failed compilation or
|
||||||
|
staged validation leaves the previous installed binary and successful state
|
||||||
|
untouched.
|
||||||
|
|
||||||
|
For example, development from a branch must identify both source and output:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
seriatim_source_ref: feature/example
|
||||||
|
seriatim_build_version: v1.5.0-dev
|
||||||
|
```
|
||||||
|
|
||||||
## Static validation
|
## Static validation
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
189
tasks/build.yml
Normal file
189
tasks/build.yml
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
---
|
||||||
|
- name: Construct canonical Seriatim build inputs
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
seriatim_build_inputs: >-
|
||||||
|
{{ {
|
||||||
|
'source_commit': seriatim_source_commit,
|
||||||
|
'go_version': seriatim_go_version_result.stdout,
|
||||||
|
'go_binary': seriatim_go_binary,
|
||||||
|
'build_version': seriatim_build_version,
|
||||||
|
'build_flags': seriatim_go_build_flags,
|
||||||
|
'ldflags': seriatim_go_ldflags,
|
||||||
|
'package': seriatim_go_package,
|
||||||
|
'environment': {
|
||||||
|
'GOWORK': 'off',
|
||||||
|
'GOTOOLCHAIN': 'local',
|
||||||
|
'CGO_ENABLED': '0'
|
||||||
|
}
|
||||||
|
} | to_nice_json(indent=2, sort_keys=true) }}
|
||||||
|
|
||||||
|
- name: Calculate desired Seriatim build fingerprint
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
seriatim_desired_fingerprint: "{{ seriatim_build_inputs | hash('sha256') }}"
|
||||||
|
seriatim_stored_fingerprint: ""
|
||||||
|
seriatim_stored_checksum: ""
|
||||||
|
|
||||||
|
- name: Inspect installed Seriatim binary
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ seriatim_binary_path }}"
|
||||||
|
checksum_algorithm: sha256
|
||||||
|
register: seriatim_installed_binary_stat
|
||||||
|
|
||||||
|
- name: Inspect Seriatim build input state
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ seriatim_build_state_dir }}/build-inputs.json"
|
||||||
|
register: seriatim_build_inputs_state_stat
|
||||||
|
|
||||||
|
- name: Inspect Seriatim fingerprint state
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ seriatim_build_state_dir }}/fingerprint.sha256"
|
||||||
|
register: seriatim_fingerprint_state_stat
|
||||||
|
|
||||||
|
- name: Inspect Seriatim checksum state
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ seriatim_build_state_dir }}/binary.sha256"
|
||||||
|
register: seriatim_checksum_state_stat
|
||||||
|
|
||||||
|
- name: Read stored Seriatim fingerprint
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ seriatim_build_state_dir }}/fingerprint.sha256"
|
||||||
|
register: seriatim_stored_fingerprint_result
|
||||||
|
when: seriatim_fingerprint_state_stat.stat.exists
|
||||||
|
|
||||||
|
- name: Read stored Seriatim checksum
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ seriatim_build_state_dir }}/binary.sha256"
|
||||||
|
register: seriatim_stored_checksum_result
|
||||||
|
when: seriatim_checksum_state_stat.stat.exists
|
||||||
|
|
||||||
|
- name: Record stored Seriatim state values
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
seriatim_stored_fingerprint: >-
|
||||||
|
{{ seriatim_stored_fingerprint_result.content | b64decode | trim }}
|
||||||
|
seriatim_stored_checksum: >-
|
||||||
|
{{ seriatim_stored_checksum_result.content | b64decode | trim }}
|
||||||
|
when:
|
||||||
|
- seriatim_fingerprint_state_stat.stat.exists
|
||||||
|
- seriatim_checksum_state_stat.stat.exists
|
||||||
|
|
||||||
|
- name: Read installed Seriatim version
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "{{ seriatim_binary_path }}"
|
||||||
|
- --version
|
||||||
|
register: seriatim_installed_version_result
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
when: seriatim_installed_binary_stat.stat.exists
|
||||||
|
|
||||||
|
- name: Decide whether Seriatim requires rebuilding
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
seriatim_build_required: >-
|
||||||
|
{{ not seriatim_installed_binary_stat.stat.exists
|
||||||
|
or not seriatim_build_inputs_state_stat.stat.exists
|
||||||
|
or not seriatim_fingerprint_state_stat.stat.exists
|
||||||
|
or not seriatim_checksum_state_stat.stat.exists
|
||||||
|
or seriatim_stored_fingerprint != seriatim_desired_fingerprint
|
||||||
|
or seriatim_stored_checksum != (seriatim_installed_binary_stat.stat.checksum | default(''))
|
||||||
|
or (seriatim_installed_version_result.rc | default(1)) != 0
|
||||||
|
or (seriatim_installed_version_result.stdout | default('')) != 'seriatim version ' ~ seriatim_build_version }}
|
||||||
|
|
||||||
|
- name: Build, validate, and install Seriatim
|
||||||
|
when: seriatim_build_required
|
||||||
|
block:
|
||||||
|
- name: Create temporary Seriatim build directory
|
||||||
|
ansible.builtin.tempfile:
|
||||||
|
state: directory
|
||||||
|
prefix: ansible-seriatim-build-
|
||||||
|
register: seriatim_build_tempdir
|
||||||
|
|
||||||
|
- name: Build staged Seriatim binary
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv: >-
|
||||||
|
{{ [seriatim_go_binary, 'build']
|
||||||
|
+ seriatim_go_build_flags
|
||||||
|
+ ['-ldflags', seriatim_go_ldflags,
|
||||||
|
'-o', seriatim_build_tempdir.path ~ '/seriatim',
|
||||||
|
seriatim_go_package] }}
|
||||||
|
chdir: "{{ seriatim_source_dir }}"
|
||||||
|
environment:
|
||||||
|
GOWORK: "off"
|
||||||
|
GOTOOLCHAIN: local
|
||||||
|
CGO_ENABLED: "0"
|
||||||
|
changed_when: true
|
||||||
|
|
||||||
|
- name: Validate staged Seriatim binary
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "{{ seriatim_build_tempdir.path }}/seriatim"
|
||||||
|
- --version
|
||||||
|
register: seriatim_staged_version_result
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >-
|
||||||
|
seriatim_staged_version_result.rc != 0 or
|
||||||
|
seriatim_staged_version_result.stdout != 'seriatim version ' ~ seriatim_build_version
|
||||||
|
|
||||||
|
- name: Install validated Seriatim binary
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ seriatim_build_tempdir.path }}/seriatim"
|
||||||
|
dest: "{{ seriatim_binary_path }}"
|
||||||
|
remote_src: true
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Validate installed Seriatim binary
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "{{ seriatim_binary_path }}"
|
||||||
|
- --version
|
||||||
|
register: seriatim_new_installed_version_result
|
||||||
|
changed_when: false
|
||||||
|
failed_when: >-
|
||||||
|
seriatim_new_installed_version_result.rc != 0 or
|
||||||
|
seriatim_new_installed_version_result.stdout != 'seriatim version ' ~ seriatim_build_version
|
||||||
|
|
||||||
|
- name: Calculate installed Seriatim checksum
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ seriatim_binary_path }}"
|
||||||
|
checksum_algorithm: sha256
|
||||||
|
register: seriatim_new_binary_stat
|
||||||
|
|
||||||
|
- name: Create Seriatim build state directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ seriatim_build_state_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Record Seriatim build inputs
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ seriatim_build_inputs }}\n"
|
||||||
|
dest: "{{ seriatim_build_state_dir }}/build-inputs.json"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Record Seriatim build fingerprint
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ seriatim_desired_fingerprint }}\n"
|
||||||
|
dest: "{{ seriatim_build_state_dir }}/fingerprint.sha256"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Record installed Seriatim checksum
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ seriatim_new_binary_stat.stat.checksum }}\n"
|
||||||
|
dest: "{{ seriatim_build_state_dir }}/binary.sha256"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove temporary Seriatim build directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ seriatim_build_tempdir.path }}"
|
||||||
|
state: absent
|
||||||
|
when: seriatim_build_tempdir.path is defined
|
||||||
@@ -7,3 +7,6 @@
|
|||||||
|
|
||||||
- name: Manage Seriatim source checkout
|
- name: Manage Seriatim source checkout
|
||||||
ansible.builtin.import_tasks: source.yml
|
ansible.builtin.import_tasks: source.yml
|
||||||
|
|
||||||
|
- name: Build and install Seriatim
|
||||||
|
ansible.builtin.import_tasks: build.yml
|
||||||
|
|||||||
Reference in New Issue
Block a user