added ci
This commit is contained in:
1 parent
7f60661eef
commit
25fa51c76d
12 files changed
+350
-3
No files matched your search
@@ -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
@@ -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
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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/
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
Executable
+15
@@ -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
|
||||
Executable
+12
@@ -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
|
||||
Vendored
+11
@@ -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.
|
||||
BIN
Binary file not shown.
Executable
+10
@@ -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
|
||||
Reference in new issue
Block a user