国内虚拟机对接 Freedesktop:Fork xserver、自建 Runner 与提交 MR 实战
适用场景:需要向 gitlab.freedesktop.org(简称 FDO)上的
xorg/xserver贡献代码,但本地是国内网络 + 性能一般的虚拟机,希望自己跑通「类上游」CI,再正式开 Merge Request。本文按真实踩坑顺序记录:账号与 Fork → 鉴权推送与 MR → Docker / Runner 安装与注册 → debug 分支改
.gitlab-ci.yml→ 常见故障排查。功能本身只作背景一笔带过。
一、背景与整体路线
上游 xserver 现以 GitLab MR 为主要合入方式(目标分支一般是 main ,不是旧的 master)。国内环境常见卡点有:
- 访问
gitlab.freedesktop.org/ 拉官方 CI 镜像慢或不稳定 - 官方共享 Runner 排队或权限限制,想在自己机器上验编译与测试
- 虚拟机 CPU/内存偏弱,跑不全量 ASAN / Piglit 容易超时
因此较稳妥的路线是:
text
注册 FDO 账号
→ Fork xorg/xserver 到个人命名空间
→ 配置 SSH Key 或 Personal Access Token
→ 功能分支推送到自己的 Fork,再对上游开 MR
→(可选)在 Ubuntu 虚拟机上自建 gitlab-runner
→ 用独立 debug 分支改 .gitlab-ci.yml,打上自建 Runner 的 tag
→ 验证联动成功后,正式 MR 分支保持干净,不要带本地 CI 覆盖
功能侧本次只是给 Xorg 增加了一个与 libglvnd 相关的配置项(DRISWRAST 回退路径下覆盖客户端 vendor 广告名),下文不展开实现细节,重点写基础设施与提交流程。
二、FDO 账号、Fork 与仓库权限
2.1 注册 / 登录
- 打开 https://gitlab.freedesktop.org
- 注册并完成邮箱验证(FDO 有时会对新账号有审核或限流,耐心等待即可)
- 登录后完善 Profile(显示名、公开邮箱等,提交时
Signed-off-by/ 作者信息建议与之一致)
2.2 Fork xserver
- 打开官方仓:https://gitlab.freedesktop.org/xorg/xserver
- 右上角 Fork,Fork 到自己的命名空间
- 得到个人仓库,形如:
text
https://gitlab.freedesktop.org/<你的用户名>/xserver
示例(本文叙述中用到的个人 Fork):
text
https://gitlab.freedesktop.org/daemon.qiang/xserver
2.3 关于「申请权限」
- 往自己的 Fork 推代码:Fork 完成后默认就有 Developer/Maintainer 权限,一般不需要再申请。
- 往上游
xorg/xserver直接 push :普通人通常没有 写权限,正确姿势是 MR,而不是申请写官方仓。 - 若网页 Fork 按钮灰掉、或组织策略限制:到 FDO 相关 issue / 邮件列表说明用途,或确认账号是否已通过审核。
三、鉴权:SSH Key 或 Token,以及如何推送
推送到 FDO 推荐两种方式,任选其一即可。
3.1 方式 A:SSH Key(适合长期贡献)
本机生成密钥(若还没有):
bash
ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519_fdo
把公钥加到 GitLab:
- 复制
~/.ssh/id_ed25519_fdo.pub内容 - GitLab → Preferences → SSH Keys → 粘贴并保存
可选:~/.ssh/config 指定 Host:
sshconfig
Host gitlab.freedesktop.org
HostName gitlab.freedesktop.org
User git
IdentityFile ~/.ssh/id_ed25519_fdo
IdentitiesOnly yes
连通性测试:
bash
ssh -T git@gitlab.freedesktop.org
# 成功时会看到 Welcome to GitLab, @你的用户名!
添加 remote 并推送:
bash
cd /path/to/xserver
git remote add fork git@gitlab.freedesktop.org:<你的用户名>/xserver.git
# 若已存在:
# git remote set-url fork git@gitlab.freedesktop.org:<你的用户名>/xserver.git
git push -u fork <你的功能分支名>
3.2 方式 B:HTTPS + Personal Access Token(SSH 不通时常用)
- GitLab → Preferences → Access Tokens
- 新建 Token,至少勾选:
write_repository(开 MR、读 API 可再加api) - 只显示一次,务必本地安全保存,不要写进仓库、不要贴到公开文章/截图里
推送示例:
bash
git remote add fork https://gitlab.freedesktop.org/<你的用户名>/xserver.git
# 用户名填 GitLab 用户名,密码处粘贴 Token
git push -u fork <你的功能分支名>
也可把 Token 配进凭据助手 / GIT_ASKPASS,避免每次交互输入。
3.3 本地 remote 建议布局
bash
git remote -v
# origin → 可指向官方只读镜像,或你自己的习惯源
# upstream → https://gitlab.freedesktop.org/xorg/xserver.git (官方)
# fork → 你的个人 Fork(真正 push 目标)
功能开发建议:
bash
git fetch upstream
git checkout -b glx-client-vendor-fallback upstream/main # 或 origin/main
# ... 开发、commit ...
git push -u fork glx-client-vendor-fallback
注意: 自建 Runner 调试用的 local-runner-debug 分支,和正式功能分支 分开 ,避免把 .gitlab-ci.yml 的本地覆盖带进上游 MR。
四、写 MR 并提交上游
推送成功后:
- 打开自己的 Fork 页面,GitLab 通常会提示 Create merge request
- 或手动:Fork 仓 → Merge requests → New merge request
- 关键配置:
| 项 | 建议 |
|---|---|
| Source | <你的用户名>/xserver → 功能分支 |
| Target | xorg/xserver → main |
| Title | 简洁说明改动,例如 glx: Add Option "GlxClientVendorFallback" for DRISWRAST |
| Description | 动机、行为、测试方法;可附 xorg.conf 示例 |
| Commit | 建议带 Signed-off-by:(DCO) |
MR 描述不必写 Runner 搭建过程;评审关心的是行为是否正确、是否破坏默认路径、测了什么。
创建 MR 后,上游 CI 会按官方 .gitlab-ci.yml 调度。若你只是想在弱机上先自测,见下一节「自建 Runner + debug 分支」。
五、自建 GitLab Runner(Ubuntu 24.04 虚拟机)
下文环境假设:
- 宿主机/开发机在内网
- Runner 跑在一台 Ubuntu 24.04 虚拟机(性能一般)
- 执行器使用 Docker,尽量贴近 FDO 官方 job(官方 job 本身就是 Docker 镜像里编测)
5.1 安装 Docker,并配置国内镜像
官方镜像在国内拉取 registry.freedesktop.org/... 以及基础层时经常很慢,建议先给 Docker 配镜像加速(具体镜像地址按你司/云厂商文档替换):
bash
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.ccs.tencentyun.com",
"https://docker.mirrors.ustc.edu.cn",
"https://ueo0uggy.mirror.aliyuncs.com",
"https://docker.m.daocloud.io",
"https://cf-workers-docker-io-apl.pages.dev"
],
"dns": ["8.8.8.8", "114.114.114.114"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
docker info | grep -A5 'Registry Mirrors'
说明:
registry-mirrors:加速 Docker Hub 等公共镜像;FDO 自己的registry.freedesktop.org不一定走 mirror,但仍建议配好 DNS。dns:后面 Runner 容器里git clone gitlab.freedesktop.org失败时,优先查容器 DNS(见文末排错)。
把当前用户加入 docker 组(按需):
bash
sudo usermod -aG docker $USER
# 重新登录后生效
5.2 安装 gitlab-runner(国内可用腾讯相关包/文档路径)
官方源直连有时不稳定,实践中可按腾讯云开发者社区等国内文档,用 deb 包安装 gitlab-runner(版本号按当时可用版本调整):
bash
# 示例:下载对应架构的 deb 后安装(URL/文件名以你实际下载为准)
sudo mkdir -pv /opt/gitlab-runner && cd /opt/gitlab-runner
# wget <腾讯云或 GitLab Release 页面提供的 gitlab-runner_amd64.deb>
# 参考地址:https://mirrors.cloud.tencent.com/gitlab-runner/ubuntu/pool/main/g/gitlab-runner/gitlab-runner_19.3.3-1_amd64.deb
# https://mirrors.cloud.tencent.com/gitlab-runner/ubuntu/pool/main/g/gitlab-runner-helper-images/gitlab-runner-helper-#images_19.3.3-1_all.deb
sudo dpkg -i gitlab-runner_*.deb
# 若缺依赖:
sudo apt-get install -f -y
gitlab-runner --version
也可以走官方仓库脚本(网络允许时):
bash
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install -y gitlab-runner
5.3 在 FDO 项目里创建 Runner,拿到注册 Token
在你的 Fork 项目(或有权限的 Group)中:
- Settings → CI/CD → Runners → New project runner
- 勾选/填写:
- Tags:例如
local-fdo(后面.gitlab-ci.yml要用同一个 tag) - 可取消 "Run untagged jobs",避免误抢无关 job
- Tags:例如
- 复制 registration / authentication token(注意保密)
5.4 注册并写成可用的 Docker 执行器
bash
sudo gitlab-runner register \
--url https://gitlab.freedesktop.org \
--token "<你的 runner token>" \
--executor docker \
--docker-image debian:bookworm-slim \
--description "ubuntu2404-fdo-like" \
--tag-list "local-fdo" \
--docker-privileged \
--non-interactive
xserver 官方 CI 会拉自定义镜像、挂 cache、甚至用到 Docker-in-Docker 一类能力,因此常见还需要在 config.toml 里补强,例如:
toml
$ cat /etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "ubuntu2404-fdo-like"
url = "https://gitlab.freedesktop.org"
id = 13598
token = "<你的 runner token>""
token_obtained_at = 2026-09-17T08:47:27Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
AssumeRoleMaxConcurrency = 0
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "debian:bookworm-slim"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
dns = ["8.8.8.8", "114.114.114.114"]
volumes = [
"/cache:/cache",
"/var/run/docker.sock:/var/run/docker.sock"
]
volume_keep = false
shm_size = 0
network_mtu = 0
注意:
- 系统服务读的配置通常是
/etc/gitlab-runner/config.toml;若你用用户态~/.gitlab-runner/config.toml,要确认真正启动的是哪一份,否则改了不生效。 - 改完后:
bash
sudo gitlab-runner verify
sudo systemctl restart gitlab-runner
sudo gitlab-runner list
在 GitLab 网页上 Runner 应变为 Online ,且带 local-fdo tag。
5.5 验证「和 FDO 能联动」
最小验证:
- 在 Fork 上随便推一个带 CI 的分支,或网页 CI/CD → Pipelines → Run pipeline
- Job 日志里应出现:
Running on runner-... via <你的虚机主机名> - 能成功 Pull
registry.freedesktop.org/xorg/xserver/...官方 CI 镜像(第一次会很慢) - 能在容器里访问
gitlab.freedesktop.org(clone 依赖)
六、用独立分支改 .gitlab-ci.yml(不要污染正式 MR)
官方 .gitlab-ci.yml 默认把 job 调度到 FDO 共享基础设施(含 FreeBSD/KVM 等)。自建 Runner 只有 local-fdo tag,若不改配置会出现:
- Pipeline 空(workflow 规则不匹配你的触发方式)
- Job 卡在 pending(没有匹配 tag 的 Runner)
- FreeBSD 等 job 在本地根本跑不了
推荐做法:从功能分支或 main 再拉一个 local-runner-debug,只在这个分支末尾追加覆盖,验证完也不要合进正式 MR。
bash
git checkout -b local-runner-debug
# 编辑 .gitlab-ci.yml 末尾后:
git add .gitlab-ci.yml
git commit -m "ci: local-fdo runner overrides for debug only"
git push -u fork local-runner-debug
6.1 覆盖 workflow(避免 empty pipeline)
FDO 原有 workflow 对 push / MR 有特殊规则。本地调试建议在文件末尾再写一段 workflow(同名以后面为准),允许 push / web / MR:
yaml
# ===== local debug runner only (this branch) =====
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
6.2 默认打上自建 Runner 的 tag
yaml
default:
tags:
- local-fdo
这样大多数 job 都会落到你的虚机上。
6.3 跳过本地跑不了 / 太重的 job
GitLab 同名 job 整段覆盖 ,且即使用 rules: when: never,配置里也必须 仍有 script:(否则报错:config should implement the script:, run:, or trigger: keyword)。
正确写法(空壳 + never):
yaml
freebsd-image:
stage: docker-image
script:
- echo "skip freebsd-image on local-fdo runner"
rules:
- when: never
freebsd:
stage: build-and-test
script:
- echo "skip freebsd on local-fdo runner"
rules:
- when: never
# 弱虚拟机强烈建议跳过 ASAN 全量 pyxtest
meson-asan:
stage: build-and-test
script:
- echo "skip meson-asan on weak local runner"
rules:
- when: never
错误写法(会无法创建 Pipeline):
yaml
meson-asan:
rules:
- when: never
# → Unable to run pipeline
# jobs meson-asan config should implement the script:, run:, or trigger: keyword
可选地,还可以同样跳过 mingw-cross-build、xf86-driver-build-test、多个 meson 变体,只保留 debian-bookworm + 主 meson,进一步减压。
6.4 改完如何重新触发
- 网页打开失败的 Pipeline / Job → Retry
- 或 CI/CD → Pipelines → Run pipeline 选
local-runner-debug - 或空提交再 push:
bash
git commit --allow-empty -m "ci: retry"
git push
七、真实踩坑与排查(强烈建议收藏)
7.1 Pipeline 是空的 / 没有 jobs
- 检查是否覆盖了
workflow - 确认触发源是
push或web,而不只是被「已有 open MR 时禁止 push pipeline」之类规则挡住
7.2 Job pending:没有 Runner 接单
- 网页确认 Runner Online
- Job 的
tags是否包含local-fdo config.toml是否被服务真正加载
7.3 Could not resolve host: gitlab.freedesktop.org
镜像能 pull,但 job 里 git clone 失败 → 容器 DNS 问题。验证:
bash
# 宿主机
getent hosts gitlab.freedesktop.org
# 容器内(最关键)
docker run --rm debian:bookworm-slim getent hosts gitlab.freedesktop.org
修复:/etc/docker/daemon.json 的 dns,或 runners.docker.dns,然后重启 docker 与 gitlab-runner。
7.4 弱虚拟机上 meson-asan 大面积 pyxtest 超时
日志典型特征:
text
Timed out waiting for X server display number (waited 15s)
Failed to start xvfb server
编译(含 -Dwerror=true)往往已经成功;失败在 ASAN 下启动 Xvfb 过慢 / 并行过多 。
这与功能补丁逻辑通常无关。弱机策略:直接 skip meson-asan ,主看 meson job。
7.5 正式 MR 分支保持干净
local-runner-debug 上的 workflow / default.tags / skip 规则 不要 cherry-pick 进功能分支。
上游评审应跑官方共享 CI;本地 Runner 只是你的预检环境。
7.6 Token / 密钥安全
- Runner token、Personal Access Token、SSH 私钥不要进 git
- 若曾误贴到聊天或日志,到 GitLab 立刻 Revoke 并轮换
八、流程小结(可当检查清单)
- FDO 账号可用,已 Fork
xorg/xserver - SSH 或 PAT 配好,
git push fork <功能分支>成功 - 对
xorg/xserver:main开好 MR,描述含动机与测试 - Ubuntu 虚机安装 Docker(国内 mirror + DNS)
- 安装 gitlab-runner 并注册到 Fork,tag=
local-fdo,privileged=true - 独立分支
local-runner-debug覆盖 workflow / tags / skip 重 job - skip 写法带
script:+rules: when: never - 容器内能解析
gitlab.freedesktop.org - 弱机跳过
meson-asan,以主meson编译结果为准 - 正式 MR 不含本地 CI 覆盖
九、参考链接
- xserver 官方仓:https://gitlab.freedesktop.org/xorg/xserver
- GitLab Runner 文档:https://docs.gitlab.com/runner/
- FDO CI templates:https://gitlab.freedesktop.org/freedesktop/ci-templates
- 腾讯云社区 Runner 安装说明(deb 安装思路可参考):搜索「Gitlab注册runner使用说明 腾讯云」
自己搭建gitlab-runner运行结果:https://gitlab.freedesktop.org/daemon.qiang/xserver/-/pipelines/1748795
走mr提交代码共享runner流程运行结果:https://gitlab.freedesktop.org/daemon.qiang/xserver/-/pipelines/1748079
本文基于个人在国内虚拟机上对接 FDO、自建 Runner 调试 xserver CI,并向上游提交功能 MR 的实践整理,环境与包版本会随时间变化,命令请以当时官方文档为准。