Skip to content

feat: ATTOM API fixes and FRED API integration #323

feat: ATTOM API fixes and FRED API integration

feat: ATTOM API fixes and FRED API integration #323

name: Tier 2 Governance — Build, Publish & Attest
on:
push:
branches: [main]
tags: ["v*.*.*"]
concurrency:
group: tier-2-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-image:
name: "🏗️ Tier 2 — Build Image"
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
image-digest: ${{ steps.build.outputs.digest }}
steps:
- name: "job-start"
run: |
echo "job-start: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
- name: Checkout
uses: actions/checkout@v7
- name: Extract metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
labels: |
org.opencontainers.image.title=PREI - Real Estate Investment Analyzer
org.opencontainers.image.description=Django app for RE investment KPIs
org.opencontainers.image.vendor=paruff
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build image
id: build
uses: docker/build-push-action@v7
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:build-${{ github.sha }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: "job-finish"
if: always()
run: |
echo "job-finish: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
scan-image:
name: "🛡️ Tier 2 — Scan Image"
needs: build-image
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
security-events: write
steps:
- name: "job-start"
run: |
echo "job-start: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
- name: Trivy — block HIGH/CRITICAL CVEs with fixes
uses: aquasecurity/trivy-action@v0.36.0
with:
scan-type: image
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }}
format: table
exit-code: 1
severity: CRITICAL,HIGH
ignore-unfixed: true
vuln-type: os,library
- name: Trivy — upload SARIF
uses: aquasecurity/trivy-action@v0.36.0
if: always()
with:
scan-type: image
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }}
format: sarif
output: trivy-tier-2.sarif
severity: CRITICAL,HIGH,MEDIUM
ignore-unfixed: true
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: trivy-tier-2.sarif
category: trivy-tier-2-scan
- name: "job-finish"
if: always()
run: |
echo "job-finish: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
publish:
name: "📤 Tier 2 — Publish"
needs: [build-image, scan-image]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: "job-start"
run: |
echo "job-start: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
- name: Extract metadata
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-,format=short
type=raw,value=latest,enable={{is_default_branch}}
labels: |
org.opencontainers.image.title=PREI - Real Estate Investment Analyzer
org.opencontainers.image.description=Django app for RE investment KPIs
org.opencontainers.image.vendor=paruff
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Publish tags from built image
env:
SOURCE_IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-image.outputs.image-digest }}
TARGET_TAGS: ${{ steps.meta.outputs.tags }}
run: |
mapfile -t tags <<<"$TARGET_TAGS"
if [ "${#tags[@]}" -eq 0 ]; then
echo "No target tags were generated."
exit 1
fi
args=()
for tag in "${tags[@]}"; do
args+=("-t" "$tag")
done
docker buildx imagetools create "${args[@]}" "$SOURCE_IMAGE"
- name: "job-finish"
if: always()
run: |
echo "job-finish: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
attest:
name: "🧾 Tier 2 — Attest"
needs: [publish, build-image]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- name: "job-start"
run: |
echo "job-start: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"
- name: Log in to GHCR
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Attest build provenance
uses: actions/attest-build-provenance@v4
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
subject-digest: ${{ needs.build-image.outputs.image-digest }}
push-to-registry: true
- name: "job-finish"
if: always()
run: |
echo "job-finish: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "sha: ${{ github.sha }}"