Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/pay-report-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Pay Report CD GCP

on:
push:
branches:
- main
paths:
- "pay-report/**"
workflow_dispatch:
inputs:
target:
description: "Deploy To"
required: true
type: choice
options:
- dev
- test
- sandbox
- prod
redeploy:
description: "Redeploy Application"
required: true
type: choice
options:
- "false"
- "true"
jobs:
pay-report-cd:
uses: bcgov/bcregistry-sre/.github/workflows/backend-cd.yaml@main
with:
target: ${{ inputs.target }}
app_name: "pay-report"
working_directory: "./pay-report"
redeploy: ${{ inputs.redeploy }}
secrets:
WORKLOAD_IDENTIFY_POOLS_PROVIDER: ${{ secrets.WORKLOAD_IDENTIFY_POOLS_PROVIDER }}
GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }}
Comment on lines +29 to +37

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI about 2 months ago

In general, to fix this class of issue, you explicitly declare a permissions block either at the root of the workflow (applying to all jobs without their own permissions) or on individual jobs. This constrains the GITHUB_TOKEN to the least privileges needed, instead of relying on potentially broad repository defaults.

For this specific workflow, the single best fix with minimal behavioral impact is to add a conservative permissions block at the top level, after the on: block and before jobs:. A common minimal baseline recommended by GitHub is contents: read, which allows read access to repository contents while preventing unintended write operations. The reusable workflow you call can still specify additional or different permissions inside its own definition if needed; your workflow’s top-level block just ensures you are not accidentally inheriting over-permissive defaults.

Concretely, in .github/workflows/pay-report-cd.yml, add:

permissions:
  contents: read

on new lines between the existing on: section (ending at line 26) and the jobs: section (line 27). No imports or additional definitions are required, as this is standard GitHub Actions YAML configuration.


Suggested changeset 1
.github/workflows/pay-report-cd.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pay-report-cd.yml b/.github/workflows/pay-report-cd.yml
--- a/.github/workflows/pay-report-cd.yml
+++ b/.github/workflows/pay-report-cd.yml
@@ -24,6 +24,8 @@
         options:
           - "false"
           - "true"
+permissions:
+  contents: read
 jobs:
   pay-report-cd:
     uses: bcgov/bcregistry-sre/.github/workflows/backend-cd.yaml@main
EOF
@@ -24,6 +24,8 @@
options:
- "false"
- "true"
permissions:
contents: read
jobs:
pay-report-cd:
uses: bcgov/bcregistry-sre/.github/workflows/backend-cd.yaml@main
Copilot is powered by AI and may make mistakes. Always verify output.

114 changes: 114 additions & 0 deletions .github/workflows/pay-report-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: PAY REPORT CI

