mirror of
https://github.com/dsec-hub/dsec-discord-bot.git
synced 2026-09-22 15:53:56 +00:00
SEC-01: add pull-request CI and stop the deploy leaving DOT_ENV on the VPS
A merge to main runs the merged commit as root on the club VPS through the self-hosted runner, and this repo has no PR CI, no required review and no status check. - .github/workflows/ci.yml: fmt / clippy / build --locked / test on ubuntu-latest, contents: read, both actions pinned by commit SHA. Never the VPS. - deploy.yml: keep push to main, add workflow_dispatch, permissions contents: read, environment: production, and an if: always() step that removes the .env the deploy writes into the workspace. - .dockerignore: keep that .env, target/ and .git out of the build context. - Dockerfile: --locked on both cargo build --release lines. environment: production gates nothing until required reviewers are configured on the environment itself, and the ruleset still requires zero approving reviews. Both are owner-only and listed in the pull request. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
88e50b1dc4
commit
9932bdcecb
4 changed files with 107 additions and 2 deletions
9
.dockerignore
Normal file
9
.dockerignore
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Keep the docker build context to what the Dockerfile actually COPYs
|
||||||
|
# (Cargo.toml, Cargo.lock, src). deploy.yml writes the DOT_ENV secret to .env in
|
||||||
|
# the workspace before running `docker compose up --build`; without this file
|
||||||
|
# that secret is tarred into the build context and handed to the docker daemon
|
||||||
|
# on every deploy.
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
target/
|
||||||
|
.git
|
||||||
82
.github/workflows/ci.yml
vendored
Normal file
82
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
# Format, lint, build and test on every pull request.
|
||||||
|
#
|
||||||
|
# This must run on a GitHub-hosted runner and never on the club VPS. The runner
|
||||||
|
# deploy.yml uses lives on the club's own server and executes whatever a workflow
|
||||||
|
# tells it to, as root, so nothing triggered by a pull request may be pointed at
|
||||||
|
# it. Read that as a rule for this file, not a property of the repository: this
|
||||||
|
# repo is public, forking is on, and fork pull requests only need approval from a
|
||||||
|
# first-time contributor, so a fork that brings its own workflow can still reach
|
||||||
|
# that runner. See SEC-01.
|
||||||
|
#
|
||||||
|
# SEC-01: point the protect-main ruleset's required status check at this job's
|
||||||
|
# name ("fmt / clippy / build / test") so a red build blocks the merge that
|
||||||
|
# deploys.
|
||||||
|
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
# A newer push to the same pull request makes an in-flight run irrelevant.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
name: fmt / clippy / build / test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# A cold build of this dependency tree (serenity, reqwest, image, exr) in
|
||||||
|
# release, then clippy, then test, is slow on a 4-vCPU hosted runner. This is
|
||||||
|
# a guard against a hung job, not a target.
|
||||||
|
timeout-minutes: 45
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Third-party and first-party actions alike are pinned to a full commit
|
||||||
|
# SHA: a tag is mutable and can be repointed at new code by whoever owns
|
||||||
|
# the action.
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
|
# Caches written by a pull_request run are scoped to that pull request, so
|
||||||
|
# this pays off across pushes to the same branch rather than across branches.
|
||||||
|
- name: Cache cargo registry and build artifacts
|
||||||
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
target
|
||||||
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-cargo-
|
||||||
|
|
||||||
|
# actions/runner-images documents rustfmt for ubuntu-24.04 but not clippy (it
|
||||||
|
# lists clippy only under ubuntu-22.04), while the image actually in use does
|
||||||
|
# ship it. Adding both components is a no-op when they are present and keeps
|
||||||
|
# this job working if that undocumented extra ever goes away. Print the
|
||||||
|
# versions too: clippy's lint set moves between releases, so knowing which one
|
||||||
|
# ran is what explains a lint that appeared from nowhere.
|
||||||
|
- name: Toolchain
|
||||||
|
run: |
|
||||||
|
rustup component add clippy rustfmt
|
||||||
|
cargo --version
|
||||||
|
cargo fmt --version
|
||||||
|
cargo clippy --version
|
||||||
|
|
||||||
|
- name: Format
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
# Kept ahead of clippy and test: those resolve dependencies and would
|
||||||
|
# refresh Cargo.lock in place, so a stale lockfile would slip past
|
||||||
|
# --locked if they ran first.
|
||||||
|
- name: Build
|
||||||
|
run: cargo build --locked --release
|
||||||
|
|
||||||
|
- name: Clippy
|
||||||
|
run: cargo clippy --all-targets -- -D warnings
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: cargo test
|
||||||
14
.github/workflows/deploy.yml
vendored
14
.github/workflows/deploy.yml
vendored
|
|
@ -4,10 +4,19 @@ on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
# Manual re-run, for redeploying after a rollback or re-creating the
|
||||||
|
# workspace .env that the cleanup step below now removes.
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_and_deploy:
|
build_and_deploy:
|
||||||
runs-on: [self-hosted, linux]
|
runs-on: [self-hosted, linux]
|
||||||
|
# SEC-01: this gates nothing until required reviewers are configured on the
|
||||||
|
# "production" environment itself. See the pull request description.
|
||||||
|
environment: production
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|
@ -35,5 +44,10 @@ jobs:
|
||||||
sudo docker compose up -d --build --force-recreate
|
sudo docker compose up -d --build --force-recreate
|
||||||
echo "Deployment complete."
|
echo "Deployment complete."
|
||||||
|
|
||||||
|
- name: Remove environment file
|
||||||
|
if: always()
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
run: rm -f .env
|
||||||
|
|
||||||
- name: Clean up old Docker images
|
- name: Clean up old Docker images
|
||||||
run: sudo docker image prune -f
|
run: sudo docker image prune -f
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,14 @@ RUN mkdir src && \
|
||||||
echo 'fn main() { println!("Dummy main for dependency caching"); }' > src/main.rs
|
echo 'fn main() { println!("Dummy main for dependency caching"); }' > src/main.rs
|
||||||
|
|
||||||
# Build dependencies (this layer will be cached unless Cargo.toml/Cargo.lock changes)
|
# Build dependencies (this layer will be cached unless Cargo.toml/Cargo.lock changes)
|
||||||
RUN cargo build --release && \
|
RUN cargo build --locked --release && \
|
||||||
rm -rf src target/release/deps/dsec_bot*
|
rm -rf src target/release/deps/dsec_bot*
|
||||||
|
|
||||||
# Copy the actual source code
|
# Copy the actual source code
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
|
|
||||||
# Build the actual application
|
# Build the actual application
|
||||||
RUN cargo build --release
|
RUN cargo build --locked --release
|
||||||
|
|
||||||
# Runtime stage - use a minimal image
|
# Runtime stage - use a minimal image
|
||||||
FROM debian:bookworm-slim
|
FROM debian:bookworm-slim
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue