diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a73ec3d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.dockerignore +.env +.git* +.idea +.vscode +Containerfile +migrations +scripts +target +tests diff --git a/.github/workflows/general.yml b/.github/workflows/general.yml index afdae6f..fe9fff8 100644 --- a/.github/workflows/general.yml +++ b/.github/workflows/general.yml @@ -1,7 +1,5 @@ -# The name of your workflow. GitHub displays the names of your workflows on your repository's "Actions" tab name: Rust -# To automatically trigger the workflow on: # NB: this differs from the book's project! # These settings allow us to run this specific CI pipeline for PRs against @@ -19,70 +17,42 @@ env: SQLX_VERSION: 0.7.3 SQLX_FEATURES: "rustls,postgres" -# A workflow run is made up of one or more jobs, which run in parallel by default -# Each job runs in a runner environment specified by runs-on jobs: - # Unique identifier of our job (`job_id`) test: - # Sets the name `Test` for the job, which is displayed in the GitHub UI name: Test - # Containers must run in Linux based operating systems runs-on: ubuntu-latest - # Service containers to run with the `test` container job services: - # Label used to access the service container postgres: - # Docker Hub image image: postgres:16 - # Environment variables scoped only for the `postgres` element env: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: postgres - # When you map ports using the ports keyword, GitHub uses the --publish command to publish the container’s ports to the Docker host - # Opens tcp port 5432 on the host and service container ports: - 5432:5432 steps: - # Downloads a copy of the code in your repository before running CI tests - - name: Check out repository code - # The uses keyword specifies that this step will run v3 of the actions/checkout action. - # This is an action that checks out your repository onto the runner, allowing you to run scripts or other actions against your code (such as build and test tools). - # You should use the checkout action any time your workflow will run against the repository's code. - uses: actions/checkout@v4 - - # This GitHub Action installs a Rust toolchain using rustup. It is designed for one-line concise usage and good defaults. - - name: Install the Rust toolchain - uses: dtolnay/rust-toolchain@stable - - # A GitHub Action that implements smart caching for rust/cargo projects with sensible defaults. - - name: Rust Cache Action - uses: Swatinem/rust-cache@v2 + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 with: - # An additional cache key that is added alongside the automatic `job`-based cache key and can be used to further differentiate jobs. default: empty key: sqlx-${{ env.SQLX_VERSION }} - - name: Install sqlx-cli run: - cargo install sqlx-cli - --version=${{ env.SQLX_VERSION }} - --features ${{ env.SQLX_FEATURES }} - --no-default-features - --locked - # The --locked flag can be used to force Cargo to use the packaged Cargo.lock file if it is available. - # This may be useful for ensuring reproducible builds, to use the exact same set of dependencies that were available when the package was published. - # It may also be useful if a newer version of a dependency is published that no longer builds on your system, or has other problems - - - name: Install postgresql-client - run: sudo apt-get update && sudo apt-get install postgresql-client -y - + cargo install sqlx-cli + --version=${{ env.SQLX_VERSION }} + --features ${{ env.SQLX_FEATURES }} + --no-default-features + --locked - name: Migrate database - run: SKIP_PODMAN=true ./scripts/init_db.sh - + run: | + sudo apt-get install --no-install-recommends -y libpq-dev + SKIP_PODMAN=true ./scripts/init_db.sh + - name: Check sqlx-data.json is up-to-date + run: | + cargo sqlx prepare --workspace --check - name: Run tests run: cargo test - # `fmt` container job fmt: name: Rustfmt runs-on: ubuntu-latest @@ -90,12 +60,10 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: - # Specific to dtolnay/rust-toolchain: Comma-separated string of additional components to install components: rustfmt - name: Enforce formatting run: cargo fmt --check - # `clippy` container job clippy: name: Clippy runs-on: ubuntu-latest @@ -117,19 +85,19 @@ jobs: with: key: sqlx-${{ env.SQLX_VERSION }} - name: Install sqlx-cli - run: cargo install sqlx-cli - --version=${{ env.SQLX_VERSION }} - --features ${{ env.SQLX_FEATURES }} - --no-default-features - --locked - - name: Install postgresql-client - run: sudo apt-get update && sudo apt-get install postgresql-client -y + run: + cargo install sqlx-cli + --version=${{ env.SQLX_VERSION }} + --features ${{ env.SQLX_FEATURES }} + --no-default-features + --locked - name: Migrate database - run: SKIP_PODMAN=true ./scripts/init_db.sh + run: | + sudo apt-get install --no-install-recommends -y libpq-dev + SKIP_PODMAN=true ./scripts/init_db.sh - name: Linting run: cargo clippy -- -D warnings - # `coverage` container job coverage: name: Code coverage runs-on: ubuntu-latest @@ -146,13 +114,16 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - - name: Install postgresql-client - run: sudo apt-get update && sudo apt-get install postgresql-client -y + - name: Install libpq + run: sudo apt-get update && sudo apt-get install --no-install-recommends -y postgresql-client - uses: Swatinem/rust-cache@v2 with: key: sqlx-${{ env.SQLX_VERSION }} + - name: Install tarpaulin + run: cargo install cargo-tarpaulin - name: Install sqlx-cli - run: cargo install sqlx-cli + run: + cargo install sqlx-cli --version=${{ env.SQLX_VERSION }} --features ${{ env.SQLX_FEATURES }} --no-default-features @@ -160,4 +131,4 @@ jobs: - name: Migrate database run: SKIP_PODMAN=true ./scripts/init_db.sh - name: Generate code coverage - run: cargo install cargo-tarpaulin && cargo tarpaulin --verbose --workspace + run: cargo tarpaulin --verbose --workspace diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..4870723 --- /dev/null +++ b/Containerfile @@ -0,0 +1,47 @@ +FROM docker.io/lukemathwalker/cargo-chef:0.1.63-rust-1.76.0-bookworm as chef +LABEL stage=build + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y clang libssl-dev lld pkg-config \ + && groupadd -g 1000 app \ + && useradd -u 1000 -g 1000 -s /bin/bash -M app \ + && mkdir /app \ + && chown app:app /app + +FROM chef AS planner +LABEL stage=build + +USER app + +WORKDIR /app +COPY --chown=app:app . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM planner AS builder +LABEL stage=build + +ENV SQLX_OFFLINE true +USER app + +COPY --from=planner --chown=app:app /app/recipe.json . +RUN cargo chef cook --release --recipe-path recipe.json + +COPY --chown=app:app . . +RUN cargo build --release + +FROM docker.io/library/debian:bookworm-slim AS runtime + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y ca-certificates libssl3 \ + && rm -rf /var/lib/apt/lists/* \ + && groupadd -g 1000 app \ + && useradd -u 1000 -g 1000 -s /bin/bash -M app + +ENV APP_ENVIRONMENT production +USER app + +WORKDIR /app +COPY --chown=root:root --chmod=444 configuration ./configuration +COPY --from=builder --chown=root:root --chmod=555 /app/target/release/zero2prod . + +ENTRYPOINT ["./zero2prod"]