You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible脚本实现GitLab Runner升级前等待无运行作业的问题

解决Ansible中GitLab Runner运行中作业检查的循环等待问题

问题场景

编写Ansible Playbook升级本地GitLab Runner,流程为:暂停虚拟机上的Runner→确认无运行中作业(通过GitLab API)→补丁/升级→恢复Runner。暂停和恢复步骤已实现,但作业检查环节触发报错。

原代码及报错

尝试用以下代码循环检查Runner的运行中作业:

- name: Wait for No Running Jobs
  uri:
    url: "{{ api_base_url }}/runners/{{ item.id }}/jobs?status=running"
    headers:
      PRIVATE-TOKEN: "{{ PRIVATE_TOKEN }}"
  register: job_list
  with_items: "{{ host_runner_ids.json }}"
  until: job_list.results | json_query('[*].json[*]') | first | length == 0

持续触发错误:

The error was: Unexpected templating type error occurred on ({% if job_list.results | json_query('[].json[]') | first | length <= 20 %} True {% else %} False {% endif %}): 'NoneType' object is not iterable.

移除until条件后,通过debug任务可正常获取每个Runner的运行作业数:

- name: debug job list
  debug:
    msg: "{{ job_list.results | json_query('[*].json[*]') | first | length }}"
  with_items: "{{ host_runner_ids.json }}"

错误原因

  1. 首次执行时变量未初始化:任务第一次运行时,job_list还未被注册,job_list.results为None,此时用json_query处理会触发NoneType不可迭代的错误。
  2. 逻辑覆盖不全:原until条件仅检查第一个Runner的作业数,未验证所有Runner均无运行作业,不符合升级前的安全要求。

解决方案

方案1:逐个等待每个Runner无作业(推荐,逻辑清晰)

针对每个Runner单独发起API请求并等待,避免批量注册变量的初始化问题:

- name: Wait for each Runner to finish all running jobs
  uri:
    url: "{{ api_base_url }}/runners/{{ item }}/jobs?status=running"
    headers:
      PRIVATE-TOKEN: "{{ PRIVATE_TOKEN }}"
  register: single_runner_jobs
  until: single_runner_jobs.json | length == 0
  retries: 30  # 根据作业平均时长调整重试次数
  delay: 60    # 每次检查间隔60秒
  loop: "{{ host_runner_ids.json | map(attribute='id') | list }}"
  • 用loop替代with_items(Ansible官方推荐),先提取所有Runner的ID列表
  • 每个循环单独注册single_runner_jobs,首次执行时即可正常获取API返回结果
  • 直接检查当前Runner的作业列表长度,直到为0再进入下一个Runner的检查

方案2:批量检查所有Runner(处理初始化问题)

如果需要批量获取所有Runner状态,需先判断变量是否存在,再验证全部Runner无作业:

- name: Wait for all Runners to have no running jobs
  uri:
    url: "{{ api_base_url }}/runners/{{ item.id }}/jobs?status=running"
    headers:
      PRIVATE-TOKEN: "{{ PRIVATE_TOKEN }}"
  register: job_list
  loop: "{{ host_runner_ids.json }}"
  until: >
    job_list is defined
    and job_list.results is defined
    and job_list.results | json_query('[*].json | length(@)') | max == 0
  retries: 30
  delay: 60
  • 先通过job_list is defined和job_list.results is defined避免首次执行的None错误
  • 用json_query('[*].json | length(@)')提取每个Runner的作业数量列表,再取最大值,当最大值为0时说明所有Runner均无运行作业

注意事项

  • 根据实际环境中作业的平均运行时长,调整retries和delay参数,确保等待时间充足
  • 如果GitLab API返回的作业列表嵌套在json.jobs字段下,需修改json_query路径为[*].json.jobs | length(@)

内容的提问来源于stack exchange,提问作者JScott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:43:29