Skip to content

Add multi-arch Docker builds and fix arm/v7 plugin system compilation - #34

Merged
thiagoralves merged 10 commits into
developmentfrom
devin/1763481207-multi-arch-docker
Nov 18, 2025
Merged

Add multi-arch Docker builds and fix arm/v7 plugin system compilation#34
thiagoralves merged 10 commits into
developmentfrom
devin/1763481207-multi-arch-docker

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 18, 2025

Copy link
Copy Markdown
Contributor

Add multi-arch Docker builds and fix arm/v7 plugin system compilation

Summary

This PR adds GitHub Actions workflow for building multi-architecture Docker images (amd64, arm64, arm/v7) and fixes a critical compilation error in the plugin system that prevented builds on 32-bit architectures.

Key Changes:

  1. Multi-arch Docker workflow - Added .github/workflows/docker.yml to build and publish images to GHCR for linux/amd64, linux/arm64, and linux/arm/v7
  2. Plugin system fix - Fixed compilation error on arm/v7 where Py_SET_REFCNT(args, UINT64_MAX) caused overflow (UINT64_MAX doesn't fit in 32-bit Py_ssize_t). Replaced with proper Python C API reference counting pattern.
  3. Dockerfile optimization - Simplified Dockerfile to delegate all dependency installation to install.sh
  4. Minor fixes - Added .venv/ to .gitignore and pkg-config to install.sh dependencies

Review & Testing Checklist for Human

CRITICAL - These items must be verified before merging:

  • Verify arm/v7 build succeeds in CI - The main issue was arm/v7 compilation failure. Check that the CI workflow completes successfully for all three architectures (amd64, arm64, arm/v7). The plugin system fix uses proper reference counting instead of the UINT64_MAX hack.

  • Configure GitHub Secrets - The workflow requires GHCR_USERNAME and GHCR_TOKEN secrets in repository settings. Without these, the workflow will fail when trying to push images to GHCR. Verify these are set before merging.

  • Review workflow trigger configuration - The workflow now triggers on pushes to both main and development branches, as well as on pull requests. This differs from the original requirement (development only). Verify this is the desired behavior or adjust the on: section if needed.

  • Test plugin system functionality - After the Docker image builds successfully, verify that the plugin system still works correctly by:

    1. Running a container with a Python plugin
    2. Verifying the plugin initializes without errors
    3. Checking that plugin cleanup doesn't leak memory
  • Verify Docker image size - The Dockerfile now relies on install.sh for all dependencies. Check that the final image size is reasonable and all required dependencies (gcc, g++, cmake, etc.) are present for PLC program compilation.

Recommended Test Plan

  1. Wait for CI to complete and verify all three architectures build successfully
  2. Pull the image: docker pull ghcr.io/autonomy-logic/openplc-runtime:latest
  3. Run the container: docker run -d -p 8443:8443 ghcr.io/autonomy-logic/openplc-runtime:latest
  4. Access the web interface at https://localhost:8443
  5. Upload and compile a test PLC program to verify compilation works
  6. If possible, test on actual arm/v7 hardware to verify the plugin system fix

Notes

  • The plugin system fix follows Python C API best practices: store the capsule reference in plugin state (args_capsule field) and release it with Py_XDECREF during cleanup. This ensures the plugin_runtime_args_t structure is freed exactly once via the capsule destructor.
  • The old build.yml workflow was removed since the new docker.yml workflow handles both building and testing.
  • The Dockerfile is now simpler and more maintainable, with all dependency logic centralized in install.sh.

Link to Devin run: https://app.devin.ai/sessions/692283defe0d473d9229876fc25e6ffe
Requested by: Thiago Alves (@thiagoralves)

- Update Dockerfile with optimized build dependencies (gcc, g++, cmake, build-essential)
- Add .github/workflows/docker.yml for multi-arch builds (amd64, arm64, armv7)
- Create install/install.sh script for easy local Docker image building
- Add .venv/ to .gitignore to prevent committing virtual environment
- Follow orchestrator-agent pattern for consistent Docker workflow
- Enable easy installation via: docker pull ghcr.io/autonomy-logic/openplc-runtime:latest

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

thiagoralves and others added 5 commits November 18, 2025 11:19
The plugin system was using Py_SET_REFCNT(args, UINT64_MAX) to prevent
garbage collection of the runtime args capsule. This caused an overflow
error on 32-bit systems where Py_ssize_t is 32 bits (int), but UINT64_MAX
is a 64-bit value.

Changes:
- Add args_capsule field to python_binds_t structure to store capsule reference
- Replace Py_SET_REFCNT hack with proper reference counting pattern
- Store capsule reference in plugin->python_plugin->args_capsule for lifetime
- Add Py_XDECREF in python_plugin_cleanup to properly release capsule

This fix ensures proper cross-architecture compatibility (32-bit and 64-bit)
and follows Python C API best practices for reference counting.

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
@devin-ai-integration devin-ai-integration Bot changed the title Add multi-architecture Docker build support Add multi-arch Docker builds and fix arm/v7 plugin system compilation Nov 18, 2025
devin-ai-integration Bot and others added 4 commits November 18, 2025 20:21
The webserver was crashing in Docker with RuntimeError: 'The Werkzeug web
server is not designed to run in production.' This occurred because
Flask-SocketIO was using Werkzeug's development server by default.

Changes:
- Add eventlet to requirements.txt for production-ready async server
- Update SocketIO initialization to use async_mode='eventlet' instead of 'threading'
- Eventlet provides proper WebSocket support with HTTPS/SSL for production use

This fix ensures the webserver runs reliably in Docker containers while
maintaining WebSocket functionality for debug communication with OpenPLC Editor.

The ssl_context parameter should work with eventlet's server. If issues arise,
we can switch to ssl_certfile/ssl_keyfile parameters as an alternative.

Co-Authored-By: Thiago Alves <thiagoralves@gmail.com>
@thiagoralves
thiagoralves requested a review from Copilot November 18, 2025 21:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enables multi-architecture Docker image builds for OpenPLC Runtime (amd64, arm64, arm/v7) and resolves a critical 32-bit architecture compilation failure in the plugin system's Python C API usage.

Key Changes:

  • Multi-architecture Docker workflow added to build and publish images for three platforms
  • Plugin system fixed to use proper Python C API reference counting instead of UINT64_MAX hack that caused overflow on 32-bit systems
  • Dockerfile simplified to delegate dependency installation to install.sh

Reviewed Changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
.github/workflows/docker.yml New workflow for building multi-arch Docker images and publishing to GHCR
.github/workflows/build.yml Removed old build workflow, replaced by docker.yml
core/src/drivers/python_plugin_bridge.h Added args_capsule field to store Python capsule reference
core/src/drivers/plugin_driver.c Fixed plugin initialization to store capsule reference and cleanup properly with Py_XDECREF
Dockerfile Simplified to use install.sh for all dependencies, improved structure with comments
install.sh Added pkg-config dependency
webserver/app.py Added allow_unsafe_werkzeug=True parameter
webserver/debug_websocket.py Added blank line after imports

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

uses: docker/build-push-action@v6
with:
context: .
push: true

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow unconditionally pushes images on pull requests, which will fail without write permissions and may publish unreviewed code. Consider only pushing on branch pushes, not pull requests. Add a conditional like push: ${{ github.event_name != 'pull_request' }} to prevent push attempts during PR builds.

Suggested change
push: true
push: ${{ github.event_name != 'pull_request' }}

Copilot uses AI. Check for mistakes.
Comment thread webserver/app.py
ssl_context=context,
use_reloader=False,
log_output=False,
allow_unsafe_werkzeug=True,

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allow_unsafe_werkzeug=True flag disables important security warnings in Werkzeug. This parameter should only be used in development environments, not production. Since this appears to be production code (running HTTPS server), this flag should be removed or conditionally set based on environment.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +32
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For GitHub Container Registry authentication, use ${{ github.actor }} for username and ${{ secrets.GITHUB_TOKEN }} for password instead of custom secrets. The built-in GITHUB_TOKEN is automatically available and has appropriate permissions when packages: write is set.

Suggested change
username: ${{ secrets.GHCR_USERNAME }}
password: ${{ secrets.GHCR_TOKEN }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

Copilot uses AI. Check for mistakes.
Comment thread Dockerfile
# Clean any existing build artifacts to ensure clean Docker build
RUN rm -rf build/ venvs/ 2>/dev/null || true
RUN chmod +x install.sh scripts/* start_openplc.sh
RUN rm -rf build/ venvs/ .venv/ 2>/dev/null || true

Copilot AI Nov 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup command redirects stderr to /dev/null and uses || true, which may hide actual errors. Since you're explicitly copying files with COPY . . and want a clean build, consider using .dockerignore to exclude build artifacts instead of removing them after copying.

Copilot uses AI. Check for mistakes.
@thiagoralves
thiagoralves merged commit de5010c into development Nov 18, 2025
1 check failed
@thiagoralves
thiagoralves deleted the devin/1763481207-multi-arch-docker branch November 18, 2025 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants