Restore wopr-support-plane.py patches + fix deploy URL #1

Open
wopr wants to merge 46 commits from fix/sp-restore-quirks-patches into main
Owner

Re-applies all 5 quirks patches that keep getting reverted, repoints deploy URL from non-existent WOPR.git to wopr-installer. See commits for detail.

Re-applies all 5 quirks patches that keep getting reverted, repoints deploy URL from non-existent WOPR.git to wopr-installer. See commits for detail.
wopr added 44 commits 2026-05-05 09:28:43 -05:00
- PostgreSQL: Add PG 15+ schema grants (GRANT ALL ON SCHEMA public)
- Registry: Fix Portainer port 9443 -> 9444 (avoid Authentik collision)
- Reactor AI: Use public Git URL (vault.wopr.systems) instead of internal

These fixes ensure fresh beacon provisioning works without manual intervention.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add shared job_store.py for cross-module job status tracking
- Add send_provisioning_started email with watch link
- Fix SSE endpoint to poll real job status (not simulated)
- Update beacon_provisioner to report progress to shared store
- Wire webhook handler to create job + send email immediately

Flow: Stripe webhook → create job → send email → provision with progress updates → SSE streams real status to user

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Created new provision.html with punk rock CRT aesthetic
  - Scanlines, glow effects, terminal styling
  - Real-time SSE connection for progress updates
  - Module-by-module deployment progress bar
  - Completion and error states with proper styling
- Added /provision/{job_id} and /setup/{job_id} routes
- Updated CORS to allow provision.wopr.systems
- Fixed get_provisioning_status to return not_found instead of fake job
- Mounted /static for serving assets

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required by dashboard_api.py for upgrade options calculation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Required for dashboard_api imports. Force-added due to parent gitignore.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Floating "NEED HELP?" button in bottom-right corner
- Modal with auto-filled job info (ID, beacon, status, time)
- Issue category dropdown (stuck, failed, timeout, payment, access, other)
- Description textarea
- Drag-and-drop file upload for screenshots and screen recordings
- 50MB per file limit
- Supports images and videos
- Fallback to ntfy notification if API fails
- Keyboard escape and background click to close

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add VPSProvisioner to bridge Stripe webhooks to Hetzner API
- Generate cloud-init with bootstrap.json and orchestrator callback
- Add /api/v1/webhooks/stripe endpoint for payment processing
- Add /api/v1/provision/{job_id}/status for installer callbacks
- Add /provision endpoint to handle Stripe success redirect

This completes the one-click installer flow:
1. Stripe checkout → 2. Webhook → 3. Hetzner VPS → 4. Installer → 5. Callbacks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 6 privacy-focused VPS provider stubs:
  - Scaleway (French, EU)
  - Contabo (German, budget)
  - Netcup (German, eco-friendly)
  - 1984 Hosting (Icelandic, privacy-first)
  - Exoscale (Swiss, no backdoors)
  - BuyVM/FranTech (indie, DDoS protection)

- Deprecate Vultr provider (TOS ownership clause)
  - Removed @register_provider decorator
  - Added warning banner and deprecation notice

- Add provider_health.py monitoring service:
  - Detects API drift (plan renames, pricing changes)
  - Generates AI support tickets for auto-remediation
  - Runs as systemd timer for scheduled checks

- Update Hetzner plan IDs for 2025 changes:
  - cx22 -> cx23, cpx21 -> cpx22, etc.
  - Updated pricing table with new plan names

- Add comprehensive provisioning test suite:
  - Unit tests for cloud-init, bundles, tiers
  - Mock integration tests
  - Live Hetzner API validation tests

Tested: VPS provisioning works (created/destroyed test instance)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Containerfile for control-plane image (Python 3.12, WeasyPrint deps)
- entrypoint.sh with env validation and DB wait
- podman-compose.yml for full stack (orc, redis, provider-health)
- Systemd quadlet files for production deployment:
  - wopr-orc.container (main orchestrator)
  - wopr-provider-health.container (API drift checker)
  - wopr-provider-health.timer (6-hourly schedule)
- deploy.sh automation script
- Updated .env.example with test/live Stripe key support
- Added VERSION file (1.6.0)

This enables bulletproof deployment:
- Single container for all control plane services
- Health checks baked in
- Proper secret management via env files
- Systemd integration for production

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enables each beacon to independently use test or live Stripe mode,
allowing gradual migration from test to production.

Changes:
- config.py: StripeConfig with test_secret_key, live_secret_key, and
  get_secret_key(mode) / get_webhook_secret(mode) helpers
- beacon.py: Added stripe_mode field (default: "test")
- billing.py: WOPRBilling accepts both keys, create_checkout_session()
  takes optional stripe_mode parameter
- stripe_catalog.py: get_price_id() accepts mode parameter to return
  test or live price IDs
- dashboard_api.py: Updated WOPRBilling instantiation
- Migration 004: Adds stripe_mode column to beacons table

Usage:
  # Set dudeabides to live mode
  UPDATE beacons SET stripe_mode = 'live' WHERE domain LIKE '%dudeabides%';

  # All other beacons remain in test mode by default

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Ollama container needs explicit 'serve' command and cleanup
commands to handle stale containers/processes from previous runs.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Split support-plane into two distinct modules:
  - wopr-admin: LIGHTHOUSE-ONLY staff escalations dashboard
  - support-client: Customer beacon support client
- Updated all customer bundles to use support-client
- Updated deployment scripts for support-client
- Staff admin dashboard (escalations, AI approval) is now
  explicitly lighthouse-only and NOT in any customer bundle

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add beacon registry API (/api/v1/beacons/)
- Beacons auto-register with lighthouse on startup
- Support aggregated escalations from all beacons
- Add beacon bootstrap script for installer
- Database schema for beacon registry

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update entrypoint to api.main:app (FastAPI)
- Add WOPR_MODE env var support (lighthouse/beacon)
- Add healthcheck
- Create .dockerignore for clean builds

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create SetupSlides.svelte with CRT punk theme and educational content
- Update setup page with two-column layout (slides + progress)
- Remove emojis, use ASCII icons throughout
- Slides sync with provisioning steps and auto-advance
- Add 005_add_custom_domains.sql migration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- orchestrator.py: Add bundle complexity to server sizing
  - Enterprise (48 modules) -> cpx51 (VERY_HIGH)
  - Professional/SmallBusiness -> cpx42 (HIGH)
  - Developer/Creator/Family -> cpx32 (MEDIUM)
  - Starter/Micro -> cpx22 (LOW)
  - Added tier 4 (VERY_HIGH) for all cloud providers

- stripe_catalog.py: Fix pricing configuration
  - Sync starter_t1 price ID with live.json
  - Add DEFCON_ONE bundle ($79.99-179.99)
  - Add REACTOR_AI bundle ($99.99-249.99)

- stripe_prices_test.json: Create test mode price file

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Corrected all sovereign suite module counts from manifests.py
- Added resource-intensive micro bundles (reactor_ai, video_creator, photographer, defcon_one)
- reactor_ai gets HIGH tier for AI/ML workloads
- Media bundles get MEDIUM tier for video/image processing
- defcon_one gets MEDIUM tier for security stack

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update live and test pricing
- Update stripe catalog

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Merge orchestrator components from test server
Some checks are pending
WOPR Tests / test (push) Waiting to run
WOPR Tests / lint (push) Waiting to run
fd9a2f3850
- Containerized deployment (containers/)
- VPS provisioner and job store
- Provider health monitoring
- New providers: buyvm, contabo, exoscale, hosting1984, netcup, scaleway
- Support agent components
- Documentation
- Tests and CI/CD

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove .env from repo, add to gitignore
Some checks failed
WOPR Tests / test (push) Has been cancelled
WOPR Tests / lint (push) Has been cancelled
fa90c19922
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Enable logical replication in postgresql.sh
- Create replication user with full table permissions
- Expose PostgreSQL on port 5434 for mesh peers
- Add postgres_replication.sh module for automatic setup
- Configure pg_hba.conf and subscriptions via bootstrap.json

Phase 2 of mesh SSO implementation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Auto-deploy replication after infrastructure if mesh_replication.enabled=true
- Non-fatal if replication setup fails (allows standalone operation)
- Phase 2 complete: installer now supports mesh SSO out of box

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add mesh_replication field to BundleManifest dataclass
- Enable mesh_replication=True for all 7 sovereign suites
- Generate mesh_replication config in bootstrap.json
- Includes lighthouse PostgreSQL connection details
- Includes mesh peer list (nodez3r0, wopr)

New beacons will auto-configure replication on deployment.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Backs up PostgreSQL before migration
- Enables logical replication
- Creates replication user, publication, subscription
- Verifies replication is working
- Supports both podman and docker containers

Existing beacons can now migrate to mesh SSO.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Required by postgres_replication module to read mesh config.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- New installer module for WOPR Universal Support Plane v3.2
- Fetches v3.2 support plane from vault.wopr.systems/wopr/WOPR
- Falls back to build dir or existing installation
- Includes watchdog with heartbeat monitoring, disk/memory/load checks
- Systemd units for daemon and watchdog timer (5-min interval)
- Knowledge base auto-fetch from vault
- folkmoot_ccm module in scripts/modules/ (Phase 9 App Layer)
- Bayer-Groth mix network shuffle node + bulletin board replica
- Opt-in CCM activation per beacon
- Registers with coordination service on Mothership Prod (10.0.1.1:8444)
- Orchestrator integration docs in docs/
- tor_onion_manifest.json: .onion addresses for all WOPR servers
- wopr.systems.zone: BIND DNS zone file (200 records)
- module-folkmoot-ccm.sh: Beacon installer module for Folkmoot CCM
- ccm_coordination_routes.py: CCM coordination API routes
- orchestrator-patch.sh: Orchestrator patching script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deployment, fix, and utility scripts accumulated across all WOPR projects:
- Folkmoot (Phase 1-3 deployment + fixes)
- OpenClaw (persona pipeline, cron, skills)
- SEO pipeline, social media, DNS, security posture
- Grafana dashboards, Prometheus, CrowdSec, Wazuh
- Meme engine, podcast pipeline, RAG UI
- Beacon remediation, Caddy config, Authentik SSO
- BIND DNS, TOR services, Nebula mesh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The support plane was blind to any service not manually added to its
manifest. New services deployed without a manifest update were invisible
— the nostr-toolkit, outreach API, and dozens of other endpoints were
unmonitored. This adds a universal autodiscovery engine that scans the
entire host every 15 minutes and rebuilds the manifest automatically.

Autodiscovery sources: all listening TCP ports, Caddy reverse proxy
backends, Docker/Podman containers, ALL systemd services (not just
wopr-*), timers, crontabs, network interfaces, compose projects.
Probes every discovered port for HTTP health endpoints.

- support-plane added to CORE_INFRASTRUCTURE (deployed on ALL beacons)
- Module registry updated with support-plane entry
- Installer step 7 deploys SP + autodiscovery after all apps
- Deployed to nodez3r0, WOPR PROD, homerig, micro-reactor
- Also fixes sitrep degraded tiles (notary/governance/bulletin/outreach)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause of Falken 502 and all cross-server failures: CrowdSec on
PROD banned nodez3r0 IP (159.203.138.7) for http-probing, which
blocked Nebula UDP 4242 and all reverse proxy traffic.

Also fixed PROD Nebula config which had its own IP in static_host_map
causing "Refusing to handshake with myself" loop.

Changes:
- CrowdSec mesh whitelist deployed to all 4 servers (all WOPR IPs +
  10.0.0.0/8 + 172.16.0.0/12 whitelisted permanently)
- CrowdSec whitelist added to support_plane.sh installer module
- Autodiscovery NON_HTTP_PORTS expanded: k8s (10250/10257/10259/
  16443/25000), SOCKS (9050/9051), Caddy admin (2019), MongoDB
  (27017-27019), Suricata (9997/9998), Nebula (4242), and more
- Reduced PROD issues from 61 to ~20 real issues (was ~40 false positives)
- Standalone autodiscovery script added as wopr-sp-autodiscovery.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PROD went from 61 issues to 6 actual issues. Root causes fixed:

- SP code used "expect_status" but manifest has "expected_status" (key
  mismatch) — patched on all 4 servers
- SP public endpoint default didn't include 400/404/501 — added them
- Autodiscovery NON_HTTP_PORTS: added netdata(19999), docker(9443),
  flink(6060), supervisord(9001), prometheus(9009), internal(42000)
- Autodiscovery skips fully-commented Caddy configs (tracking-webhook)
- Autodiscovery public endpoints now accept 400/404 by default
- Stats collector script (_sp_stats.py) for quick diagnostics

PROD infrastructure fixed:
- 8 GPU SSH tunnels created (180xx → homerig), then masked when
  homerig GPU services confirmed not running
- 15 stale Caddy configs disabled (GPU/AI on-demand services, flowise,
  ollama-proxy, search, pinokio, flink-homerig/nodez3r0, tracking-webhook)
- Wazuh dashboard config disabled (never deployed)
- Flink jobmanager restarted
- Authentik worker restarted

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PROD issues: 61 -> 1 (Wazuh HTTPS endpoint, pinned in manifest)

- Falken Caddy: switched from public IP to Nebula IP (10.0.0.2:3200)
- Wazuh: native install was present but indexer failed (missing log dir
  /var/log/wazuh-indexer). Created dir, restarted indexer+dashboard.
  Dashboard live at wazuh.wopr.systems:5601
- Flink jobmanager: port mapping was 8181->8181 but Flink listens on
  8081 internally. Recreated container with 8181->8081. Now 200.
- Disabled 15 stale Caddy configs for services that don't exist
- GPU tunnel services: created 8 then masked (homerig services offline)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checkout was broken: infinite SPA redirect loop, missing success template,
Stripe webhook returning 400 (wrong secret + python-dotenv missing),
Hetzner plan names stale (cx22 -> cpx21). Customer paid twice.

Fixes applied on WOPR PROD:
- Caddy /checkout route -> Flask (was falling through to SPA)
- checkout_success.html template created
- Stripe webhook secret rotated, python-dotenv installed
- Hetzner plans updated to cpx21/cpx31/cpx41 (US-available)
- SMTP config switched from dead Mailgun to local Postfix
- slowapi conflict removed from provision endpoint
- CF API token updated in installer .env

New monitoring (DEFCON-1 tier):
- SP functional checks: orchestrator health, Stripe config, webhook,
  provider count, email config, checkout page (Flask + Caddy)
- Weekly provider plan scanner (Hetzner/DO/Linode) with cron
- SP reads provider_plan_alert.json for DEFCON-1 escalation

Hardening:
- 22 critical files locked with chattr +i (immutable)
- DEFCON-1 unlock/relock protocol in SP for auto-remediation
- lockdown_manifest.json tracks locked file state

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- wopr_install.sh: reads bootstrap.json, deploys full sovereign suite
  (docker, PG, Redis, Authentik, Caddy, then all app modules)
- Retry logic: each module gets 2 attempts, failures bypass and log
  to /etc/wopr/failed_modules.json for SP remediation
- Fixed collabora/code:24.04 -> collabora/code:latest (tag removed)
- Deployed to orchestrator tarball for cloud-init auto-install

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Authentik branding: WOPR logo, dark CRT background, green accent
- Custom CSS: terminal-style login, green buttons, dark inputs
- Installer now waits for Authentik healthy, creates API token,
  applies theme, creates proxy provider + app + outpost config
- Caddyfile template includes forward_auth for SSO-protected dashboard
- Dashboard API routed through Caddy with Authentik headers
- Standalone theme script for manual/SP remediation use

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 345 deploy/fix scripts (asscast, meme engine, SP, beacon, project2032, etc.)
- Swiss Army Node ESP-IDF firmware (p4-bare, p4-brookesia, p4-display, p4-colortest, tbeam-ota-receiver)
- ArtJoos deploy scripts and caddy config
- WTP-Rise scaffold
- Snitch frontend
- Dashboard installer fixes (+layout.svelte, settings page)
- Updated .gitignore (exclude binary artifacts, build dirs, shell junk)
- SEO pipeline and keyword engine updates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Includes meme-engine GPU scheduler integration, SP manifest cleanup,
nodemin removal, lovejoos outreach, and various tmp fix scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The daemon at /opt/wopr/support-plane/wopr-support-plane.py on homerig
was reverted to pre-04-25 state (mtime Apr 23) — wiping out 5 documented
patches from support_plane_quirks.md. False-positive DEFCON-2 spam
returned (meme-engine "no activity" alerts every cooldown window).

Re-applied patches in this commit:
  1. grep -ci -> grep -ciE on meme-engine activity check (line 1869)
     basic-regex pipe was literal, always returned 0 matches
  2. EMAIL_COOLDOWN_MINUTES 30 -> 120 (line 53)
  3. ALERT_SUPPRESS_TARGETS list + _is_suppressed_target() helper
     covers 8600, easy-diffusion, comfyui, fooocus, wopr-ai-engine,
     meme-engine-homerig, meme-engine, wopr-meme-engine (lines 58-72)
  4. tier2_backend_check issues.append wrapped with suppress check
     (line 1805) - prevents alerts not just remediation
  5. Cooldown key normalization re.sub _\d+_issue_s_ -> _N_issue_s_
     (line 854) - so cooldown matches across issue-count variants
  6. Two meme-engine "backend_critical" issues.append blocks wrapped
     with _is_suppressed_target (lines 1895, 1904)

Verified: scan complete, 0 false-positive issues, service active.
Backups on homerig: .bak.1777989782, .bak.restore-1777990051,
.bak.restore2-1777990113.

Tracking source-of-truth here so deploys can pull from canonical.
NOTE: scripts/modules/support_plane.sh fetches from
vault.wopr.systems/wopr/WOPR/raw/branch/main/scripts/wopr-support-plane-universal.py
which 404s (no WOPR.git on vault). Recommend repointing to
wopr-installer or creating WOPR.git mirror.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The fetch URL was hardcoded to vault.wopr.systems/wopr/WOPR/raw/... but no
WOPR.git repo exists on vault — every install silently 404'd and fell back
to either a non-existent build_dir path or the existing on-disk file. That
silent failure is part of why the daemon kept getting reverted: nothing was
actively deploying the patched version, so any time someone restored from a
.bak the patches were gone for good.

Changes:
  - Repoint fetch URLs to wopr/wopr-installer.git (raw/branch/main, with
    raw/branch/fix/sp-restore-quirks-patches as second-try fallback until
    the fix branch is merged).
  - Validate fetched body before writing (size + EMAIL_COOLDOWN_MINUTES
    sentinel) so we never overwrite a healthy file with a stub or HTML
    error page.
  - Update build_dir fallback to look for wopr-installer/ first, with the
    legacy WOPR/ path kept as a secondary fallback.
  - Strengthen the existing-file branch comment so it's clear: leave the
    on-disk file alone, do NOT clobber from a stale backup.

Mirror both copies (scripts/modules/ and wopr-installer/scripts/modules/).

Verified the deploy URL now returns 200 with all 5 patches present after
fixing a stale Docker DNAT rule that was sending :3001 to a long-dead
container (172.19.0.4 instead of 172.19.0.7).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Repoint deploy URLs from scripts/wopr-support-plane-universal.py to
support-plane/wopr-support-plane.py — the latter is what actually lives on
main (verified 200 from vault), so we don't need the fix branch as a
fallback anymore.

Also add a direct-IP HTTP fallback (http://159.203.138.7:3001/...) so a
broken Caddy/DNS layer doesn't take deploys down with it.

Verified: vault main now serves the patched file (3164 lines, all 5 quirks
patches present: EMAIL_COOLDOWN_MINUTES=120, ALERT_SUPPRESS_TARGETS,
_N_issue_s_ key normalization, grep -ciE meme-engine activity check).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two more stale fetches were still pointing at the nonexistent WOPR.git:
  - knowledge-base JSON
  - autodiscovery engine .py

Repointed both to wopr-installer with the same scheme as the daemon URL
(vault HTTPS first, direct-IP HTTP fallback for when Caddy/DNS is broken):
  - support-plane/knowledge-base.json (verified 200 on main)
  - support-plane/wopr-sp-autodiscovery.py (file pushed to main in same
    operation; will be 200 after that commit lands)

Build-dir fallbacks updated to match the new wopr-installer/support-plane/
layout, with the legacy WOPR/scripts/ path preserved as a secondary fallback
so older build dirs still work.

KB fallback also gained "if file already exists, leave alone" — prevents
clobbering a working KB with a stub on transient fetch failure.

Verified: 0 wopr/WOPR URLs remain in the file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This pull request has changes conflicting with the target branch.
  • ai-engine/Dockerfile
  • ai-engine/api/database.py
  • ai-engine/api/engine.py
  • wopr-installer/control_plane/dashboard_api.py
  • wopr-installer/dashboard/package-lock.json
  • wopr-installer/scripts/modules/dashboard.sh
  • wopr-installer/scripts/modules/postgresql.sh
  • wopr-installer/scripts/modules/reactor_ai.sh
  • wopr-installer/scripts/modules/registry.sh
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/sp-restore-quirks-patches:fix/sp-restore-quirks-patches
git switch fix/sp-restore-quirks-patches

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff fix/sp-restore-quirks-patches
git switch fix/sp-restore-quirks-patches
git rebase main
git switch main
git merge --ff-only fix/sp-restore-quirks-patches
git switch fix/sp-restore-quirks-patches
git rebase main
git switch main
git merge --no-ff fix/sp-restore-quirks-patches
git switch main
git merge --squash fix/sp-restore-quirks-patches
git switch main
git merge --ff-only fix/sp-restore-quirks-patches
git switch main
git merge fix/sp-restore-quirks-patches
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
wopr/wopr-installer!1
No description provided.