diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
new file mode 100644
index 0000000..bc7bc64
--- /dev/null
+++ b/.github/workflows/github-actions.yml
@@ -0,0 +1,53 @@
+name: Build and run ROS tests
+on:
+  push:
+  pull_request:
+  workflow_dispatch:
+    inputs:
+      debug_enabled:
+        type: boolean
+        description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
+        required: false
+        default: false
+jobs:
+  build:
+    strategy:
+      matrix:
+        rosdistro: [humble, iron, rolling]
+      fail-fast: false
+    runs-on: ubuntu-latest
+    container:
+      image: ros:${{ matrix.rosdistro }}-ros-core
+    steps:
+    # Enable tmate debugging of manually-triggered workflows if the input option was provided
+    - name: Setup tmate session
+      uses: mxschmitt/action-tmate@v3
+      if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
+      with:
+        detached: true
+    - name: Install apt dependencies
+      run: |
+        apt-get update
+        apt-get install -y build-essential clang-format file git python3-pip python3-colcon-common-extensions python3-rosdep pre-commit
+    - name: Checkout repository
+      uses: actions/checkout@v4
+      with:
+        path: src/rospy_message_converter
+    - name: Use rosdep to install remaining dependencies
+      run: |
+        rosdep init
+        rosdep update
+        rosdep install --from-paths src -i -y --rosdistro ${{ matrix.rosdistro }}
+    - name: Build
+      run: |
+        . /opt/ros/${{ matrix.rosdistro }}/setup.sh
+        colcon build --parallel-workers 1
+    - name: Run tests
+      run: |
+        . install/setup.sh
+        colcon test --parallel-workers 1
+        colcon test-result
+    - name: Run pre-commit hooks
+      run: |
+        cd src/rospy_message_converter
+        pre-commit run -a