chore: add docker and ci
This commit is contained in:
8
.dockerignore
Normal file
8
.dockerignore
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.git
|
||||||
|
.github
|
||||||
|
.dockerignore
|
||||||
|
Dockerfile
|
||||||
|
target
|
||||||
|
.env
|
||||||
|
*.md
|
||||||
|
.DS_Store
|
||||||
50
.github/workflows/docker.yml
vendored
Normal file
50
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
name: Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||||
|
|
||||||
|
- name: Select Docker platforms
|
||||||
|
id: docker-platforms
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [ "${ACT:-}" = "true" ] || [ "${GITEA_ACTIONS:-}" = "true" ]; then
|
||||||
|
echo "platforms=linux/amd64" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "platforms=linux/amd64,linux/arm64" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
if: ${{ steps.docker-platforms.outputs.platforms != 'linux/amd64' }}
|
||||||
|
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
|
||||||
|
|
||||||
|
# Production hardening: add dependency and image scanning before publishing,
|
||||||
|
# for example cargo-audit plus a container scanner such as Sysdig or Trivy.
|
||||||
|
- name: Build multi-arch image
|
||||||
|
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: ${{ steps.docker-platforms.outputs.platforms }}
|
||||||
|
push: false
|
||||||
|
build-args: |
|
||||||
|
GIT_SHA=${{ github.sha }}
|
||||||
|
cache-from: type=gha,scope=docker-multiarch
|
||||||
|
cache-to: type=gha,mode=max,scope=docker-multiarch
|
||||||
30
.github/workflows/external-contracts.yml
vendored
Normal file
30
.github/workflows/external-contracts.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: External contracts
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 3 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_TEST_DEBUG: line-tables-only
|
||||||
|
CARGO_INCREMENTAL: 0
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
external-contracts:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
||||||
|
|
||||||
|
# These tests intentionally call real third-party APIs. Unit/integration
|
||||||
|
# tests mock providers, but a nightly contract check catches external API
|
||||||
|
# drift that would otherwise only appear at runtime.
|
||||||
|
- name: Run external contract tests
|
||||||
|
run: cargo test --locked --test external_contract -- --ignored --test-threads=1
|
||||||
47
.github/workflows/rust.yml
vendored
Normal file
47
.github/workflows/rust.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: Rust
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
pull_request:
|
||||||
|
branches: [main, master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_DEV_DEBUG: line-tables-only
|
||||||
|
CARGO_PROFILE_TEST_DEBUG: line-tables-only
|
||||||
|
CARGO_INCREMENTAL: 0
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||||
|
with:
|
||||||
|
components: clippy, rustfmt
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
||||||
|
|
||||||
|
- name: cargo fmt
|
||||||
|
run: cargo fmt --all --check
|
||||||
|
|
||||||
|
- name: cargo clippy
|
||||||
|
run: cargo clippy --locked --all-targets -- -D warnings
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
|
||||||
|
|
||||||
|
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
||||||
|
|
||||||
|
- name: cargo test
|
||||||
|
run: cargo test --locked
|
||||||
84
Dockerfile
Normal file
84
Dockerfile
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# syntax=docker/dockerfile:1.7
|
||||||
|
FROM --platform=$BUILDPLATFORM rust:1.94-trixie AS chef
|
||||||
|
|
||||||
|
ARG BUILDARCH
|
||||||
|
ARG TARGETARCH
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN if [ "$TARGETARCH" = "arm64" ] && [ "$BUILDARCH" != "arm64" ]; then \
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc-aarch64-linux-gnu \
|
||||||
|
g++-aarch64-linux-gnu \
|
||||||
|
libc6-dev-arm64-cross \
|
||||||
|
pkg-config && \
|
||||||
|
rustup target add aarch64-unknown-linux-gnu && \
|
||||||
|
rm -rf /var/lib/apt/lists/*; \
|
||||||
|
elif [ "$TARGETARCH" = "amd64" ] && [ "$BUILDARCH" != "amd64" ]; then \
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
gcc-x86-64-linux-gnu \
|
||||||
|
g++-x86-64-linux-gnu \
|
||||||
|
libc6-dev-amd64-cross \
|
||||||
|
pkg-config && \
|
||||||
|
rustup target add x86_64-unknown-linux-gnu && \
|
||||||
|
rm -rf /var/lib/apt/lists/*; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
|
||||||
|
CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \
|
||||||
|
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc \
|
||||||
|
CC_x86_64_unknown_linux_gnu=x86_64-linux-gnu-gcc
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
|
cargo install cargo-chef --locked
|
||||||
|
|
||||||
|
RUN if [ "$TARGETARCH" = "$BUILDARCH" ]; then \
|
||||||
|
echo '--release --locked' > /tmp/cargo-args && \
|
||||||
|
echo 'target/release/pokedex-api' > /tmp/binary-path; \
|
||||||
|
elif [ "$TARGETARCH" = "arm64" ]; then \
|
||||||
|
echo '--release --locked --target aarch64-unknown-linux-gnu' > /tmp/cargo-args && \
|
||||||
|
echo 'target/aarch64-unknown-linux-gnu/release/pokedex-api' > /tmp/binary-path; \
|
||||||
|
elif [ "$TARGETARCH" = "amd64" ]; then \
|
||||||
|
echo '--release --locked --target x86_64-unknown-linux-gnu' > /tmp/cargo-args && \
|
||||||
|
echo 'target/x86_64-unknown-linux-gnu/release/pokedex-api' > /tmp/binary-path; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
FROM chef AS planner
|
||||||
|
COPY . .
|
||||||
|
RUN cargo chef prepare --recipe-path recipe.json
|
||||||
|
|
||||||
|
FROM chef AS builder
|
||||||
|
COPY --from=planner /app/recipe.json recipe.json
|
||||||
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
|
--mount=type=cache,target=/usr/local/cargo/git \
|
||||||
|
--mount=type=cache,target=/app/target \
|
||||||
|
cargo chef cook $(cat /tmp/cargo-args) --recipe-path recipe.json
|
||||||
|
|
||||||
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
COPY src/ src/
|
||||||
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
|
--mount=type=cache,target=/usr/local/cargo/git \
|
||||||
|
--mount=type=cache,target=/app/target \
|
||||||
|
cargo build $(cat /tmp/cargo-args) --bin pokedex-api && \
|
||||||
|
cp $(cat /tmp/binary-path) /usr/local/bin/pokedex-api
|
||||||
|
|
||||||
|
FROM debian:trixie-slim
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& groupadd --system app \
|
||||||
|
&& useradd --system --gid app --home-dir /nonexistent --shell /usr/sbin/nologin app
|
||||||
|
|
||||||
|
COPY --from=builder /usr/local/bin/pokedex-api /usr/local/bin/pokedex-api
|
||||||
|
|
||||||
|
ARG GIT_SHA=unknown
|
||||||
|
ENV GIT_SHA=$GIT_SHA \
|
||||||
|
BIND_ADDR=0.0.0.0:8000
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
USER app
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -fsS http://127.0.0.1:8000/health || exit 1
|
||||||
|
|
||||||
|
CMD ["pokedex-api"]
|
||||||
Reference in New Issue
Block a user