diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..11257b0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.github +__pycache__/ +*.py[cod] +.pytest_cache/ +.Rhistory +.RData +.Rproj.user/ +.venv/ +venv/ +outputs_*/ +outputs_r/ +tables_r/ diff --git a/.github/workflows/container-ci.yml b/.github/workflows/container-ci.yml new file mode 100644 index 0000000..f6b620e --- /dev/null +++ b/.github/workflows/container-ci.yml @@ -0,0 +1,98 @@ +name: Python, R, and container CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: container-ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + python-canonical: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip + python -m pip install --requirement requirements.txt + - name: Run scanner tests + run: python -m pytest -q + - name: Run a quick canonical Fe II scan + run: | + python scripts/nist_wct_log_spectral_scan_FIXED.py \ + --csv data/Fe_lines.csv \ + --ion 2 \ + --bins 160 \ + --null-n 10 \ + --min-lines 100 \ + --out-dir /tmp/nist-preview + + python-container: + runs-on: ubuntu-24.04 + needs: python-canonical + steps: + - uses: actions/checkout@v4 + - name: Build canonical Python image + run: docker build --tag nist-python-ci . + - name: Run a quick scan in the Python image + run: | + docker run --rm nist-python-ci \ + python scripts/nist_wct_log_spectral_scan_FIXED.py \ + --csv data/Fe_lines.csv \ + --ion 2 \ + --bins 160 \ + --null-n 5 \ + --min-lines 100 \ + --out-dir /tmp/nist-preview + + r-container: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Build independent R image + id: r_build + shell: bash + run: | + set +e + set -o pipefail + docker build --progress=plain --file Dockerfile.r --tag nist-r-ci . \ + 2>&1 | tee r-build.log + status=${PIPESTATUS[0]} + echo "status=$status" >> "$GITHUB_OUTPUT" + exit 0 + - name: Run R test suite + id: r_tests + if: steps.r_build.outputs.status == '0' + shell: bash + run: | + set +e + docker run --rm nist-r-ci > r-test.log 2>&1 + status=$? + echo "status=$status" >> "$GITHUB_OUTPUT" + tail -n 250 r-test.log + exit 0 + - name: Upload R diagnostics + if: always() + uses: actions/upload-artifact@v4 + with: + name: nist-r-diagnostics-${{ github.sha }} + if-no-files-found: warn + path: | + r-build.log + r-test.log + - name: Enforce R image and test results + shell: bash + run: | + test "${{ steps.r_build.outputs.status }}" -eq 0 + test "${{ steps.r_tests.outputs.status }}" -eq 0 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1f1398a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + MPLBACKEND=Agg \ + PIP_NO_CACHE_DIR=1 + +WORKDIR /app + +COPY requirements.txt ./ +RUN python -m pip install --upgrade pip \ + && python -m pip install --requirement requirements.txt + +COPY . . + +CMD ["python", "scripts/run_feii_bin_stability.py", "--null-n", "100"] diff --git a/Dockerfile.r b/Dockerfile.r new file mode 100644 index 0000000..a59db33 --- /dev/null +++ b/Dockerfile.r @@ -0,0 +1,22 @@ +FROM rocker/r-ver:4.4.2 + +ENV DEBIAN_FRONTEND=noninteractive + +# Rocker versioned images pin both R and the CRAN snapshot. Install only system +# libraries with apt; install R packages into the Rocker R library with +# install2.r so packages cannot be pulled from Ubuntu's separate R runtime. +RUN apt-get update \ + && apt-get install -y --no-install-recommends libgmp-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN install2.r --error --skipinstalled --ncpus -1 \ + jsonlite \ + gmp \ + testthat + +RUN Rscript -e "required <- c('jsonlite', 'gmp', 'testthat'); missing <- required[!vapply(required, requireNamespace, logical(1), quietly=TRUE)]; if (length(missing)) stop('missing R packages: ', paste(missing, collapse=', '))" + +WORKDIR /app +COPY . . + +CMD ["Rscript", "tests/testthat.R"]