Skip to content

Commit e6acbe1

Browse files
committed
bootlinux: add intelligent git repository detection and management
Add smart logic to infer when git clone is needed regardless of the bootlinux_tree_set_by_cli setting. This solves the issue where directories exist with files (like .config) but no .git repository, which previously caused the git clone to be skipped. The new logic: 1. Checks if the target directory exists 2. Checks if .git directory exists within it 3. Infers git clone is needed if directory exists but .git doesn't 4. Clones the repository even when bootlinux_tree_set_by_cli is true 5. Ensures the correct ref is checked out if git exists but on wrong ref This handles the common case where: - Directory is pre-created for 9p mount support - Configuration files are copied before git clone - bootlinux_tree_set_by_cli persists from previous runs The implementation also: - Fetches updates if the target ref doesn't exist locally - Switches to the correct ref if repository exists but is on wrong branch - Maintains backward compatibility with existing workflows - Applies consistently across all build methods (9p, targets, builder) This makes the system more robust and user-friendly by intelligently handling partial setups and recovering from incomplete states. Generated-by: Claude AI Signed-off-by: Luis Chamberlain <[email protected]>
1 parent ae7ec05 commit e6acbe1

File tree

3 files changed

+273
-42
lines changed

3 files changed

+273
-42
lines changed

playbooks/roles/bootlinux/tasks/build/9p.yml

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,55 @@
2626
run_once: true
2727
delegate_to: localhost
2828

29-
- name: Check if target directory exists when using 9p and Linux CLI was set
29+
- name: Check if target directory exists
3030
stat:
3131
path: "{{ bootlinux_9p_host_path }}"
3232
register: target_directory_stat
3333
run_once: true
3434
delegate_to: localhost
35+
36+
- name: Check if .git directory exists in target path
37+
stat:
38+
path: "{{ bootlinux_9p_host_path }}/.git"
39+
register: git_directory_stat
40+
run_once: true
41+
delegate_to: localhost
3542
when:
36-
- bootlinux_tree_set_by_cli|bool
43+
- target_directory_stat.stat.exists
3744

38-
- name: Fail if target directory does not exist when using 9p and Linux CLI was set
39-
fail:
40-
msg: "The target directory {{ bootlinux_9p_host_path }} does not exist."
45+
- name: Infer that git clone is needed when .git doesn't exist
46+
set_fact:
47+
needs_git_clone: true
48+
when:
49+
- target_directory_stat.stat.exists
50+
- not git_directory_stat.stat.exists
4151
run_once: true
4252
delegate_to: localhost
53+
54+
- name: Set needs_git_clone when directory doesn't exist
55+
set_fact:
56+
needs_git_clone: true
4357
when:
44-
- bootlinux_tree_set_by_cli|bool
4558
- not target_directory_stat.stat.exists
59+
run_once: true
60+
delegate_to: localhost
61+
62+
- name: Set needs_git_clone to false when .git exists
63+
set_fact:
64+
needs_git_clone: false
65+
when:
66+
- target_directory_stat.stat.exists
67+
- git_directory_stat.stat.exists
68+
run_once: true
69+
delegate_to: localhost
4670

4771
- name: Verify target git ref exists before cloning
4872
command: "git ls-remote {{ target_linux_git }} {{ active_linux_ref | default(target_linux_ref) }}"
4973
register: ref_check
5074
run_once: true
5175
delegate_to: localhost
5276
when:
53-
- not bootlinux_tree_set_by_cli|bool
77+
- needs_git_clone|bool
5478
tags: [ 'clone']
5579

5680
- name: Fail if git ref does not exist
@@ -68,20 +92,11 @@
6892
- If using A/B testing with different refs, ensure shallow cloning is disabled
6993
- The repository URL '{{ target_linux_git }}' is correct and accessible
7094
when:
71-
- not bootlinux_tree_set_by_cli|bool
95+
- needs_git_clone|bool
7296
- ref_check.rc != 0
7397
run_once: true
7498
delegate_to: localhost
7599

76-
- name: Check if target directory exists for dirty check
77-
stat:
78-
path: "{{ bootlinux_9p_host_path }}"
79-
register: git_dir_stat
80-
run_once: true
81-
delegate_to: localhost
82-
when:
83-
- not bootlinux_tree_set_by_cli|bool
84-
85100
- name: Check if git tree is dirty
86101
command: "git -C {{ bootlinux_9p_host_path }} status --porcelain"
87102
register: git_status
@@ -90,9 +105,9 @@
90105
run_once: true
91106
delegate_to: localhost
92107
when:
93-
- not bootlinux_tree_set_by_cli|bool
94-
- git_dir_stat.stat.exists
95-
- git_dir_stat.stat.isdir
108+
- not needs_git_clone|bool
109+
- target_directory_stat.stat.exists
110+
- git_directory_stat.stat.exists
96111

97112
- name: Fail if git tree has local modifications
98113
fail:
@@ -109,9 +124,9 @@
109124
Modified files:
110125
{{ git_status.stdout }}
111126
when:
112-
- not bootlinux_tree_set_by_cli|bool
113-
- git_dir_stat.stat.exists
114-
- git_dir_stat.stat.isdir
127+
- not needs_git_clone|bool
128+
- target_directory_stat.stat.exists
129+
- git_directory_stat.stat.exists
115130
- git_status.stdout | length > 0
116131
run_once: true
117132
delegate_to: localhost
@@ -129,9 +144,65 @@
129144
until: not result.failed
130145
tags: [ 'clone']
131146
when:
132-
- not bootlinux_tree_set_by_cli|bool
147+
- needs_git_clone|bool
148+
run_once: true
149+
delegate_to: localhost
150+
151+
- name: Get current git ref when git exists but clone wasn't needed
152+
command: "git -C {{ bootlinux_9p_host_path }} rev-parse HEAD"
153+
register: current_ref
154+
changed_when: false
155+
run_once: true
156+
delegate_to: localhost
157+
when:
158+
- not needs_git_clone|bool
159+
- target_directory_stat.stat.exists
160+
- git_directory_stat.stat.exists
161+
162+
- name: Get target ref SHA
163+
command: "git -C {{ bootlinux_9p_host_path }} rev-parse {{ active_linux_ref | default(target_linux_ref) }}"
164+
register: target_ref_sha
165+
changed_when: false
166+
failed_when: false
133167
run_once: true
134168
delegate_to: localhost
169+
when:
170+
- not needs_git_clone|bool
171+
- target_directory_stat.stat.exists
172+
- git_directory_stat.stat.exists
173+
174+
- name: Fetch updates if target ref doesn't exist locally
175+
command: "git -C {{ bootlinux_9p_host_path }} fetch origin"
176+
run_once: true
177+
delegate_to: localhost
178+
when:
179+
- not needs_git_clone|bool
180+
- target_directory_stat.stat.exists
181+
- git_directory_stat.stat.exists
182+
- target_ref_sha.rc != 0
183+
184+
- name: Get target ref SHA after fetch
185+
command: "git -C {{ bootlinux_9p_host_path }} rev-parse {{ active_linux_ref | default(target_linux_ref) }}"
186+
register: target_ref_sha_after_fetch
187+
changed_when: false
188+
run_once: true
189+
delegate_to: localhost
190+
when:
191+
- not needs_git_clone|bool
192+
- target_directory_stat.stat.exists
193+
- git_directory_stat.stat.exists
194+
- target_ref_sha.rc != 0
195+
196+
- name: Checkout target ref if not on correct ref
197+
command: "git -C {{ bootlinux_9p_host_path }} checkout {{ active_linux_ref | default(target_linux_ref) }}"
198+
run_once: true
199+
delegate_to: localhost
200+
when:
201+
- not needs_git_clone|bool
202+
- target_directory_stat.stat.exists
203+
- git_directory_stat.stat.exists
204+
- (target_ref_sha.rc == 0 and current_ref.stdout != target_ref_sha.stdout) or
205+
(target_ref_sha.rc != 0 and target_ref_sha_after_fetch is defined and target_ref_sha_after_fetch.rc == 0)
135206

136207
- name: Copy kernel delta if requested on the control node
137208
template:

playbooks/roles/bootlinux/tasks/build/builder.yml

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,43 @@
1010
- target_linux_install_b4
1111
- ansible_os_family == "Debian"
1212

13+
- name: Check if target directory exists
14+
stat:
15+
path: "{{ target_linux_dir_path }}"
16+
register: target_directory_stat
17+
18+
- name: Check if .git directory exists in target path
19+
stat:
20+
path: "{{ target_linux_dir_path }}/.git"
21+
register: git_directory_stat
22+
when:
23+
- target_directory_stat.stat.exists
24+
25+
- name: Infer that git clone is needed when .git doesn't exist
26+
set_fact:
27+
needs_git_clone: true
28+
when:
29+
- target_directory_stat.stat.exists
30+
- not git_directory_stat.stat.exists
31+
32+
- name: Set needs_git_clone when directory doesn't exist
33+
set_fact:
34+
needs_git_clone: true
35+
when:
36+
- not target_directory_stat.stat.exists
37+
38+
- name: Set needs_git_clone to false when .git exists
39+
set_fact:
40+
needs_git_clone: false
41+
when:
42+
- target_directory_stat.stat.exists
43+
- git_directory_stat.stat.exists
44+
1345
- name: Verify target git ref exists before cloning
1446
command: "git ls-remote {{ target_linux_git }} {{ target_linux_ref }}"
1547
register: ref_check
48+
when:
49+
- needs_git_clone|bool
1650

1751
- name: Fail if git ref does not exist
1852
fail:
@@ -29,21 +63,18 @@
2963
- If using A/B testing with different refs, ensure shallow cloning is disabled
3064
- The repository URL '{{ target_linux_git }}' is correct and accessible
3165
when:
66+
- needs_git_clone|bool
3267
- ref_check.rc != 0
3368

34-
- name: Check if target directory exists for dirty check
35-
stat:
36-
path: "{{ target_linux_dir_path }}"
37-
register: git_dir_stat
38-
3969
- name: Check if git tree is dirty
4070
command: "git -C {{ target_linux_dir_path }} status --porcelain"
4171
register: git_status
4272
changed_when: false
4373
failed_when: false
4474
when:
45-
- git_dir_stat.stat.exists
46-
- git_dir_stat.stat.isdir
75+
- not needs_git_clone|bool
76+
- target_directory_stat.stat.exists
77+
- git_directory_stat.stat.exists
4778

4879
- name: Fail if git tree has local modifications
4980
fail:
@@ -60,8 +91,9 @@
6091
Modified files:
6192
{{ git_status.stdout }}
6293
when:
63-
- git_dir_stat.stat.exists
64-
- git_dir_stat.stat.isdir
94+
- not needs_git_clone|bool
95+
- target_directory_stat.stat.exists
96+
- git_directory_stat.stat.exists
6597
- git_status.stdout | length > 0
6698

6799
- name: Clone {{ target_linux_tree }}
@@ -75,6 +107,54 @@
75107
retries: 3
76108
delay: 5
77109
until: result is succeeded
110+
when:
111+
- needs_git_clone|bool
112+
113+
- name: Get current git ref when git exists but clone wasn't needed
114+
command: "git -C {{ target_linux_dir_path }} rev-parse HEAD"
115+
register: current_ref
116+
changed_when: false
117+
when:
118+
- not needs_git_clone|bool
119+
- target_directory_stat.stat.exists
120+
- git_directory_stat.stat.exists
121+
122+
- name: Get target ref SHA
123+
command: "git -C {{ target_linux_dir_path }} rev-parse {{ target_linux_ref }}"
124+
register: target_ref_sha
125+
changed_when: false
126+
failed_when: false
127+
when:
128+
- not needs_git_clone|bool
129+
- target_directory_stat.stat.exists
130+
- git_directory_stat.stat.exists
131+
132+
- name: Fetch updates if target ref doesn't exist locally
133+
command: "git -C {{ target_linux_dir_path }} fetch origin"
134+
when:
135+
- not needs_git_clone|bool
136+
- target_directory_stat.stat.exists
137+
- git_directory_stat.stat.exists
138+
- target_ref_sha.rc != 0
139+
140+
- name: Get target ref SHA after fetch
141+
command: "git -C {{ target_linux_dir_path }} rev-parse {{ target_linux_ref }}"
142+
register: target_ref_sha_after_fetch
143+
changed_when: false
144+
when:
145+
- not needs_git_clone|bool
146+
- target_directory_stat.stat.exists
147+
- git_directory_stat.stat.exists
148+
- target_ref_sha.rc != 0
149+
150+
- name: Checkout target ref if not on correct ref
151+
command: "git -C {{ target_linux_dir_path }} checkout {{ target_linux_ref }}"
152+
when:
153+
- not needs_git_clone|bool
154+
- target_directory_stat.stat.exists
155+
- git_directory_stat.stat.exists
156+
- (target_ref_sha.rc == 0 and current_ref.stdout != target_ref_sha.stdout) or
157+
(target_ref_sha.rc != 0 and target_ref_sha_after_fetch is defined and target_ref_sha_after_fetch.rc == 0)
78158

79159
- name: Copy the kernel delta to the builder
80160
ansible.builtin.template:

0 commit comments

Comments
 (0)