Skip to content

Repository files navigation

OpenPlan Capacity Conversion Model

codecov

Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.

This repository contains a Python CLI and Shiny application for converting NHP demand-model activity aggregated into functional areas into capacity estimates. It is a work in progress intended for internal use only.

For developers

Prerequisites for running this model are on the team wiki.

This package uses uv; the commands below were verified with uv 0.12.1.

Run the complete capacity conversion pipeline for all sites or selected sites:

uv run --locked -m nhp.capacity_conversion GUID
uv run --locked -m nhp.capacity_conversion GUID --ip-sites ALL --op-sites SITEA,SITEB --aae-sites SITEA

Run a single activity type:

uv run --locked -m nhp.capacity_conversion.op GUID
uv run --locked -m nhp.capacity_conversion.aae GUID --sites SITEA

Running the pipeline will create a results/GUID/RUNTIME folder, with a capacity_conversion_results.xlsx file within it.

Shiny application

The application requires:

  • AZ_STORAGE_EP: Azure Blob Storage account endpoint.
  • AZ_STORAGE_RESULTS: container containing functional aggregations.
  • AZ_TABLE_ENDPOINT: Azure Table Storage account endpoint.
  • CAPACITY_MODEL_VERSION: functional-aggregation catalogue partition and blob path version, such as dev or prod.
  • TABLE_NAME: table containing functional-aggregation metadata.

FEEDBACK_FORM_URL is required. Set it to the src URL from the Microsoft Forms embed code. Deployment rejects a missing or invalid URL. The application still reports that the form is unavailable if the runtime configuration is unexpectedly missing.

Azure authentication uses DefaultAzureCredential. The credential must have read access to both the Table catalogue and Blob results container. For local Azure CLI authentication, run az login when needed.

The local application does not load .env automatically. Start the development server from the repository root, pointing uv to your .env file:

uv run --env-file .env --locked --group app shiny run --reload app.py

The application queries the table partition configured by CAPACITY_MODEL_VERSION. It presents permitted datasets, scenario_name values and scenario_runtime model-run times, using the selected entity's RowKey as the functional aggregation GUID. It loads OP, A&E, IP day-case, IP maternity and IP wards aggregations, reshaping each across all sites before capacity conversion. It displays their capacity summaries and includes all five activity types in the Excel download.

On Posit Connect, nhp_provider_<dataset> grants access to one dataset, while nhp_devs and nhp_power_users grant access to every available aggregation. Unrecognised or absent Connect groups grant no dataset access. Local development permits all available aggregations.

The Shiny dependencies are in the app dependency group. requirements.txt is generated for Posit Connect and must not be edited manually.

Regenerate and validate the Connect requirements after changing dependencies:

uv lock --check
uv export --no-default-groups --group app --no-hashes --output-file requirements.txt
uv pip compile requirements.txt --output-file /tmp/nhp-capacity-connect-requirements.txt

The final command reproduces Connect's dependency-resolution step and must complete successfully.

Deploying to Posit Connect

Consult the official Posit Connect publishing documentation before using rsconnect.

The interactive deployment helper loads .env automatically. Values in .env override variables already set in the current environment, making .env the source of truth for deployment. .env is ignored by Git; never commit its credentials. In addition to the application runtime variables above, set:

  • CONNECT_SERVER: the Posit Connect server URL.
  • CONNECT_API_KEY: a Posit Connect API key with permission to publish.
  • CONNECT_APP_ID: the existing content GUID, required only for a redeployment. This is not the numeric content ID.

From the repository root, start the deployment interface with:

uv run --locked --group dev scripts/deploy_shiny.py

Choose whether to create new content or replace an existing deployment. Before deploying, the helper checks the required tools, bundle files, and environment variables, reports whether each effective value came from .env or the current environment, and rejects invalid HTTPS endpoints. It then verifies the Connect server and asks for confirmation. It does not display environment variable values or include the API key in subprocess arguments.

Automated deployment

The Deploy Shiny application workflow redeploys the existing application to:

  • the dev Posit Connect environment after a push to main; and
  • the prod Posit Connect environment when a GitHub release is published.

Configure GitHub Environments named dev and prod. Define all of the following as environment secrets in each one so the same workflow can select the target's configuration and GitHub can mask their values in workflow logs:

  • CONNECT_SERVER
  • CONNECT_APP_ID (the existing content GUID, not the numeric content ID)
  • CONNECT_API_KEY
  • AZ_STORAGE_EP
  • AZ_STORAGE_RESULTS
  • AZ_TABLE_ENDPOINT
  • CAPACITY_MODEL_VERSION
  • TABLE_NAME
  • FEEDBACK_FORM_URL

The API key must be able to publish the content identified by that environment's CONNECT_APP_ID. The workflow creates a Python Shiny manifest.json, then uses Posit's connect-publish action to replace that GUID. Runtime secrets are passed through the action's CONNECT_ENV_SET_* interface; the API key is not passed to the deployed application. The explicit manifest excludes .env, so repository content cannot override GitHub secrets. Configure required reviewers and deployment protection rules on the prod GitHub Environment.

Pull requests and deployments use the same reusable CI workflow for the lockfile, generated requirements, formatting, lint, type, unit and browser checks. Requiring its pull-request status check is optional; deployment always runs the complete CI workflow again against the exact commit being deployed. Deployments are serialized per environment, with up to 100 runs queued. GitHub does not guarantee queue order, so production accepts only the highest stable vMajor.Minor.Patch tag on main. A queued dev run stops before expensive CI when a newer commit reaches main, then checks the tip again immediately before deployment.

The deployment starts only after verification succeeds. The publish action targets the existing content by GUID and waits for Connect's deployment task to finish. A follow-up authenticated HTTPS request requires HTTP 200 and retries transient failures; curl does not forward the API-key header to another host when following redirects.

The action applies supplied runtime environment variables after the content deployment succeeds. The initial manual deployment must therefore configure the runtime environment. A later environment-update failure can leave the new bundle using the previous values even though the workflow reports failure, so test configuration changes in dev first and retain previous production values securely until the production workflow succeeds.

Both Connect applications must be created manually before the workflow's first run. The local helper remains the supported way to create that initial content.

Production rollback

The version guard deliberately prevents redeploying an older GitHub release. If the latest production deployment is unhealthy, activate the previous known-good bundle from the application's Content Bundles page in Connect. Restore any previous runtime configuration separately because it is not stored in the bundle. Then revert the faulty change on main and publish a new patch release; for example, recover from v1.4.2 with v1.4.3 rather than rerunning v1.4.1.

After the initial deployment, set its Custom content URL under Settings → Manage access to:

/nhp/dev/capacity-conversion/

The development application is available at connect.strategyunitwm.nhs.uk/nhp/dev/capacity-conversion/.

About

Repository containing logic for capacity conversion methodology

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages