Chattr / .github /workflows /.docker.yaml
MH0386's picture
Add HuggingFace sync
b380004 verified
name: Docker Image
on:
workflow_call:
inputs:
is_test:
type: boolean
required: true
description: Test Mode
registry:
type: string
required: true
description: Registry
install_source:
type: string
required: true
description: Source to install from (e.g., PyPI Package or Git source)
permissions:
contents: read
packages: write
attestations: write
id-token: write
actions: read
security-events: write
jobs:
check_dockerfile:
name: Check Dockerfile
runs-on: ubuntu-latest
if: ${{ inputs.is_test }}
environment:
name: code_quality
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check Dockerfile
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
id: dockerfile_lint
with:
call: check
- name: Job Summary
uses: jazanne/job-summary-action@690eb386a0b86fe4da7c6f0e543e61330ff09f06 # v1.0.0
if: success() || failure()
with:
summary: |
## Dockerfile Check
- **Status**: ${{ steps.dockerfile_lint.outcome == 'success' && ':white_check_mark:' || ':x:' }}
build_image:
name: Build and push Docker image to ${{ inputs.registry }}
needs: check_dockerfile
if: ${{ always() && !cancelled() && !failure() }}
runs-on: ubuntu-latest
outputs:
image_tag: ${{ steps.tag.outputs.TAG }}
environment:
name: docker_image
url: ${{inputs.registry}}/${{github.repository}}
steps:
- name: Free Disk Space
uses: endersonmenezes/free-disk-space@e6ed9b02e683a3b55ed0252f1ee469ce3b39a885 # v3.1.0
with:
remove_android: true
remove_dotnet: true
remove_haskell: true
remove_tool_cache: true
remove_swap: true
remove_packages_one_command: true
rm_cmd: rmz
remove_folders: >-
/usr/share /usr/local/lib /usr/local/share
/usr/local
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Get Python version from pyproject.toml
id: get_python_version
uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
with:
cmd: yq -roy '.project.requires-python' pyproject.toml
- name: Log in to ${{ inputs.registry }} Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ${{ inputs.registry }}
username: mh0386
password: ${{ inputs.registry == 'ghcr.io' && secrets.GH_TOKEN || inputs.registry == 'docker.io' && secrets.TOKEN_KEY_DOCKER }}
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
- name: Docker meta
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: ${{ inputs.registry }}/${{ github.repository }}
tags: |
type=raw,value=latest,enable=${{ github.event_name == 'push' && contains(github.ref, 'refs/tags/') }}
type=ref,event=pr,prefix={{sha}}-pr-
type=ref,event=tag
type=ref,event=branch
- name: Build and Push to ${{ inputs.registry }}
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
id: push
with:
push: true
sbom: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
build-args: |
INSTALL_SOURCE=${{ inputs.install_source }}
PYTHON_VERSION=${{ steps.get_python_version.outputs.result }}
env:
DOCKER_CONTENT_TRUST: '1'
- name: Generate artifact attestation
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
if: ${{ inputs.is_test == false }}
with:
subject-name: ${{ inputs.registry == 'docker.io' && 'index.docker.io' || inputs.registry }}/${{github.repository}}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
- name: Update Docker Hub Description
if: ${{ inputs.registry == 'docker.io' }}
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
with:
username: mh0386
password: ${{ secrets.TOKEN_KEY_DOCKER }}
repository: ${{ github.repository }}
short-description: ${{ github.event.repository.description }}
enable-url-completion: true
- name: Export tag for Testing and Scanning
id: tag
run: echo "TAG=$(echo "${{ steps.meta.outputs.tags }}" | tail -n 1)" >> $GITHUB_OUTPUT
docker_scout:
name: Docker Scout CVEs
needs: build_image
runs-on: ubuntu-latest
environment:
name: container_health
steps:
- name: Docker Scout
uses: docker/scout-action@f8c776824083494ab0d56b8105ba2ca85c86e4de # v1.18.2
with:
command: cves
dockerhub-user: mh0386
dockerhub-password: ${{ secrets.TOKEN_KEY_DOCKER }}
image: ${{ needs.build_image.outputs.image_tag }}
github-token: ${{ secrets.GH_TOKEN }}
trufflehog:
name: TruffleHog
runs-on: ubuntu-latest
needs: build_image
environment:
name: container_health
steps:
- name: Install trufflehog
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
with:
repo: trufflesecurity/trufflehog
cache: enable
- name: Docker Secret Scanning
run: >-
trufflehog docker --image ${{needs.build_image.outputs.image_tag}}
--fail --github-actions --results=verified --log-level=4 --no-update
syft:
name: Syft
runs-on: ubuntu-latest
needs: build_image
environment:
name: container_health
permissions:
contents: write
steps:
- name: SBOM Generation
uses: anchore/sbom-action@deef08a0db64bfad603422135db61477b16cef56 # v0.22.1
with:
image: ${{ needs.build_image.outputs.image_tag }}
dependency-snapshot: true
output-file: ${{ github.event.repository.name }}-sbom.json
format: syft-json
grype:
name: Grype
needs: build_image
runs-on: ubuntu-latest
environment:
name: container_health
steps:
- name: Scan image
uses: anchore/scan-action@8d2fce09422cd6037e577f4130e9b925e9a37175 # v7.3.1
id: scan
with:
image: ${{ needs.build_image.outputs.image_tag }}
cache-db: true
- name: upload Anchore scan SARIF report
if: success() || failure()
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
trivy:
name: Trivy
needs: build_image
runs-on: ubuntu-latest
environment:
name: container_health
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
with:
image-ref: ${{ needs.build_image.outputs.image_tag }}
trivy-config: .github/lint/.trivy.yaml
format: sarif
output: trivy-results-image.sarif
exit-code: '1'
scanners: vuln,secret,misconfig,license
- name: Upload Trivy scan results to GitHub Security tab
if: success() || failure()
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
with:
sarif_file: trivy-results-image.sarif
dockle:
name: Dockle
needs: build_image
runs-on: ubuntu-latest
environment:
name: container_health
steps:
- name: Lint the Container Image
uses: goodwithtech/dockle-action@e30e6af832aad6ea7dca2a248d31a85eab6dbd68 # v0.4.15
with:
image: ${{ needs.build_image.outputs.image_tag }}
format: sarif
output: dockle.sarif
accept-file: settings.py
accept-key: --chmod,--chown,GRADIO_SERVER_PORT,GRADIO_SERVER_NAME,FASTEMBED_CACHE_PATH,PATH
ignore: CIS-DI-0006
- name: upload Dockle scan SARIF report
if: success() || failure()
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
with:
sarif_file: dockle.sarif
api_test:
name: API Test
needs: build_image
runs-on: ubuntu-latest
if: ${{ inputs.is_test }}
environment:
name: container_health
services:
vector_database:
image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
ports:
- 6333:6333
app:
image: ${{ needs.build_image.outputs.image_tag }}
ports:
- 7860:7860
env:
MODEL__URL: https://api.groq.com/openai/v1
MODEL__API_KEY: ${{ secrets.GROQ_API_KEY }}
MODEL__NAME: llama3-70b-8192
VECTOR_DATABASE__URL: http://vector_database:6333
VECTOR_DATABASE__NAME: test
options: >-
--health-cmd "curl -o /dev/null -f -s -w 'Status: %{http_code}, Time: %{time_total}s'
http://localhost:7860/" --health-interval 10s --health-timeout
10s --health-start-period 20s --health-retries 15
steps:
- name: Echo URL
run: echo "${{ github.event.repository.name }} available on localhost:${{ job.services.app.ports['7860'] }}"
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
with:
enable-cache: true
activate-environment: true
- name: Install deps
run: uv sync --only-dev
- name: Test
uses: pavelzw/pytest-action@510c5e90c360a185039bea56ce8b3e7e51a16507 # v2.2.0
with:
click-to-expand: false
custom-arguments: tests/test_app.py::test_app -p no:warnings
env:
MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
clean:
name: Cleaning GHCR
needs:
- api_test
- docker_scout
- dockle
- trivy
- grype
- syft
- trufflehog
if: ${{ inputs.registry == 'ghcr.io' && ( success() || failure() ) && !contains(github.event.head_commit.message, '[skip ghcr clean]') }}
runs-on: ubuntu-latest
environment:
name: docker_image
steps:
- name: GHCR Cleaning
uses: snok/container-retention-policy@3b0972b2276b171b212f8c4efbca59ebba26eceb # v3.0.1
with:
account: ${{ github.repository_owner }}
token: ${{ secrets.GH_TOKEN }}
image-names: ${{ github.event.repository.name }}
image-tags: '!latest !*.*.*'
cut-off: 1s