diff --git a/.github/workflows/quma-image.yml b/.github/workflows/quma-image.yml new file mode 100644 index 0000000..a5e466e --- /dev/null +++ b/.github/workflows/quma-image.yml @@ -0,0 +1,81 @@ +name: Quma Image + +on: + release: + types: [published] + pull_request: + paths: + - 'container/quma/**' + workflow_dispatch: + inputs: + version: + description: 'Release tag to build (e.g. v0.3.1)' + required: true + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}/quma + +jobs: + build: + name: Build & Push + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + + - name: Log in to GHCR + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest,enable=${{ github.event_name == 'release' }} + type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }} + type=sha,prefix= + + - name: Resolve version + id: version + run: | + if [ "${{ github.event_name }}" = "release" ]; then + echo "tag=${{ github.event.release.tag_name }}" >> "$GITHUB_OUTPUT" + else + echo "tag=${{ github.event.inputs.version }}" >> "$GITHUB_OUTPUT" + fi + + - name: Build and push + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 + with: + context: container/quma + file: container/quma/Containerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + QUMA_VERSION=${{ steps.version.outputs.tag }} + + build-check: + name: Build Check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build image + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 + with: + context: container/quma + file: container/quma/Containerfile + push: false + build-args: | + QUMA_VERSION=v0.3.1 diff --git a/container/quma/Containerfile b/container/quma/Containerfile new file mode 100644 index 0000000..aff1341 --- /dev/null +++ b/container/quma/Containerfile @@ -0,0 +1,32 @@ +# Stage 1: Download pre-built binary from GitHub release +FROM registry.fedoraproject.org/fedora-minimal:latest AS download + +ARG QUMA_VERSION +RUN test -n "$QUMA_VERSION" || { echo "ERROR: QUMA_VERSION build arg is required (e.g. v0.3.1)"; exit 1; } + +RUN microdnf install -y --nodocs --setopt=install_weak_deps=False \ + curl tar xz \ + && microdnf clean all + +WORKDIR /download +RUN curl -fsSL -O "https://github.com/cebarks/quartermaster/releases/download/${QUMA_VERSION}/spt-quartermaster-x86_64-unknown-linux-gnu.tar.xz" \ + -O "https://github.com/cebarks/quartermaster/releases/download/${QUMA_VERSION}/spt-quartermaster-x86_64-unknown-linux-gnu.tar.xz.sha256" \ + && sha256sum -c spt-quartermaster-x86_64-unknown-linux-gnu.tar.xz.sha256 \ + && tar xf spt-quartermaster-x86_64-unknown-linux-gnu.tar.xz --strip-components=1 \ + && chmod +x quma + +# Stage 2: Minimal runtime +FROM registry.fedoraproject.org/fedora-minimal:latest + +COPY --from=download /download/quma /usr/local/bin/quma + +ENV QUMA_DIR=/opt/spt + +VOLUME /opt/spt +EXPOSE 9190 + +LABEL quma.image-type="quma" \ + org.opencontainers.image.title="quma" \ + org.opencontainers.image.description="Quartermaster — mod manager for SPT/Fika dedicated servers" + +ENTRYPOINT ["quma", "serve"] diff --git a/src/cli/setup.rs b/src/cli/setup.rs index 711e1a5..90612d7 100644 --- a/src/cli/setup.rs +++ b/src/cli/setup.rs @@ -633,6 +633,13 @@ async fn detect_or_create_container( dirs: &crate::dirs::QumaDirs, container_name: &str, ) -> Result { + // Name-first: if a configured container already exists, use it directly. + // Avoids ambiguity when quma itself runs in a container mounting the same dir. + if !container_name.is_empty() && mgr.inspect(container_name).await.is_ok() { + println!("Using configured container: {}", container_name); + return Ok(container_name.to_string()); + } + let detected = mgr.detect_spt_containers(dirs).await?; if detected.len() == 1 {