on:
pull_request:
branches:
- main
- release/*
paths:
- "pay-report/**"

defaults:
run:
shell: bash
working-directory: ./pay-report

jobs:
setup-job:
runs-on: ubuntu-24.04

if: github.repository == 'bcgov/sbc-pay'

steps:
- uses: actions/checkout@v4
- run: "true"

linting:
Comment on lines +18 to +26

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 2 months ago

In general, the fix is to explicitly declare the permissions: for the workflow or per job so that the GITHUB_TOKEN has only the minimal scopes required. This workflow only needs to read repository contents to check out code and run CI; it does not need to write to the repo or modify issues/PRs. Thus, contents: read is sufficient.

The best way to fix this without changing existing behavior is to add a single permissions: block at the root of the workflow (top level, alongside name, on, defaults, and jobs). This root-level block will apply to all jobs (setup-job, linting, testing, build-check) because none of them currently define their own permissions. Concretely, in .github/workflows/pay-report-ci.yml, insert:

permissions:
  contents: read

after the on: section (e.g., after line 10) or anywhere at the root level before jobs:. No imports or additional methods are needed, since this is a YAML configuration change only.

Suggested changeset 1
.github/workflows/pay-report-ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pay-report-ci.yml b/.github/workflows/pay-report-ci.yml
--- a/.github/workflows/pay-report-ci.yml
+++ b/.github/workflows/pay-report-ci.yml
@@ -8,6 +8,9 @@
     paths:
       - "pay-report/**"
 
+permissions:
+  contents: read
+
 defaults:
   run:
     shell: bash
EOF
@@ -8,6 +8,9 @@
paths:
- "pay-report/**"

permissions:
contents: read

defaults:
run:
shell: bash
Copilot is powered by AI and may make mistakes. Always verify output.
needs: setup-job
runs-on: ubuntu-24.04

strategy:
matrix:
python-version: [3.12]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv sync --extra dev
- name: Lint with ruff
id: ruff
run: |
uv run ruff check .

testing:
Comment on lines +27 to +52

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 2 months ago

In general, this issue is fixed by explicitly declaring a permissions block for the workflow or for each job, restricting the GITHUB_TOKEN to the minimal scopes needed. For this CI workflow, all jobs only check out code and run local commands, so they only require contents: read. No job appears to need write access to issues, pull requests, or repository contents.

The best fix with no functional change is to add a single top‑level permissions block right after the name: line (before on:). This will apply to all jobs (setup-job, linting, testing, build-check) since none of them define their own permissions. The block should set contents: read so actions/checkout@v4 can function, while avoiding any unnecessary write permissions. No additional imports, methods, or other definitions are needed because this is a YAML configuration change only.

Concretely, in .github/workflows/pay-report-ci.yml, insert:

permissions:
  contents: read

between line 1 (name: PAY REPORT CI) and line 3 (on:).

Suggested changeset 1
.github/workflows/pay-report-ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pay-report-ci.yml b/.github/workflows/pay-report-ci.yml
--- a/.github/workflows/pay-report-ci.yml
+++ b/.github/workflows/pay-report-ci.yml
@@ -1,5 +1,8 @@
 name: PAY REPORT CI
 
+permissions:
+  contents: read
+
 on:
   pull_request:
     branches:
EOF
@@ -1,5 +1,8 @@
name: PAY REPORT CI

permissions:
contents: read

on:
pull_request:
branches:
Copilot is powered by AI and may make mistakes. Always verify output.
needs: setup-job
env:
PYTHONPATH: "./src"

runs-on: ubuntu-24.04

strategy:
matrix:
python-version: [3.12]

services:
postgres:
image: postgres:15.6
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: pay-report-test
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: |
uv sync --extra dev
- name: Test with pytest
id: test
run: |
uv run pytest

build-check:
Comment on lines +53 to +92

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 2 months ago

To fix the problem, explicitly set a restrictive permissions: block so that the GITHUB_TOKEN used in this workflow has only the minimal required scopes. Since all jobs just check out code and run local commands, they only need read access to repository contents, so contents: read is sufficient.

The best way to do this without changing functionality is to add a top‑level permissions: block (at the same indentation level as on: and defaults:). This will apply to all jobs that do not define their own permissions. You do not need to modify individual jobs, because none of them need write permissions or special scopes like pull-requests: write, issues: write, etc.

Concretely:

  • In .github/workflows/pay-report-ci.yml, add:
permissions:
  contents: read

between the on: section and the defaults: block (for example, after line 10). No imports, methods, or additional definitions are required, as this is pure workflow configuration.

Suggested changeset 1
.github/workflows/pay-report-ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pay-report-ci.yml b/.github/workflows/pay-report-ci.yml
--- a/.github/workflows/pay-report-ci.yml
+++ b/.github/workflows/pay-report-ci.yml
@@ -8,6 +8,9 @@
     paths:
       - "pay-report/**"
 
+permissions:
+  contents: read
+
 defaults:
   run:
     shell: bash
EOF
@@ -8,6 +8,9 @@
paths:
- "pay-report/**"

permissions:
contents: read

defaults:
run:
shell: bash
Copilot is powered by AI and may make mistakes. Always verify output.
needs: setup-job
runs-on: ubuntu-24.04

strategy:
matrix:
python-version: [3.12]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Build Docker image
id: build
run: |
docker build -t pay-report:test .
Comment on lines +93 to +113

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 2 months ago

In general, the fix is to explicitly define permissions for the GITHUB_TOKEN in this workflow, limiting it to the minimal scope required. Since all three jobs (setup-job, linting, testing, and build-check) only need to read the repository contents (via actions/checkout) and do not perform any write operations to GitHub resources, we can safely set contents: read. The best way, without changing existing functionality, is to add a top-level permissions block so that all jobs inherit it, rather than repeating it on each job.

Concretely, in .github/workflows/pay-report-ci.yml, add:

permissions:
  contents: read

near the top of the file (after name: and before on: or immediately after on:), ensuring the indentation matches YAML requirements. No additional imports, methods, or definitions are needed; this is purely a YAML configuration change within the workflow file.

Suggested changeset 1
.github/workflows/pay-report-ci.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/pay-report-ci.yml b/.github/workflows/pay-report-ci.yml
--- a/.github/workflows/pay-report-ci.yml
+++ b/.github/workflows/pay-report-ci.yml
@@ -1,5 +1,8 @@
 name: PAY REPORT CI
 
+permissions:
+  contents: read
+
 on:
   pull_request:
     branches:
EOF
@@ -1,5 +1,8 @@
name: PAY REPORT CI

permissions:
contents: read

on:
pull_request:
branches:
Copilot is powered by AI and may make mistakes. Always verify output.

28 changes: 28 additions & 0 deletions pay-report/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
__pycache__
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg
*.egg-info
dist
build
.venv
venv
env
.env
.env.local
*.log
.git
.gitignore
README.md
.pytest_cache
.coverage
htmlcov
.DS_Store
*.swp
*.swo
*~


1 change: 1 addition & 0 deletions pay-report/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.streamlit/secrets.toml
2 changes: 2 additions & 0 deletions pay-report/.streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[client]
showSidebarNavigation = false
19 changes: 19 additions & 0 deletions pay-report/.streamlit/secrets.toml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "your-random-cookie-secret-here"
client_id = "your-client-id"
client_secret = "your-client-secret"
server_metadata_url = "http://localhost:8080/realms/your-realm/.well-known/openid-configuration"

[database]
# For regular PostgreSQL connections:
host = "localhost"
port = "5432"
name = "your_database_name"
username = "your_username"
password = "your_password"

# For Google Cloud SQL connections (optional):
# instance_connection = "project:region:instance"
# Uses IAM authentication - no password required

27 changes: 27 additions & 0 deletions pay-report/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM python:3.13-slim

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir uv

COPY pyproject.toml ./

RUN uv sync

COPY . .

# Convert .env to .streamlit/secrets.toml if it exists
RUN if [ -f .env ]; then \
python3 scripts/env_to_toml.py .env .streamlit/secrets.toml; \
fi

EXPOSE 8501

HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health || exit 1

ENTRYPOINT ["uv", "run", "streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]

134 changes: 134 additions & 0 deletions pay-report/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Pay Team Report Dashboard

A Streamlit application with multiple pages that allows users to generate reports and download data as XLSX files.

## Purpose

This application was created as a stopgap solution for PowerBI. It enables non-technical staff to generate and download reports independently, eliminating the need for developers to repeatedly run reports on demand. This isn't meant for complicated visuals or dashboards just a means to an end for access to data for business users.

## Features

- **Streamlit Native Authentication**: User authentication using Streamlit's built-in OIDC support with Keycloak
- **Multi-page navigation**: Main dashboard and Analytics page
- **PostgreSQL integration**: Connect to your PostgreSQL database
- **XLSX download**: Export generated reports as XLSX files

## Setup

### 1. Install UV (if not already installed)

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

Or using pip:
```bash
pip install uv
```

### 2. Install Dependencies

```bash
uv sync
```

### 3. Configure Streamlit Secrets

Create a `.streamlit/secrets.toml` file from the example:

```bash
mkdir -p .streamlit
cp .streamlit/secrets.toml.example .streamlit/secrets.toml
```

Edit `.streamlit/secrets.toml` with your actual configuration values. See `.streamlit/secrets.toml.example` for the required structure.

### 4. Run the Application

Using UV:
```bash
uv run streamlit run app.py
```

Or using standard Python:

```bash
streamlit run app.py
```

The application will open in your default web browser at `http://localhost:8501`.

## Running Tests

Install test dependencies:

```bash
uv sync --extra dev
```

Run the tests:

```bash
uv run pytest
```

The tests verify that:
- `enforce_auth()` correctly handles authentication and role checks
- All pages in pages/*.py import from src (which enforces auth)

## Linting

This project uses [ruff](https://docs.astral.sh/ruff/) for linting and code formatting.

Install dev dependencies:
```bash
uv sync --extra dev
```

Run the linter:
```bash
uv run ruff check .
```

Format code:
```bash
uv run ruff format .
```

Check and format in one command:
```bash
uv run ruff check . --fix
uv run ruff format .
```

## Docker Setup

### Build the Docker Image

```bash
docker build -t pay-report .
```

### Run with Docker

Mount your `.streamlit/secrets.toml` file:

```bash
docker run -p 8501:8501 \
-v $(pwd)/.streamlit/secrets.toml:/app/.streamlit/secrets.toml:ro \
pay-report
```

**Note**: Make sure your `.streamlit/secrets.toml` file is configured with the correct values before running the container.

The application will be available at `http://localhost:8501`.

## Notes

- Make sure your PostgreSQL database is running and accessible
- Make sure your Keycloak server is running and accessible
- The application requires authentication before accessing any pages
- Authentication is handled automatically using Streamlit's native authentication
- Each page maintains its own session state for report data


Loading