ci: upgrade tox to 4.x, target Python 3.13, document local test workflow#573
Open
lgelauff wants to merge 24 commits into
Open
ci: upgrade tox to 4.x, target Python 3.13, document local test workflow#573lgelauff wants to merge 24 commits into
lgelauff wants to merge 24 commits into
Conversation
Replace toolforge webservice python3.13 with the Toolforge buildservice (Cloud Native Buildpacks). Adds Procfile, .python-version, and a root-level package.json shim so both Python and Node buildpacks activate, baking the Vue frontend into the container image and eliminating the separate node20 frontend-build job. Config and env detection are updated in utils.py to work inside containers: - get_env_name() checks MONTAGE_ENV first (LDAP/getpass.getuser unavailable in containers per Toolforge docs) - load_env_config() loads secrets from individual MONTAGE_* environment variables (stored via toolforge envvars) when MONTAGE_OAUTH_CONSUMER_TOKEN is set; falls back to YAML for local dev Removes the urllib3/pyopenssl SSL shim (deprecated since urllib3 2.0, no longer needed on Python 3.13) and its dependency from requirements.in. Removes the cryptography version pin, which was a uwsgi+PyO3 workaround that does not apply to gunicorn. Adds gunicorn to requirements.in. Rewrites deployment.md for the buildservice workflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the Python version used on Toolforge (.python-version). Required by gunicorn>=20 which dropped support for Python <3.10. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cffi 1.16.0 ships a cp39 manylinux wheel but not a cp313 one, so pip falls back to compiling from source on Python 3.13. The slim image has no C toolchain. gcc and libffi-dev are the standard build requirements for cffi. The underlying fix (cffi>=1.17.1, which has cp313 wheels) is tracked in #512. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cffi 1.17.1 adds cp313 wheels, eliminating source compilation on Python 3.13 (and the need for gcc in the CI image). setuptools is pinned <82 because setuptools 82 removed pkg_resources, which python-graph-core depends on via namespace packages. Remove once python-graph-core is replaced (#421). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Heroku Node.js buildpack v5 requires a package-lock.json to run npm ci and npm run build. Without it, the buildpack installs Node.js but skips the install/build steps, leaving montage/static/ empty. The build script runs: cd frontend && npm ci && npm run toolforge:build which builds the Vite frontend and copies assets to montage/static/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The Toolforge buildservice startup probe checks port 8000. The earlier change to 5000 was incorrect and caused the startup probe to fail with "connection refused", putting pods into CrashLoopBackOff. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NFS must be mounted so Montage can write logs to /data/project/<toolname>/. Also adds URLs to the multi-environment table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
frontend/.env is gitignored, so the buildpack never had it. Without it, VITE_API_ENDPOINT was undefined at build time, making every Axios call go to /undefined/v1/... and fail with 404. .env.production sets it to empty string so Vite produces a relative /v1/ base URL, correct for same-origin Toolforge deployments. Also adds build verification and debugging guidance to deployment.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Important for deployers**: Montage now uses OAuth 2.0. If you have an existing OAuth 1.0a consumer registered on Meta-Wiki, you will need to register a new OAuth 2.0 consumer at Special:OAuthConsumerRegistration. Changes: - Replace mwoauth Handshaker/RequestToken with direct OAuth 2.0 PKCE flow using requests against rest.php/oauth2/ endpoints - New env vars: MONTAGE_OAUTH_CLIENT_ID, MONTAGE_OAUTH_CLIENT_SECRET, MONTAGE_OAUTH_REDIRECT_URI (replaces MONTAGE_OAUTH_CONSUMER_TOKEN / MONTAGE_OAUTH_SECRET_TOKEN) - Remove mwoauth, oauthlib, requests-oauthlib, pyjwt from dependencies - debug mode in complete_login now reads debug_username/debug_userid from config instead of hardcoded values Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The juror round listing was filtering on campaign status only, so finalized and cancelled rounds inside active campaigns still appeared. Jurors clicking them got a confusing 400 "round not active" error. Now only active and paused rounds are shown in the active view. Suspected cause: e3069dd (PR #350, merged 2025-10-23) added a finalize_round endpoint that can finalize individual rounds without advancing, creating a state the juror listing never filtered for. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Automates: build → poll for completion → verify SHA + port → warn if running SHA already matches → restart → smoke-test /meta/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- git pull --ff-only at start so the script stays current - default ref changed to master (was tools/buildservice) - document one-time clone in script header Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Paused rounds were still appearing in the juror round list because the only_active filter allowed both ACTIVE_STATUS and PAUSED_STATUS. However confirm_active() only permits ACTIVE_STATUS, so clicking a paused round always produced a 400 "round not active" error. Fix restricts the juror index to strictly active rounds only. Suspected introduced by e3069dd (#350). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _load_config_from_env now raises ValueError if MONTAGE_DEBUG=true in prod, beta, or devlabs; prevents a single envvar command from disabling auth on a live Toolforge tool - UserMiddleware auto-login path split: devtest keeps the test fixture user (6024474); debug mode uses userid=0 / '__montage_debug__' which has no match in any real DB, producing an immediate and obvious error if debug mode somehow reaches a production database - complete_login debug defaults changed to the same sentinel values so config.dev.yaml must explicitly set debug_userid / debug_username Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Unvalidated ?next= parameter allowed open redirects: any URL passed to /login?next= or /logout?next= was stored in a signed cookie and redirected to after auth, enabling phishing via crafted links. _safe_next() accepts only same-origin paths (starts with / but not //) and falls back to root_path for anything else. Applied at all three sites: login (cookie store), logout (direct redirect), and complete_login (cookie read, defence-in-depth). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_index() accepted an only_active parameter but hard-coded True when calling get_all_rounds_task_counts, so get_all_campaigns() (the archive endpoint at /juror/campaigns/all) was always returning an empty list instead of finalized rounds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously scm_secure was only True when env_name == 'prod', so beta and devlabs deployments (both served over HTTPS on Toolforge) shipped session cookies without the Secure flag. A MONTAGE_ENV typo (e.g. 'production' instead of 'prod') would silently drop it on prod. - scm_secure is now True for all envs except dev and devtest - app startup raises on unknown env names so typos fail loudly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tests - LoggingMiddleware now redacts code/state/access_token/token from request.args before writing to api_log; these are auth material and should never appear on disk - complete_login no longer swallows exceptions silently; OAuth exchange failures are now logged via api_log so operators can distinguish 'user cancelled' from 'client secret is wrong' or 'MW is down' - Four new tests cover the PKCE flow using mocked MW endpoints: login redirect params, state mismatch, token exchange failure, and successful login with cookie verification Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- app.py: refuse to start if cookie_secret is the default placeholder or shorter than 32 chars - public_endpoints.py: use hmac.compare_digest for state comparison (constant-time, prevents timing oracle on the CSRF token) - utils.py: print effective superuser list at startup so misconfigured MONTAGE_SUPERUSERS is immediately visible in logs - deploy.sh: fail explicitly when git ls-remote cannot resolve the ref instead of silently using the literal branch name as the SHA - dev.md: update OAuth keys to oauth_client_id/secret/redirect_uri and note that debug_userid/debug_username must be set for a useful local dev session Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update tox.ini to py313, tox 4 style, skip_missing_interpreters=false - Drop stale tox 3.x pins (tox<3.15, pluggy<1), Fabric3, coverage==5.0.2 - Document tox as the recommended local test command in dev.md - Keep Docker path in dev.md for exact CI reproduction Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
skip_missing_interpreters = falseso tox fails loudly if Python 3.13 is not installedtox<3.15,pluggy<1) and unused dev deps (Fabric3,coverage==5.0.2)toxas the recommended local test command indev.md, with the Docker path retained for exact CI reproductionWhy tox
The Toolforge buildservice cannot be run locally.
toxfills the reproducibility gap by creating a clean, isolated Python 3.13 environment for every local test run — independent of whatever venv the developer happens to have set up.Test plan
toxruns and all 10 tests passtoxexits with a clearFAIL(not a silent skip)🤖 Generated with Claude Code