added ci
Test, build and publish / All tests and Linux binary (push) Failing after 28s
Test, build and publish / Container smoke test and Gitea publish (push) Skipped

This commit is contained in:
wt committed 2026-10-20 17:41:56 +07:00
1 parent 7f60661eef
commit 25fa51c76d
12 files changed
+350 -3

No files matched your search

+150
View File
@@ -0,0 +1,150 @@
name: Test, build and publish
on:
push:
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_INCREMENTAL: '0'
CARGO_PROFILE_DEV_DEBUG: '0'
CARGO_PROFILE_TEST_DEBUG: '0'
RUST_BACKTRACE: '1'
jobs:
verify:
name: All tests and Linux binary
runs-on: ubuntu-24.04
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Install native test dependencies and make room for 10 GiB tests
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential pkg-config libssl-dev libicu-dev lua5.4 liblua5.4-dev lua-filesystem lua-expat lua-socket lua-sec openssl
rust_version=$(python3 -c 'import tomllib; print(tomllib.load(open("rust-toolchain.toml", "rb"))["toolchain"]["channel"])')
rustup toolchain install "$rust_version" --profile minimal --component rustfmt --component clippy
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/setup-go@v5
with:
go-version: '1.24.3'
cache: false
- name: Build exact native Prosody reference
run: bash scripts/ci/prepare-reference.sh "$RUNNER_TEMP/reference"
- name: Build genuine MinIO
run: |
bash scripts/ci/prepare-minio.sh "$RUNNER_TEMP/minio"
go clean -cache -modcache
df -h . "$RUNNER_TEMP"
python3 -c 'import shutil; assert shutil.disk_usage(".").free >= 20 * 2**30, "Need 20 GiB free for actual upload tests"'
- name: Run every test, native oracle, load and real 10 GiB uploads
env:
PROSODY_REFERENCE_SOURCE: ${{ runner.temp }}/reference/prosody-cafd74b9c5ea
PROSODY_REFERENCE_LUA: lua5.4
MINIO_BINARY: ${{ runner.temp }}/minio
run: |
mkdir -p ci-results
set -o pipefail
bash scripts/ci/verify-all.sh 2>&1 | tee ci-results/verify.log
- name: Package tested binary
run: |
mkdir -p dist
cp target/release/rust-xmpp dist/rust-xmpp
chmod 0755 dist/rust-xmpp
dist/rust-xmpp --version
(cd dist && sha256sum rust-xmpp > SHA256SUMS)
- name: Save binary
uses: actions/upload-artifact@v4
with:
name: rust-xmpp-linux-amd64
path: dist/
if-no-files-found: error
retention-days: 30
- name: Save test reports even on failure
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: |
ci-results/
/tmp/muc-sm-load.json
if-no-files-found: warn
retention-days: 14
image:
name: Container smoke test and Gitea publish
needs: verify
runs-on: ubuntu-24.04
timeout-minutes: 20
# Only the publication job needs registry credentials. PRs still build and test images.
env:
GITEA_REGISTRY: ${{ vars.GITEA_REGISTRY }}
GITEA_IMAGE: ${{ vars.GITEA_IMAGE }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
PUBLISH: ${{ github.event_name != 'pull_request' && (github.ref == format('refs/heads/{0}', github.event.repository.default_branch) || startsWith(github.ref, 'refs/tags/v')) }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/download-artifact@v4
with:
name: rust-xmpp-linux-amd64
path: dist
- name: Verify downloaded executable
run: |
(cd dist && sha256sum --check SHA256SUMS)
chmod 0755 dist/rust-xmpp
- uses: docker/setup-buildx-action@v3
- name: Build exact tested binary into runtime image
uses: docker/build-push-action@v6
with:
context: .
target: ci-runtime
platforms: linux/amd64
load: true
push: false
tags: rust-xmpp:ci
- name: Smoke-test runtime image
run: |
docker run --rm rust-xmpp:ci --version
docker run --rm --entrypoint /usr/local/bin/prosodyctl rust-xmpp:ci --version
id=$(docker create rust-xmpp:ci)
trap 'docker rm "$id" >/dev/null' EXIT
docker cp "$id:/usr/local/bin/rust-xmpp" /tmp/container-rust-xmpp
cmp dist/rust-xmpp /tmp/container-rust-xmpp
- name: Validate publication configuration
if: env.PUBLISH == 'true'
env:
REGISTRY_USER: ${{ secrets.GITEA_REGISTRY_USERNAME }}
REGISTRY_TOKEN: ${{ secrets.GITEA_REGISTRY_TOKEN }}
run: python3 scripts/ci/image-tags.py
id: image
- name: Login to private Gitea registry
if: env.PUBLISH == 'true'
uses: docker/login-action@v3
with:
registry: ${{ vars.GITEA_REGISTRY }}
username: ${{ secrets.GITEA_REGISTRY_USERNAME }}
password: ${{ secrets.GITEA_REGISTRY_TOKEN }}
- name: Push the smoke-tested image
if: env.PUBLISH == 'true'
env:
IMAGE_TAGS: ${{ steps.image.outputs.tags }}
run: |
while IFS= read -r tag; do
docker tag rust-xmpp:ci "$tag"
docker push "$tag"
printf 'Published `%s`\n' "$tag" >> "$GITHUB_STEP_SUMMARY"
done <<< "$IMAGE_TAGS"
+12 -3
View File
@@ -4,14 +4,23 @@ COPY Cargo.toml Cargo.lock ./
COPY src ./src
RUN cargo build --release --locked
FROM debian:trixie-slim
FROM debian:trixie-slim AS runtime-base
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates gosu \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /src/target/release/rust-xmpp /usr/local/bin/rust-xmpp
RUN ln -s /usr/local/bin/rust-xmpp /usr/local/bin/prosodyctl
COPY scripts/docker-entrypoint.sh /usr/local/bin/rust-xmpp-entrypoint
RUN chmod 0755 /usr/local/bin/rust-xmpp-entrypoint
WORKDIR /work
ENTRYPOINT ["rust-xmpp-entrypoint"]
CMD ["serve", "/etc/prosody/prosody.cfg.lua", "--experimental"]
# CI downloads the exact executable produced by the verification job.
FROM runtime-base AS ci-runtime
COPY dist/rust-xmpp /usr/local/bin/rust-xmpp
RUN chmod 0755 /usr/local/bin/rust-xmpp \
&& ln -s /usr/local/bin/rust-xmpp /usr/local/bin/prosodyctl
# Default local build still compiles directly from source.
FROM runtime-base AS runtime
COPY --from=builder /src/target/release/rust-xmpp /usr/local/bin/rust-xmpp
RUN ln -s /usr/local/bin/rust-xmpp /usr/local/bin/prosodyctl
+6
View File
@@ -232,3 +232,9 @@ recovery Rust служит собственный журнал. Перед от
не выполняются; неизвестные явно включённые MUC-модули отклоняются при запуске.
Результаты проверки — в
[docs/VALIDATION-0.8.0.md](docs/VALIDATION-0.8.0.md).
## GitHub Actions и Gitea Registry
Полные тесты, Linux binary artifact и Docker push после проверок:
[настройка workflow](docs/GITHUB-ACTIONS.md). Registry и credentials задаются
через GitHub Actions variables/secrets.
+17
View File
@@ -0,0 +1,17 @@
# Проверка изменения CI
2026-10-20. Изменяется только CI, упаковка Docker и документация; Rust source
и версия0.8.0 не менялись. Предыдущие293 теста относятся к этому Rust source.
Локально успешно:
- actionlint1.7.7: `.github/workflows/ci.yml` без ошибок;
- bash -n для всех трёх CI shell scripts;
- Python compile и проверка генерации default-branch/version/SHA tags;
- отклонение чужой ветки, несовпадающей версии, URL вместо hostname,
некорректного image path и отсутствующего token;
- SHA-256 bundled reference archive совпадает с ожидаемым.
Docker daemon отсутствует; GitHub Actions и реальный push в Gitea здесь
не запускались. Результат следует проверить первым workflow run после
добавления репозитория, variables и secrets по GITHUB-ACTIONS.md.
+66
View File
@@ -0,0 +1,66 @@
# GitHub Actions → private Gitea Registry
Workflow: `.github/workflows/ci.yml`. Push, pull request и ручной запуск выполняют
проверки; публикация разрешена только для основной ветки репозитория и тегов
`v<версия Cargo.toml>`. PR, включая PR из forks, не получает registry credentials.
## Настройка GitHub
Settings → Secrets and variables → Actions:
| Тип | Имя | Значение |
|---|---|---|
| Variable | `GITEA_REGISTRY` | `gitea.example.org` или `gitea.example.org:5000`, без `https://` и пути |
| Variable | `GITEA_IMAGE` | `owner/rust-xmpp`, lowercase, без registry и тега |
| Secret | `GITEA_REGISTRY_USERNAME` | Имя пользователя Gitea с правом публикации пакетов owner |
| Secret | `GITEA_REGISTRY_TOKEN` | Personal access token с правом записи packages |
Создайте private owner/organization и проверьте права чтения пакета в Gitea:
аутентифицированный push сам по себе не меняет публичность owner/package.
Registry должен быть доступен GitHub-hosted runner по HTTPS с доверенным CA.
Для registry только в LAN потребуется runner с доступом к этой сети; настройки
runs-on для image job можно заменить на labels доверенного self-hosted runner.
Не запускайте PR-код на привилегированном self-hosted runner без изоляции.
## Проверки и результат
Job `verify` на Ubuntu24.04 ставит Rust из `rust-toolchain.toml`, Python3.12,
Lua5.4, OpenSSL/ICU и собирает оригинальную bundled Prosody cafd74b9c5ea.
MinIO собирается из unmodified upstream RELEASE.2025-04-22T22-12-26Z,
Go1.24.3, с проверкой SHA-256 исходного архива. Sandbox adapter не применяется.
`scripts/ci/verify-all.sh` запускает:
- fmt, все обычные Rust tests, Clippy и release build;
- все сетевые проверки из verify-local.sh, native module/storage и federation;
- обе нагрузки500TLS, в том числе MUC+SM SIGKILL/resume;
- оставшиеся ignored tests: AF_UNIX admin socket и archive>128MiB;
- реальные10GiB PUT/GET через MinIO и через local HTTPS backend, последовательно.
Таким образом отсутствие native reference или MinIO является ошибкой, а не skip.
Нужно не менее20GiB свободного диска перед проверками. На одноразовом hosted runner
удаляются неиспользуемые Android/.NET/GHC SDK; Go caches очищаются после сборки MinIO.
Тесты могут занимать десятки минут. Timeout verify job —90минут.
Artifact `rust-xmpp-linux-amd64`: проверенный release executable и SHA256SUMS.
Artifact `test-results`: полный лог и JSON-отчёты, также при ошибке теста.
Job `image` скачивает именно этот executable, проверяет checksum и собирает
Docker target `ci-runtime`. В образе выполняются `rust-xmpp --version` и
`prosodyctl --version`, затем извлечённый executable сравнивается побайтно с artifact.
Image smoke проходит и на PR. Только после успеха выполняются login/push.
Теги:
- `sha-<полный40символьныйcommit>` — каждый публикуемый commit;
- `latest` — только основная ветка;
- `v0.8.0` — пример version tag; он должен совпадать с Cargo.toml.
Version tag не меняет latest; prerelease также не перезаписывает latest.
Собирается Linux amd64, не multiarch. Локальный `docker build .` по-прежнему
собирает source target `runtime`; CI target использует уже проверенный binary.
Workflow добавлен и проверен локально как конфигурация. Реальный GitHub-run,
Docker daemon и push в ваш Gitea здесь не выполнялись; для этого нужны репозиторий
и перечисленные настройки. CI намеренно останавливает публикацию при любой ошибке.
Документация registry: https://docs.gitea.com/usage/packages/container/
+7
View File
@@ -1,8 +1,15 @@
9c4e46e42c549436c503a4cd70f90efd8f7754ce8c2103a6d1352cd34174aac0 .github/workflows/ci.yml
7136ea911bb6b6d352f703f80efeebde921028ea9dc39cd0d2cd55ea465f8c37 examples/config.json
8a65739eb5c24f10b9f2c509f0bd050fb1115706e6a41fdf804b9e0e44f583fd examples/config.toml
ca86274bcf4dc5daebbf69c9f003854afca92954719aff068f810e0a3d615dea examples/config.yaml
bbc2591581d382fef5fb918a480e6c338c7e3e3f2025df5509f51708534631e7 examples/converse-origin.fragment.yaml
66ea9e2b58f6a39b70911b9981cae5e99625483af7a41168e24923464de8ae56 examples/reverse-proxy.fragment.yaml
c08bd5923906f4d2163a258c8b68dbef39ea6a3e07032f67e5c12d3d9ca81c5e scripts/ci/image-tags.py
8820d262f8018a822b27eb9e5f0d3b9ca0c1272001164ca8a59fcd13911a5426 scripts/ci/prepare-minio.sh
5bcd646c6c9159bbdce3a4eadce4d80d6c7422748e47c6ad04e5769efb4f2920 scripts/ci/prepare-reference.sh
cb44f2692aefd618872153aed2658a7ab5c1a420802592e3240553b1f8da5ea5 scripts/ci/vendor/README.md
1e558d3d2211ea0228596aced2b71306503190c454ec4cb44f172045b3513c34 scripts/ci/vendor/prosody-cafd74b9c5ea.tar.gz
7ae11639143308ed4acd30ef6f99f55c7575893e5f6dce819d1f9d7da00cc29c scripts/ci/verify-all.sh
16e476e50c5802efcbb7d1aa68141c183c60f5ab17037d697dce720c209141f4 scripts/docker-entrypoint.sh
6fcb8a4977fee840d826951b0c30a3f2477c55d00860c79e99f635ca6e215e2b scripts/filter-android-pep-log.py
a83cfdb6d910af1add9a14df7b0bd43fb0e2a23342f1a1eec831d47c659bba6f scripts/integration_http.py
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env python3
"""Validate Gitea publication inputs and emit literal, shell-safe image tags."""
import os
import re
import tomllib
from pathlib import Path
def image_tags(env, version):
registry = env.get('GITEA_REGISTRY', '')
image = env.get('GITEA_IMAGE', '')
if not re.fullmatch(r'[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?::[0-9]{1,5})?', registry):
raise ValueError('GITEA_REGISTRY must be a lowercase hostname[:port], without scheme or path')
if not re.fullmatch(r'[a-z0-9]+(?:[._-][a-z0-9]+)*(?:/[a-z0-9]+(?:[._-][a-z0-9]+)*)+', image):
raise ValueError('GITEA_IMAGE must be lowercase owner/image, without registry or tag')
if not env.get('REGISTRY_USER') or not env.get('REGISTRY_TOKEN'):
raise ValueError('Set GITEA_REGISTRY_USERNAME and GITEA_REGISTRY_TOKEN secrets')
sha = env['GITHUB_SHA']
if not re.fullmatch(r'[0-9a-f]{40}', sha):
raise ValueError('Invalid commit SHA')
base = f'{registry}/{image}'
tags = [f'{base}:sha-{sha}']
ref = env['GITHUB_REF']
if ref.startswith('refs/tags/'):
release = ref.removeprefix('refs/tags/')
if release != f'v{version}' or not re.fullmatch(r'v[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?', release):
raise ValueError('Release tag must be v<Cargo.toml package.version> (no build metadata)')
tags.append(f'{base}:{release.lower()}')
elif ref == 'refs/heads/' + env['DEFAULT_BRANCH']:
tags.append(f'{base}:latest')
else:
raise ValueError('Only default branch or version tags may publish')
return tags
def main():
version = tomllib.loads(Path('Cargo.toml').read_text())['package']['version']
tags = image_tags(os.environ, version)
with open(os.environ['GITHUB_OUTPUT'], 'a', encoding='utf-8') as out:
out.write('tags<<IMAGE_TAGS\n' + '\n'.join(tags) + '\nIMAGE_TAGS\n')
if __name__ == '__main__':
main()
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Unmodified upstream source; never apply the sandbox adapter in hosted CI.
set -euo pipefail
output=${1:?Usage: prepare-minio.sh ABSOLUTE_OUTPUT_BINARY}
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
curl --fail --location --retry 3 --connect-timeout 20 --max-time 300 \
https://github.com/minio/minio/archive/refs/tags/RELEASE.2025-04-22T22-12-26Z.tar.gz \
--output "$work/minio.tar.gz"
printf '%s %s\n' 1a63209927b9d1fb239b2a776b7b01d1902eff19379a108f4bc7005edcc0968c "$work/minio.tar.gz" | sha256sum --check --strict
tar --no-same-owner -xzf "$work/minio.tar.gz" -C "$work"
cd "$work/minio-RELEASE.2025-04-22T22-12-26Z"
mkdir -p "$(dirname "$output")"
GOTOOLCHAIN=local go build -mod=readonly -p 2 -o "$output" .
"$output" --version
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
project_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
reference_parent=${1:?Usage: prepare-reference.sh OUTPUT_DIRECTORY}
mkdir -p "$reference_parent"
reference_parent=$(cd -- "$reference_parent" && pwd)
cd "$project_dir/scripts/ci/vendor"
printf '%s\n' '1e558d3d2211ea0228596aced2b71306503190c454ec4cb44f172045b3513c34 prosody-cafd74b9c5ea.tar.gz' | sha256sum --check --strict
tar --no-same-owner -xzf prosody-cafd74b9c5ea.tar.gz -C "$reference_parent"
cd "$reference_parent/prosody-cafd74b9c5ea"
./configure --ostype=debian --lua-version=5.4 --lua-suffix=5.4
make -j2
+11
View File
@@ -0,0 +1,11 @@
# Native reference test source
`prosody-cafd74b9c5ea.tar.gz` is the original, unmodified source archive supplied
with this project. Revision: `cafd74b9c5ead46eb58910359eb266e1732b0aa1`.
SHA-256: `1e558d3d2211ea0228596aced2b71306503190c454ec4cb44f172045b3513c34`.
The source is bundled so CI cannot silently skip native oracle tests when a
private upload URL expires. Prosody's MIT/X11 license and copyright notices
are retained inside the archive (`COPYING`). No compiled shared objects are
bundled. `prepare-reference.sh` checks the archive hash and builds native
modules against the runner's Lua/OpenSSL/ICU installation.
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
: "${PROSODY_REFERENCE_SOURCE:?Build the bundled reference first}"
: "${MINIO_BINARY:?Build genuine MinIO first}"
export XMPP_LOAD_CHECK=1
mkdir -p ci-results
bash scripts/verify-local.sh
# These two tests are deliberately ignored by the ordinary test command.
cargo test --locked --test admin_socket --test archive_mam -- --ignored --nocapture
python3 tests/upload_large_network.py --binary target/release/rust-xmpp --report ci-results/upload-local-10gib.json