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`
|
||||
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
|
||||
this point binary installation is added by subsequent implementation work.
|
||||
The role manages its build dependencies and a root-owned source checkout,
|
||||
builds a native static executable, validates it, and safely installs it.
|
||||
|
||||
## 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
|
||||
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
|
||||
|
||||
```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
|
||||
ansible.builtin.import_tasks: source.yml
|
||||
|
||||
- name: Build and install Seriatim
|
||||
ansible.builtin.import_tasks: build.yml
|
||||
|
||||
Reference in New Issue
Block a user