diff --git a/.github/workflows/auto-retarget-main-pr-to-dev.yml b/.github/workflows/auto-retarget-main-pr-to-dev.yml index 3732a72359f..bc65279e049 100644 --- a/.github/workflows/auto-retarget-main-pr-to-dev.yml +++ b/.github/workflows/auto-retarget-main-pr-to-dev.yml @@ -16,7 +16,7 @@ permissions: jobs: retarget: - if: github.actor != 'github-actions[bot]' + if: github.repository == 'router-for-me/CLIProxyAPI' && github.actor != 'github-actions[bot]' runs-on: ubuntu-latest steps: - name: Retarget PR base to dev diff --git a/.github/workflows/lazurio-container.yml b/.github/workflows/lazurio-container.yml new file mode 100644 index 00000000000..0d40a44747f --- /dev/null +++ b/.github/workflows/lazurio-container.yml @@ -0,0 +1,71 @@ +name: Lazurio container + +on: + workflow_dispatch: + inputs: + source_commit: + description: Exact merged source commit (40 lowercase hexadecimal characters) + required: true + type: string + version: + description: Qualified Lazurio version, for example 8.0.30-lazurio.thread3 + required: true + type: string + +permissions: + contents: read + packages: write + +concurrency: + group: lazurio-container-${{ inputs.version }} + cancel-in-progress: false + +jobs: + publish: + if: github.repository == 'Lazurio/CLIProxyAPI' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + env: + SOURCE_COMMIT: ${{ inputs.source_commit }} + VERSION: ${{ inputs.version }} + IMAGE: ghcr.io/lazurio/cliproxyapi + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + fetch-depth: 0 + persist-credentials: false + - name: Validate the immutable merged source + shell: bash + run: | + set -euo pipefail + [[ "$SOURCE_COMMIT" =~ ^[0-9a-f]{40}$ ]] + [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-lazurio\.[a-zA-Z0-9.-]+$ ]] + git merge-base --is-ancestor "$SOURCE_COMMIT" origin/main + git checkout --detach "$SOURCE_COMMIT" + test "$(git rev-parse HEAD)" = "$SOURCE_COMMIT" + - name: Build the Linux amd64 container + shell: bash + run: | + set -euo pipefail + docker build --platform linux/amd64 \ + --build-arg VERSION="$VERSION" \ + --build-arg COMMIT="$SOURCE_COMMIT" \ + --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + --label org.opencontainers.image.source=https://github.com/Lazurio/CLIProxyAPI \ + --label org.opencontainers.image.revision="$SOURCE_COMMIT" \ + --tag "$IMAGE:$VERSION" . + - name: Publish using this repository's package permission + env: + REGISTRY_TOKEN: ${{ github.token }} + shell: bash + run: | + set -euo pipefail + printf '%s' "$REGISTRY_TOKEN" | docker login ghcr.io --username "$GITHUB_ACTOR" --password-stdin + trap 'docker logout ghcr.io' EXIT + docker push "$IMAGE:$VERSION" + digest=$(docker image inspect "$IMAGE:$VERSION" --format '{{index .RepoDigests 0}}') + [[ "$digest" =~ ^ghcr.io/lazurio/cliproxyapi@sha256:[0-9a-f]{64}$ ]] + { + printf 'Source: `%s`\n\n' "$SOURCE_COMMIT" + printf 'Version: `%s`\n\n' "$VERSION" + printf 'Deployment reference: `%s`\n' "$digest" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.gitignore b/.gitignore index e63d33ae031..016a3c98b97 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ auths/* # Documentation docs/* !docs/management-api-v8.md +!docs/lazurio-container.md AGENTS.md CLAUDE.md GEMINI.md diff --git a/docs/lazurio-container.md b/docs/lazurio-container.md new file mode 100644 index 00000000000..8f6f6108ff8 --- /dev/null +++ b/docs/lazurio-container.md @@ -0,0 +1,33 @@ +# Lazurio server container + +The fork's **Lazurio container** workflow builds a selected, already merged +commit for Linux amd64 and publishes it to `ghcr.io/lazurio/cliproxyapi`. +It uses the repository-scoped Actions package permission, not the upstream +Docker Hub credentials. It does not refresh the model catalog during the build +or include any local configuration, account files or conversation data. + +Dispatch from `main` with an exact `source_commit` and a Lazurio `version`: + +```sh +gh workflow run lazurio-container.yml --repo Lazurio/CLIProxyAPI --ref main \ + -f source_commit=395e7206770035162feabc581bcaa227a1eb0f58 \ + -f version=8.0.30-lazurio.thread3 +``` + +The workflow refuses commits outside `main`'s history. The job summary records +the source, version and registry digest. A tag is a discovery aid; deployments +must select the resulting `@sha256:` reference in the Machines software catalog, +after qualification with the actual service configuration. Never promote an +unqualified digest or substitute a mutable tag into a deployment. + +GitHub creates new packages as private. Before the first deployment, an owner +must make this public-source container package public and verify anonymous +pulls. No registry login is installed on the services guest. The workflow does +not change package access settings or upstream release workflows. + +Qualification must use synthetic credentials. Live OAuth accounts remain in +their single owning proxy service: copying them into a second running instance +can invalidate the original refresh token. Back up the existing account volume, +stop the old container before starting the replacement, and verify account +counts, health and the administration UI. A rollback uses the previous qualified +image with the same persistent account volume.