diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6b62d682a..9aa987543 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp { "name": "VILLASnode", - "image": "registry.git.rwth-aachen.de/acs/public/villas/node/dev-vscode", + "image": "ghcr.io/villasframework/villas/node/dev-vscode:master", // Uncomment to build the devcontainer locally // "build": { // "dockerfile": "../packaging/docker/Dockerfile.fedora", diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 000000000..077d21a29 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,93 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Build + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + +env: + CMAKE_BUILD_OPTS: --parallel $(nproc) + CMAKE_EXTRA_OPTS: -DCMAKE_BUILD_TYPE=Release + CCACHE_DIR: ${{ github.workspace }}/.ccache + +permissions: + contents: read + packages: write + +jobs: + build-source: + name: "Build Source [${{ matrix.distro }}]" + runs-on: ubuntu-latest + container: + image: ${{ inputs.docker_image }}/dev-${{ matrix.image_name }}:${{ github.sha }} + options: --user root + strategy: + fail-fast: false + matrix: + include: + - distro: fedora + image_name: fedora + cmake_extra_opts: >- + -DVILLAS_COMPILE_WARNING_AS_ERROR=ON + -DCMAKE_C_COMPILER_LAUNCHER=ccache + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + - distro: fedora-minimal + image_name: fedora-minimal + cmake_extra_opts: >- + -DVILLAS_COMPILE_WARNING_AS_ERROR=ON + -DWITH_API=OFF + -DWITH_CLIENTS=OFF + -DWITH_CONFIG=OFF + -DWITH_DOC=OFF + -DWITH_FPGA=OFF + -DWITH_GRAPHVIZ=OFF + -DWITH_HOOKS=OFF + -DWITH_LUA=OFF + -DWITH_OPENMP=OFF + -DWITH_PLUGINS=OFF + -DWITH_SRC=OFF + -DWITH_TESTS=OFF + -DWITH_TOOLS=OFF + -DWITH_WEB=OFF + -DCMAKE_MODULE_PATH=/usr/local/lib64/cmake + -DCMAKE_PREFIX_PATH=/usr/local + - distro: debian + image_name: debian + - distro: rocky + image_name: rocky + - distro: rocky9 + image_name: rocky9 + - distro: ubuntu + image_name: ubuntu + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Setup ccache + if: matrix.distro == 'fedora' + uses: actions/cache@v6 + with: + path: ${{ github.workspace }}/.ccache + key: ccache-fedora-${{ github.sha }} + restore-keys: ccache-fedora- + + - name: Configure + run: cmake -S . -B build ${{ matrix.cmake_extra_opts || env.CMAKE_EXTRA_OPTS }} + + - name: Build + run: cmake --build build ${{ env.CMAKE_BUILD_OPTS }} + + - name: Upload Build Artifacts + uses: actions/upload-artifact@v7 + with: + name: build-${{ matrix.distro }} + path: build/ + retention-days: 7 diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml new file mode 100644 index 000000000..0c4ef2970 --- /dev/null +++ b/.github/workflows/checks.yaml @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Checks + +on: + workflow_call: + +permissions: + contents: read + +jobs: + build-openapi: + name: Build OpenAPI Documentation + runs-on: ubuntu-latest + container: + image: node:24-alpine + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Lint OpenAPI Specification + run: npx -y @redocly/cli lint --config doc/redocly.yaml doc/openapi/openapi.yaml + + - name: Build OpenAPI Documentation + run: npx -y @redocly/cli build-docs --config doc/redocly.yaml doc/openapi/openapi.yaml --output openapi.html + + - name: Upload OpenAPI HTML Documentation + uses: actions/upload-artifact@v7 + with: + name: openapi + path: openapi.html + + pre-commit: + name: Run pre-commit + runs-on: ubuntu-latest + container: + image: python:3.12.10-slim-bookworm + options: --user root + steps: + - name: Install Git and Ruby + run: apt-get update && apt-get -y install git ruby + + - name: Checkout + uses: actions/checkout@v7 + + - name: Add Git safe Directory + run: git config --global --add safe.directory '*' + + - name: Install pre-commit + run: pip install --no-cache-dir pre-commit + + - name: Run pre-commit + run: pre-commit run --all-files + + - name: Upload Log + if: failure() + uses: actions/upload-artifact@v7 + with: + name: pre-commit-log + path: /github/home/.cache/pre-commit/pre-commit.log + + reuse: + name: Check REUSE Compliance + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v6 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 000000000..f7823837d --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: CI + +on: + push: + branches: [master] + tags: ["v*"] + pull_request: + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + setup: + name: setup + runs-on: ubuntu-latest + outputs: + docker_image: ${{ steps.image.outputs.docker_image }} + steps: + - name: Compute image name for the current repository + id: image + env: + OWNER: ${{ github.repository_owner }} + run: echo "docker_image=ghcr.io/${OWNER,,}/villas/node" >> "$GITHUB_OUTPUT" + + checks: + uses: ./.github/workflows/checks.yaml + secrets: inherit + + paper: + uses: ./.github/workflows/paper.yaml + secrets: inherit + + nix: + uses: ./.github/workflows/nix.yaml + secrets: inherit + + prepare: + needs: [setup] + uses: ./.github/workflows/prepare.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + secrets: inherit + + build: + needs: [setup, prepare] + uses: ./.github/workflows/build.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + secrets: inherit + + test: + needs: [setup, build] + uses: ./.github/workflows/test.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + secrets: inherit + + packaging-docker: + needs: [setup, test, prepare] + uses: ./.github/workflows/packaging-docker.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + secrets: inherit + + packaging-nix: + needs: [setup, nix] + uses: ./.github/workflows/packaging-nix.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + secrets: inherit + + deploy: + needs: [setup, packaging-docker] + uses: ./.github/workflows/deploy.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + is_version_tag: ${{ startsWith(github.ref, 'refs/tags/v') }} + secrets: inherit + + deploy-nix: + needs: [setup, packaging-nix] + uses: ./.github/workflows/deploy-nix.yaml + with: + docker_image: ${{ needs.setup.outputs.docker_image }} + is_version_tag: ${{ startsWith(github.ref, 'refs/tags/v') }} + secrets: inherit + + tag-minor-release: + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + needs: + - setup + - checks + - paper + - nix + - prepare + - build + - test + - packaging-docker + - packaging-nix + - deploy + - deploy-nix + uses: ./.github/workflows/tag-minor-release.yaml + secrets: inherit diff --git a/.github/workflows/cleanup.yaml b/.github/workflows/cleanup.yaml new file mode 100644 index 000000000..26370e767 --- /dev/null +++ b/.github/workflows/cleanup.yaml @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Cleanup + +on: + schedule: + - cron: "0 3 * * *" + workflow_dispatch: + +permissions: + packages: write + +jobs: + cleanup-packages: + name: Packages + runs-on: ubuntu-latest + steps: + # Deletes PR, branch, SHA and content-hash image versions older than + # 14 days. Version tags (v*), master and latest are kept forever. + # Starts in dry-run: review one run's log, then set dry-run to false. + - name: Cleanup GHCR Packages + uses: dataaxiom/ghcr-cleanup-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + owner: ${{ github.repository_owner }} + packages: ^villas/node(/.*)?$ + expand-packages: true + use-regex: true + exclude-tags: ^(latest|master.*|v.*)$ + older-than: 14 days + delete-untagged: true + dry-run: true diff --git a/.github/workflows/deploy-nix.yaml b/.github/workflows/deploy-nix.yaml new file mode 100644 index 000000000..26fa4e032 --- /dev/null +++ b/.github/workflows/deploy-nix.yaml @@ -0,0 +1,101 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Deploy (Nix) + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + is_version_tag: + required: false + type: boolean + default: false + +env: + REGISTRY: ghcr.io + DOCKER_IMAGE: ${{ inputs.docker_image }} + +permissions: + contents: read + packages: write + +jobs: + deploy-docker-nix: + name: Nix-based Docker Images + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Create and Push Multi-arch Nix Manifest + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-nix" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-nix-x86_64-linux" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-nix-aarch64-linux" + + latest-docker-nix: + name: Tag Nix-based Docker Images as latest-nix + if: ${{ inputs.is_version_tag }} + needs: [deploy-docker-nix] + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Tag Nix Manifest as latest-nix + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}:latest-nix" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-nix" + + release-nix: + name: Release Nix + if: ${{ inputs.is_version_tag }} + runs-on: ubuntu-latest + permissions: + contents: write + actions: read + steps: + - name: Download Artifacts + uses: actions/download-artifact@v7 + with: + pattern: villas-* + path: dist + merge-multiple: true + + - name: Publish ARX and RPM Bundles to the Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${GITHUB_REF_NAME}" dist/* \ + --repo "${GITHUB_REPOSITORY}" \ + --title "${GITHUB_REF_NAME}" \ + --generate-notes \ + || gh release upload "${GITHUB_REF_NAME}" dist/* \ + --repo "${GITHUB_REPOSITORY}" --clobber diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml new file mode 100644 index 000000000..f133e2a76 --- /dev/null +++ b/.github/workflows/deploy.yaml @@ -0,0 +1,150 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Deploy + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + is_version_tag: + required: false + type: boolean + default: false + +env: + REGISTRY: ghcr.io + DOCKER_IMAGE: ${{ inputs.docker_image }} + +permissions: + contents: read + packages: write + +jobs: + deploy-docker: + name: Docker Images + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Create and push multi-arch manifest + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-x86_64" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-arm64" + + deploy-docker-dev: + name: Docker Dev Images + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Publish dev image for current ref + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}/dev:${{ steps.ref.outputs.tag }}" \ + "${{ env.DOCKER_IMAGE }}/dev-fedora:${{ steps.ref.outputs.tag }}" + + deploy-docker-dev-vscode: + name: Docker Dev VSCode Images + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Publish dev-vscode image for current ref + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}/dev-vscode:${{ steps.ref.outputs.tag }}" \ + "${{ env.DOCKER_IMAGE }}/dev-vscode:${{ github.sha }}" + + latest-docker: + name: Docker Images as latest + if: ${{ inputs.is_version_tag }} + needs: [deploy-docker] + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Tag and Push Image as latest + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}:latest" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-x86_64" \ + "${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-arm64" + + latest-docker-dev: + name: Docker Dev Images as latest + if: ${{ inputs.is_version_tag }} + needs: [deploy-docker-dev] + runs-on: ubuntu-latest + steps: + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Tag and push dev image as latest + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}/dev:latest" \ + "${{ env.DOCKER_IMAGE }}/dev:${{ steps.ref.outputs.tag }}" diff --git a/.github/workflows/mirror.yaml b/.github/workflows/mirror.yaml deleted file mode 100644 index 7762b1a80..000000000 --- a/.github/workflows/mirror.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# SPDX-FileCopyrightText: 2025 OPAL-RT Germany GmbH -# SPDX-License-Identifier: Apache-2.0 - ---- -name: Mirror to RWTH GitLab - -on: - push: - delete: - -jobs: - mirror: - name: Mirror - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - uses: yesolutions/mirror-action@master - with: - REMOTE: https://git.rwth-aachen.de/acs/public/villas/node.git - GIT_USERNAME: github - GIT_PASSWORD: ${{ secrets.RWTH_GITLAB_TOKEN }} - PUSH_ALL_REFS: "false" diff --git a/.github/workflows/nix.yaml b/.github/workflows/nix.yaml new file mode 100644 index 000000000..fe0c5b449 --- /dev/null +++ b/.github/workflows/nix.yaml @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Nix + +on: + workflow_call: + +permissions: + contents: read + +jobs: + build-nix: + name: "Nix [${{ matrix.system }}]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + system: [x86_64-linux, aarch64-linux] + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install Nix + uses: cachix/install-nix-action@v31 + + - name: Setup Attic Cache + uses: ryanccn/attic-action@v0 + with: + endpoint: https://cache.0l.de + cache: villas + token: ${{ secrets.ATTIC_TOKEN }} + + - name: Build + run: nix build --print-build-logs ".#villas-node-${{ matrix.system }}" diff --git a/.github/workflows/packaging-docker.yaml b/.github/workflows/packaging-docker.yaml new file mode 100644 index 000000000..0baa47012 --- /dev/null +++ b/.github/workflows/packaging-docker.yaml @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Packaging (Docker) + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + +env: + REGISTRY: ghcr.io + DOCKER_IMAGE: ${{ inputs.docker_image }} + CMAKE_EXTRA_OPTS: -DCMAKE_BUILD_TYPE=Release + DOCKER_FILE: packaging/docker/Dockerfile.debian + +permissions: + contents: read + packages: write + +jobs: + pkg-docker-x86_64: + name: "Docker [x86_64]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Build and Push Image + uses: docker/build-push-action@v7 + with: + context: . + file: ${{ env.DOCKER_FILE }} + target: app + push: true + pull: true + platforms: amd64 + cache-from: | + type=gha,scope=dev-debian + type=gha,scope=app-x86_64 + cache-to: type=gha,mode=max,scope=app-x86_64 + build-args: | + ARCH=x86_64 + TRIPLET=x86_64-linux-gnu + CMAKE_OPTS=${{ env.CMAKE_EXTRA_OPTS }} + tags: ${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-x86_64 + + pkg-docker-arm64: + name: "Docker [arm64]" + runs-on: ubuntu-24.04-arm + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Build and Push Image + uses: docker/build-push-action@v7 + with: + context: . + file: packaging/docker/Dockerfile.debian + target: app + push: true + pull: true + platforms: linux/arm64 + cache-from: type=gha,scope=app-arm64 + cache-to: type=gha,mode=max,scope=app-arm64 + build-args: | + ARCH=arm64 + TRIPLET=aarch64-linux-gnu + CMAKE_OPTS=${{ env.CMAKE_EXTRA_OPTS }} + tags: ${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-arm64 diff --git a/.github/workflows/packaging-nix.yaml b/.github/workflows/packaging-nix.yaml new file mode 100644 index 000000000..19596dcf2 --- /dev/null +++ b/.github/workflows/packaging-nix.yaml @@ -0,0 +1,148 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Packaging (Nix) + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + +env: + REGISTRY: ghcr.io + DOCKER_IMAGE: ${{ inputs.docker_image }} + +permissions: + contents: read + packages: write + +jobs: + pkg-nix-arx: + name: "ARX [${{ matrix.system }}]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + system: [x86_64-linux, aarch64-linux] + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install Nix + uses: cachix/install-nix-action@v31 + + - name: Setup Attic Cache + uses: ryanccn/attic-action@v0 + with: + endpoint: https://cache.0l.de + cache: villas + token: ${{ secrets.ATTIC_TOKEN }} + + - name: Bundle as arx + run: | + nix bundle --print-build-logs --out-link bundle-arx \ + --bundler github:nix-community/nix-bundle \ + ".#villas-node-${{ matrix.system }}" + mkdir -p artifacts + cp -L bundle-arx artifacts/villas-${{ matrix.system }} + + - name: Upload ARX Archives + uses: actions/upload-artifact@v7 + with: + name: villas-arx-${{ matrix.system }} + path: artifacts/ + retention-days: 90 + + pkg-nix-rpm: + name: "RPM [${{ matrix.system }}]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + system: [x86_64-linux, aarch64-linux] + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install Nix + uses: cachix/install-nix-action@v31 + + - name: Setup Attic Cache + uses: ryanccn/attic-action@v0 + with: + endpoint: https://cache.0l.de + cache: villas + token: ${{ secrets.ATTIC_TOKEN }} + + - name: Bundle as RPM + run: | + nix bundle --print-build-logs --out-link bundle-rpm \ + --bundler github:NixOS/bundlers#toRPM \ + ".#villas-node-${{ matrix.system }}" + mkdir -p artifacts + cp -L bundle-rpm/*.rpm artifacts/villas-${{ matrix.system }}.rpm + + - name: Upload RPM Package + uses: actions/upload-artifact@v7 + with: + name: villas-rpm-${{ matrix.system }} + path: artifacts/ + retention-days: 90 + + pkg-nix-docker: + name: "Docker [${{ matrix.system }}]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + system: [x86_64-linux, aarch64-linux] + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Install Nix + uses: cachix/install-nix-action@v31 + + - name: Setup Attic Cache + uses: ryanccn/attic-action@v0 + with: + endpoint: https://cache.0l.de + cache: villas + token: ${{ secrets.ATTIC_TOKEN }} + + - name: Bundle as Docker Image + run: | + mkdir -p /var/tmp/ + nix bundle --print-build-logs --out-link bundle-docker \ + --bundler github:NixOS/bundlers#toDockerImage \ + ".#villas-node-${{ matrix.system }}" + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Push to Registry + env: + CONTAINERS_REGISTRIES_CONF: ${{ runner.temp }}/registries.conf + run: | + echo 'unqualified-search-registries = []' > "$CONTAINERS_REGISTRIES_CONF" + nix run nixpkgs#skopeo -- login \ + --username "${{ github.actor }}" \ + --password "${{ secrets.GITHUB_TOKEN }}" \ + "${{ env.REGISTRY }}" + nix run nixpkgs#skopeo -- \ + --tmpdir="${{ runner.temp }}" \ + --insecure-policy \ + copy "docker-archive:./bundle-docker" \ + "docker://${{ env.DOCKER_IMAGE }}:${{ steps.ref.outputs.tag }}-nix-${{ matrix.system }}" diff --git a/.github/workflows/paper.yaml b/.github/workflows/paper.yaml index 8a0981a28..245f9dea2 100644 --- a/.github/workflows/paper.yaml +++ b/.github/workflows/paper.yaml @@ -1,32 +1,27 @@ # SPDX-FileCopyrightText: 2025 OPAL-RT Germany GmbH # SPDX-License-Identifier: Apache-2.0 - ---- name: Draft PDF on: - push: - paths: - - paper/** - - .github/workflows/paper.yaml + workflow_call: jobs: paper: runs-on: ubuntu-latest - name: Paper Draft + name: Build Paper Draft steps: - - name: Checkout - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v7 - - name: Build draft PDF - uses: openjournals/openjournals-draft-action@v1.0 - with: - journal: joss - paper-path: paper/paper.md + - name: Build Draft PDF + uses: openjournals/openjournals-draft-action@v1.0 + with: + journal: joss + paper-path: paper/paper.md - - name: Upload - uses: actions/upload-artifact@v4 - with: - name: paper - path: paper/paper.pdf + - name: Upload PDF + uses: actions/upload-artifact@v7 + with: + name: paper + path: paper/paper.pdf diff --git a/.github/workflows/prepare.yaml b/.github/workflows/prepare.yaml new file mode 100644 index 000000000..a42009f7c --- /dev/null +++ b/.github/workflows/prepare.yaml @@ -0,0 +1,92 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Prepare + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + +env: + REGISTRY: ghcr.io + DOCKER_IMAGE: ${{ inputs.docker_image }} + DOCKER_TAG: ${{ github.sha }} + +permissions: + contents: read + packages: write + +jobs: + prepare-docker: + name: "Prepare Docker Dev Images [${{ matrix.name }}]" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: ubuntu + docker_file: packaging/docker/Dockerfile.ubuntu + image_name: ubuntu + - name: debian + docker_file: packaging/docker/Dockerfile.debian + image_name: debian + - name: rocky + docker_file: packaging/docker/Dockerfile.rocky + image_name: rocky + - name: rocky9 + docker_file: packaging/docker/Dockerfile.rocky9 + image_name: rocky9 + - name: fedora + docker_file: packaging/docker/Dockerfile.fedora + image_name: fedora + - name: fedora-minimal + docker_file: packaging/docker/Dockerfile.fedora-minimal + image_name: fedora-minimal + - name: fedora-vscode + docker_file: packaging/docker/Dockerfile.fedora + image_name: vscode + target: dev-vscode + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Login to Registry + uses: docker/login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Image + uses: docker/setup-buildx-action@v4 + + - name: Compute safe ref Tag + id: ref + run: echo "tag=${GITHUB_REF_NAME//\//-}" >> "$GITHUB_OUTPUT" + + - name: Build and Push Image + uses: docker/build-push-action@v7 + with: + context: . + file: ${{ matrix.docker_file }} + target: ${{ matrix.target || 'dev' }} + push: true + cache-from: type=gha,scope=dev-${{ matrix.image_name }} + cache-to: type=gha,mode=max,scope=dev-${{ matrix.image_name }} + tags: | + ${{ env.DOCKER_IMAGE }}/dev-${{ matrix.image_name }}:${{ env.DOCKER_TAG }} + ${{ env.DOCKER_IMAGE }}/dev-${{ matrix.image_name }}:${{ steps.ref.outputs.tag }} + + - name: Publish fedora dev alias + if: matrix.name == 'fedora' + run: | + docker buildx imagetools create \ + -t "${{ env.DOCKER_IMAGE }}/dev:${{ env.DOCKER_TAG }}" \ + -t "${{ env.DOCKER_IMAGE }}/dev:${{ steps.ref.outputs.tag }}" \ + "${{ env.DOCKER_IMAGE }}/dev-fedora:${{ env.DOCKER_TAG }}" diff --git a/.github/workflows/tag-minor-release.yaml b/.github/workflows/tag-minor-release.yaml new file mode 100644 index 000000000..26ef0fee1 --- /dev/null +++ b/.github/workflows/tag-minor-release.yaml @@ -0,0 +1,60 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Tag Minor Release + +on: + workflow_call: {} + +jobs: + tag-minor-release: + name: Tag Next Minor Version + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + fetch-tags: true + + - name: Determine and create next minor tag + id: next_tag + run: | + set -euo pipefail + + git fetch --tags --force + + latest_tag=$(git tag --list 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n1 || true) + + if [[ -z "${latest_tag}" ]]; then + next_tag="v0.1.0" + else + version="${latest_tag#v}" + major="${version%%.*}" + rest="${version#*.}" + minor="${rest%%.*}" + next_tag="v${major}.$((minor + 1)).0" + fi + + if git rev-parse "${next_tag}" >/dev/null 2>&1; then + echo "Tag ${next_tag} already exists. Skipping creation." + echo "created=false" >> "$GITHUB_OUTPUT" + echo "tag=${next_tag}" >> "$GITHUB_OUTPUT" + exit 0 + fi + + git tag -a "${next_tag}" -m "Release ${next_tag}" + git push origin "${next_tag}" + + echo "created=true" >> "$GITHUB_OUTPUT" + echo "tag=${next_tag}" >> "$GITHUB_OUTPUT" + + - name: Report created tag + run: | + if [[ "${{ steps.next_tag.outputs.created }}" == "true" ]]; then + echo "Created and pushed tag: ${{ steps.next_tag.outputs.tag }}" + else + echo "No new tag created. Existing tag: ${{ steps.next_tag.outputs.tag }}" + fi diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 000000000..53e260794 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,166 @@ +# SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, RWTH Aachen University +# SPDX-License-Identifier: Apache-2.0 + +name: Test + +on: + workflow_call: + inputs: + docker_image: + required: true + type: string + +env: + CMAKE_BUILD_OPTS: --parallel $(nproc) + CMAKE_OPTS: -DCMAKE_INSTALL_PREFIX=${PREFIX} + CCACHE: -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + CCACHE_DIR: ${{ github.workspace }}/.ccache + +permissions: + contents: read + packages: read + actions: read + +jobs: + test-python: + name: Python + runs-on: ubuntu-latest + container: + image: ${{ inputs.docker_image }}/dev-fedora:${{ github.sha }} + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Run Python tests + run: | + cd python + pytest --verbose . + + - name: Check formatting + run: | + cd python + black --line-length=90 --extend-exclude=".*(\.pyi|_pb2.py)$" --check . + + - name: Lint with flake8 + run: | + cd python + flake8 --max-line-length=90 --extend-exclude="*.pyi,*_pb2.py" . + + - name: Type check with mypy + run: | + cd python + mypy --namespace-packages --explicit-package-bases . + + test-cppcheck: + name: CPPCheck + runs-on: ubuntu-latest + container: + image: ${{ inputs.docker_image }}/dev-fedora:${{ github.sha }} + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Run cppcheck + run: ./tools/run-cppcheck.sh | tee cppcheck.log + + - name: Upload CPPCheck Log + uses: actions/upload-artifact@v7 + if: failure() + with: + name: cppcheck-log + path: cppcheck.log + + test-unit: + name: Unit Tests + runs-on: ubuntu-latest + container: + image: ${{ inputs.docker_image }}/dev-fedora:${{ github.sha }} + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Reuse compiled tree from Build Source [fedora] + uses: actions/download-artifact@v7 + with: + name: build-fedora + path: build + + - name: Setup ccache + uses: actions/cache/restore@v6 + with: + path: ${{ github.workspace }}/.ccache + key: ccache-fedora-${{ github.sha }} + restore-keys: ccache-fedora- + + - name: Configure + run: cmake -S . -B build ${{ env.CCACHE }} + + - name: Build and run unit tests + run: LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH cmake --build build ${{ env.CMAKE_BUILD_OPTS }} --target run-unit-tests run-unit-tests-common + + test-integration: + name: Integration Tests + runs-on: ubuntu-latest + container: + image: ${{ inputs.docker_image }}/dev-fedora:${{ github.sha }} + options: --user root + services: + rabbitmq: + image: rwthacs/rabbitmq + redis: + image: redis:6.2 + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + submodules: recursive + + - name: Reuse compiled tree from Build Source [fedora] + uses: actions/download-artifact@v7 + with: + name: build-fedora + path: build + + - name: Setup ccache + uses: actions/cache/restore@v6 + with: + path: ${{ github.workspace }}/.ccache + key: ccache-fedora-${{ github.sha }} + restore-keys: ccache-fedora- + + - name: Start Mosquitto + run: | + echo "127.0.0.1 mosquitto" >> /etc/hosts + cat > /tmp/mosquitto.conf <<'EOF' + listener 1883 + allow_anonymous true + EOF + mosquitto -c /tmp/mosquitto.conf -d + + - name: Configure + run: | + cmake -S . -B build ${{ env.CCACHE }} + cmake --build build --target install + + - name: Build and run Integration Tests + run: cmake --build build --target run-integration-tests + + - name: Upload Integration Test Artifacts + uses: actions/upload-artifact@v7 + if: always() + with: + name: integration-tests + path: build/tests/integration/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index d2fe774a7..000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,409 +0,0 @@ -# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University -# SPDX-License-Identifier: Apache-2.0 - -variables: - GIT_SUBMODULE_STRATEGY: recursive - GIT_DEPTH: 0 - DISTRO: fedora # Standard distribution - DOCKER_FILE: packaging/docker/Dockerfile.${DISTRO} - DOCKER_TAG: ${CI_COMMIT_REF_NAME} - DOCKER_IMAGE: registry.git.rwth-aachen.de/acs/public/villas/node - DOCKER_IMAGE_DEV: ${DOCKER_IMAGE}/dev-${DISTRO} - DOCKER_CLI_EXPERIMENTAL: enabled - CMAKE_BUILD_OPTS: "--parallel 16" - CMAKE_EXTRA_OPTS: "-DCMAKE_BUILD_TYPE=Release" - CMAKE_EXTRA_OPTS_FEDORA_MINIMAL: > - -DVILLAS_COMPILE_WARNING_AS_ERROR=ON - -DWITH_API=OFF - -DWITH_CLIENTS=OFF - -DWITH_CONFIG=OFF - -DWITH_DOC=OFF - -DWITH_FPGA=OFF - -DWITH_GRAPHVIZ=OFF - -DWITH_HOOKS=OFF - -DWITH_LUA=OFF - -DWITH_OPENMP=OFF - -DWITH_PLUGINS=OFF - -DWITH_SRC=OFF - -DWITH_TESTS=OFF - -DWITH_TOOLS=OFF - -DWITH_WEB=OFF - -DCMAKE_MODULE_PATH=/usr/local/lib64/cmake - -DCMAKE_PREFIX_PATH=/usr/local - CACHIX_CACHE_NAME: villas - -stages: - - prepare - - build - - test - - packaging - - deploy - - latest - -# Anchors - -.nix: &nix - image: docker.nix-community.org/nixpkgs/cachix-flakes - - parallel: - matrix: - - SYSTEM: [x86_64-linux, aarch64-linux] - - before_script: - - cachix use "$CACHIX_CACHE_NAME" - -.nix_packaging: &nix_packaging - <<: *nix - - stage: packaging - needs: - - job: build:nix - parallel: - matrix: - - SYSTEM: [x86_64-linux, aarch64-linux] - -.nix_packaging_artifacts: &nix_packaging_artifacts - <<: *nix_packaging - - artifacts: - when: on_success - access: all - expire_in: "1 year" - paths: - - artifacts/* - -# Stage: prepare - -# Build Docker image which is used to build & test VILLASnode -prepare:docker: - stage: prepare - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker build ${DOCKER_OPTS} - --file ${DOCKER_FILE} - --tag ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - --target ${TARGET} . - - docker push ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - variables: - TARGET: dev - parallel: - matrix: - - DISTRO: [ubuntu, debian, rocky, rocky9] - - DISTRO: fedora - DOCKER_OPTS: --tag ${DOCKER_IMAGE}/dev:${DOCKER_TAG} - - DISTRO: fedora - DOCKER_FILE: packaging/docker/Dockerfile.fedora-minimal - DOCKER_IMAGE_DEV: ${DOCKER_IMAGE}/dev-fedora-minimal - - DISTRO: fedora - TARGET: dev-vscode - DOCKER_IMAGE_DEV: ${DOCKER_IMAGE}/dev-vscode - tags: - - docker-image-builder - -# Stage: build - -build:source: - stage: build - needs: ["prepare:docker"] - image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - script: - - cmake -S . -B build ${CMAKE_OPTS} ${CMAKE_EXTRA_OPTS} - - cmake --build build ${CMAKE_BUILD_OPTS} - artifacts: - expire_in: 1 week - paths: - - build/ - variables: - CMAKE: cmake - parallel: - matrix: - - DISTRO: [fedora, fedora-minimal, debian, rocky, rocky9, ubuntu] - - DISTRO: fedora - CMAKE_EXTRA_OPTS: > - -DVILLAS_COMPILE_WARNING_AS_ERROR=ON - - DISTRO: fedora-minimal - CMAKE_EXTRA_OPTS: > - ${CMAKE_EXTRA_OPTS_FEDORA_MINIMAL} - -build:nix: - <<: *nix - - stage: build - needs: [] - - script: - - cachix watch-exec $CACHIX_CACHE_NAME -- - nix build - --print-build-logs - ".#villas-node-${SYSTEM}" - -build:openapi: - stage: build - needs: [] - image: node:24-alpine - script: - - npx -y @redocly/cli lint --config doc/redocly.yaml doc/openapi/openapi.yaml - - npx -y @redocly/cli build-docs --config doc/redocly.yaml doc/openapi/openapi.yaml --output openapi.html - artifacts: - paths: - - openapi.html - -# Stage: test - -test:pre-commit: - needs: [] - image: python:3.12.10-slim-bookworm - before_script: - - pip install pre-commit - script: - - apt-get update && apt-get -y install git ruby - - pre-commit run --all-files - -test:python: - stage: test - script: - - cd python - - pytest --verbose . - - black --line-length=90 --extend-exclude=".*(\\.pyi|_pb2.py)$" --check . - - flake8 --max-line-length=90 --extend-exclude="*.pyi,*_pb2.py" . - - mypy --namespace-packages --explicit-package-bases . - image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - needs: - - job: "build:source: [fedora]" - -test:cppcheck: - stage: test - script: - - ./tools/run-cppcheck.sh | tee cppcheck.log - image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - needs: - - job: "build:source: [fedora]" - artifacts: - when: on_failure - paths: - - cppcheck.log - expose_as: cppcheck - -test:unit: - stage: test - image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - script: - - cmake -S . -B build ${CMAKE_OPTS} - - cmake --build build ${CMAKE_BUILD_OPTS} --target run-unit-tests run-unit-tests-common - needs: - - job: "build:source: [fedora]" - artifacts: true - -test:integration: - stage: test - image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} - script: - - cmake -S . -B build ${CMAKE_OPTS} - - cmake --build build ${CMAKE_BUILD_OPTS} --target run-integration-tests - artifacts: - name: ${CI_PROJECT_NAME}-integration-tests-${CI_BUILD_REF} - when: always - paths: - - build/tests/integration/ - services: - - name: eclipse-mosquitto:2.0 - alias: mosquitto - command: [mosquitto, -c, /mosquitto-no-auth.conf] - - name: rwthacs/rabbitmq - alias: rabbitmq - - name: redis:6.2 - alias: redis - needs: - - job: "build:source: [fedora]" - artifacts: true - -test:reuse: - stage: test - needs: [] - image: - name: fsfe/reuse:latest - entrypoint: [""] - script: - - reuse lint - -# Stage: packaging - -pkg:docker: - stage: packaging - needs: [] - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker build ${DOCKER_OPTS} - --pull - --target ${TARGET} - --build-arg ARCH=${ARCH} - --build-arg TRIPLET=${TRIPLET} - --build-arg CMAKE_OPTS="${CMAKE_OPTS} ${CMAKE_EXTRA_OPTS}" - --platform ${PLATFORM} - --file ${DOCKER_FILE} - --tag ${DOCKER_IMAGE}:${DOCKER_TAG}-${ARCH} . - - docker push ${DOCKER_IMAGE}:${DOCKER_TAG}-${ARCH} - tags: - - $TAG - variables: - TARGET: app - parallel: - matrix: - - DISTRO: debian - PLATFORM: linux/amd64 - ARCH: x86_64 - TRIPLET: x86_64-linux-gnu - TAG: docker - - DISTRO: debian - PLATFORM: linux/arm64/v8 - ARCH: arm64 - TRIPLET: aarch64-linux-gnu - TAG: pi5 - -pkg:nix:arx: - <<: *nix_packaging_artifacts - - script: - - cachix watch-exec $CACHIX_CACHE_NAME -- - nix bundle - --print-build-logs - --out-link bundle-arx - --bundler github:nix-community/nix-bundle - ".#villas-node-${SYSTEM}" - - - mkdir -p artifacts - - cp -L bundle-arx artifacts/villas-${SYSTEM} - -pkg:nix:rpm: - <<: *nix_packaging_artifacts - - script: - - cachix watch-exec $CACHIX_CACHE_NAME -- - nix bundle - --print-build-logs - --out-link bundle-rpm - --bundler github:NixOS/bundlers#toRPM - ".#villas-node-${SYSTEM}" - - - mkdir -p artifacts - - cp -L bundle-rpm/*.rpm artifacts/villas-${SYSTEM}.rpm - -pkg:nix:docker: - <<: *nix_packaging - - script: - - mkdir -p /var/tmp/ - - cachix watch-exec $CACHIX_CACHE_NAME -- - nix bundle - --print-build-logs - --out-link bundle-docker - --bundler github:NixOS/bundlers#toDockerImage - ".#villas-node-${SYSTEM}" - - - nix run nixpkgs#skopeo -- - login - --username ${CI_REGISTRY_USER} - --password ${CI_REGISTRY_PASSWORD} - ${CI_REGISTRY} - - - nix run nixpkgs#skopeo -- - --tmpdir=${TMPDIR} - --insecure-policy - copy "docker-archive:./bundle-docker" "docker://${DOCKER_IMAGE}:${DOCKER_TAG}-nix-${SYSTEM}" - -# Stage: deploy - -deploy:docker: - stage: deploy - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker manifest rm ${DOCKER_IMAGE}:${DOCKER_TAG} || true - - docker manifest create ${DOCKER_IMAGE}:${DOCKER_TAG} - ${DOCKER_IMAGE}:${DOCKER_TAG}-x86_64 - ${DOCKER_IMAGE}:${DOCKER_TAG}-arm64 - - docker manifest push ${DOCKER_IMAGE}:${DOCKER_TAG} - tags: - - docker - needs: - - job: "pkg:docker: [debian, linux/amd64, x86_64, x86_64-linux-gnu, docker]" - - job: "pkg:docker: [debian, linux/arm64/v8, arm64, aarch64-linux-gnu, pi5]" - -deploy:docker-dev: - stage: deploy - variables: - DOCKER_CLI_EXPERIMENTAL: enabled - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker push ${DOCKER_IMAGE}/dev:${DOCKER_TAG} - tags: - - docker - needs: - - job: "prepare:docker: [fedora, --tag ${DOCKER_IMAGE}/dev:${DOCKER_TAG}]" - -deploy:docker-dev-vscode: - stage: deploy - variables: - DOCKER_CLI_EXPERIMENTAL: enabled - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker push ${DOCKER_IMAGE}/dev-vscode:${DOCKER_TAG} - tags: - - docker - needs: - - job: "prepare:docker: [fedora, dev-vscode, ${DOCKER_IMAGE}/dev-vscode]" - -# Stage: latest - -.latest:docker:latest: &deploy_latest_docker - stage: latest - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker manifest rm ${DOCKER_IMAGE}:latest || true - - docker manifest create ${DOCKER_IMAGE}:latest - ${DOCKER_IMAGE}:${DOCKER_TAG}-x86_64 - ${DOCKER_IMAGE}:${DOCKER_TAG}-arm64 - - docker manifest push ${DOCKER_IMAGE}:latest - tags: - - docker - needs: - - job: deploy:docker - -.latest:docker-dev:latest: &deploy_latest_docker_dev - stage: latest - before_script: - - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY} - script: - - docker tag ${DOCKER_IMAGE}/dev:${DOCKER_TAG} ${DOCKER_IMAGE}/dev:latest - - docker push ${DOCKER_IMAGE}/dev:latest - tags: - - docker - needs: - - job: deploy:docker-dev - -latest:docker: - <<: *deploy_latest_docker - only: - - "/^v\\d+(\\.\\d+)+$/" # Only on version tags - -latest:docker-dev: - <<: *deploy_latest_docker_dev - only: - - "/^v\\d+(\\.\\d+)+$/" # Only on version tags - -latest:docker:manual: - <<: *deploy_latest_docker - when: manual - except: - - "/^v\\d+(\\.\\d+)+$/" # Only on version tags - -latest:docker-dev:manual: - <<: *deploy_latest_docker_dev - when: manual - except: - - "/^v\\d+(\\.\\d+)+$/" # Only on version tags diff --git a/README.md b/README.md index 36f735ec2..1f31fde28 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # VILLASnode -[![build status](https://git.rwth-aachen.de/acs/public/villas/node/badges/master/pipeline.svg)](https://git.rwth-aachen.de/acs/public/villas/node/-/pipelines/) +[![build status](https://github.com/VILLASframework/node/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/VILLASframework/node/actions/workflows/ci.yaml) [![status](https://joss.theoj.org/papers/37c2509d36586f4cec2885d5c2088e8f/status.svg)](https://joss.theoj.org/papers/37c2509d36586f4cec2885d5c2088e8f) This is VILLASnode, a gateway for processing and forwarding simulation data between real-time simulators. diff --git a/doc/openapi/components/schemas/config/nodes/infiniband.yaml b/doc/openapi/components/schemas/config/nodes/infiniband.yaml index 63867b478..fc8ad85b6 100644 --- a/doc/openapi/components/schemas/config/nodes/infiniband.yaml +++ b/doc/openapi/components/schemas/config/nodes/infiniband.yaml @@ -17,7 +17,7 @@ allOf: This specifies the type of connection the node will set up. * `RC` provides reliable, connection-oriented, message based communication between the nodes. Packets are delivered in order. In this mode, one Queue Pair is connected to one other Queue Pair. - * `UC` provides unreliable, connection-oriented, message based communication between the nodes. This service type is not officially supported by the RDMA communication manager and is implemented for scientific purposes in VILLASnode. [The InfiniBand node-type source code provides information on how to enable this service type.](https://git.rwth-aachen.de/acs/public/villas/node/blob/master/lib/nodes/infiniband.c#L429) + * `UC` provides unreliable, connection-oriented, message based communication between the nodes. This service type is not officially supported by the RDMA communication manager and is implemented for scientific purposes in VILLASnode. The InfiniBand node-type source code provides information on how to enable this service type. * `UD` provides unreliable, connection-less, datagram communication between nodes. Both ordering and delivery are not guaranteed in this mode. `RC`, `UC`, and `UD` are mapped to the Queue Pair types as `RDMA_PS_TCP`/`IBV_QPT_RC`, `RDMA_PS_IPOIB`/`IBV_QPT_UC`, and `RDMA_PS_UDP`/`IBV_QPT_UD`, respectively. diff --git a/flake.nix b/flake.nix index b22c742b2..c7484f02a 100644 --- a/flake.nix +++ b/flake.nix @@ -5,10 +5,10 @@ nixConfig = { extra-substituters = [ - "https://villas.cachix.org" + "https://cache.0l.de/villas" ]; extra-trusted-public-keys = [ - "villas.cachix.org-1:vCWp9IzwxFT6ovZivQAvn5ZuLST01bpAGXWwlGTZ9fA=" + "villas:vZYuJcdoDPp60fe/LagBlf8vSQfVJpxmEd/pGxSS+DQ=" ]; }; @@ -166,24 +166,26 @@ ruby # for pre-commit markdownlint hook ]; - mkShellFor = stdenv: pkg: stdenv.mkDerivation { - name = "${pkg.pname}-${stdenv.cc.cc.pname}-devShell"; - - # disable all hardening to suppress warnings in debug builds - hardeningDisable = [ "all" ]; - - # inherit inputs from pkg - buildInputs = pkg.buildInputs ++ packages; - nativeBuildInputs = pkg.nativeBuildInputs ++ packages; - propagatedBuildInputs = pkg.propagatedBuildInputs; - propagatedNativeBuildInputs = pkg.propagatedNativeBuildInputs; - - # configure nix-ld for pre-commit - env = { - NIX_LD = lib.fileContents "${stdenv.cc}/nix-support/dynamic-linker"; - NIX_LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.gcc-unwrapped.lib ]; + mkShellFor = + stdenv: pkg: + stdenv.mkDerivation { + name = "${pkg.pname}-${stdenv.cc.cc.pname}-devShell"; + + # disable all hardening to suppress warnings in debug builds + hardeningDisable = [ "all" ]; + + # inherit inputs from pkg + buildInputs = pkg.buildInputs ++ packages; + nativeBuildInputs = pkg.nativeBuildInputs ++ packages; + propagatedBuildInputs = pkg.propagatedBuildInputs; + propagatedNativeBuildInputs = pkg.propagatedNativeBuildInputs; + + # configure nix-ld for pre-commit + env = { + NIX_LD = lib.fileContents "${stdenv.cc}/nix-support/dynamic-linker"; + NIX_LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.gcc-unwrapped.lib ]; + }; }; - }; in rec { default = gcc; diff --git a/packaging/archlinux/PKGBUILD b/packaging/archlinux/PKGBUILD index add2dd000..3da484083 100644 --- a/packaging/archlinux/PKGBUILD +++ b/packaging/archlinux/PKGBUILD @@ -18,9 +18,9 @@ makedepends=('libconfig') depends=('libwebsockets' 'zeromq' 'nanomsg' 'libxil' 'openssl' 'jansson' 'curl' 'libnl' 'protobuf' 'libpgm') -repo=VILLASnode -url="https://git.rwth-aachen.de/acs/public/villas/$repo" -source=("$url/repository/$branch/archive.tar.bz2") +repo=node +url="https://github.com/VILLASframework/$repo" +source=("$url/archive/refs/heads/$branch.tar.gz") sha256sums=(SKIP) prepare() { diff --git a/packaging/docker/Dockerfile.fedora b/packaging/docker/Dockerfile.fedora index 2beee634f..c78a8fca0 100644 --- a/packaging/docker/Dockerfile.fedora +++ b/packaging/docker/Dockerfile.fedora @@ -6,7 +6,8 @@ ARG DISTRO=fedora ARG FEDORA_VERSION=42 -ARG REF=unknown +ARG ARCH=x86_64 +ARG REF=villasnode FROM ${DISTRO}:${FEDORA_VERSION} AS dev @@ -15,7 +16,7 @@ ARG DISTRO # Toolchain RUN dnf -y install \ gcc-14 g++-14 \ - pkgconfig cmake make meson ninja \ + pkgconfig cmake make meson ninja ccache \ autoconf automake autogen libtool \ texinfo git awk git-svn curl tar patchutils \ flex bison \ @@ -111,6 +112,10 @@ RUN groupadd --gid $USER_GID $USERNAME \ FROM dev AS app ARG CMAKE_OPTS +ARG DISTRO +ARG FEDORA_VERSION +ARG ARCH +ARG REF COPY . /villas/ diff --git a/packaging/docker/Dockerfile.fedora-minimal b/packaging/docker/Dockerfile.fedora-minimal index addcd6505..749bbedc6 100644 --- a/packaging/docker/Dockerfile.fedora-minimal +++ b/packaging/docker/Dockerfile.fedora-minimal @@ -41,7 +41,7 @@ WORKDIR /villas/build RUN cmake ${CMAKE_OPTS} -DCPACK_GENERATOR=RPM .. && \ make -j$(nproc) package -FROM ${DISTRO}:${FEDORA_VERSION} as app +FROM ${DISTRO}:${FEDORA_VERSION} AS app COPY --from=builder /villas/build/*.rpm /tmp/ RUN dnf -y install /tmp/*.rpm diff --git a/packaging/docker/Dockerfile.ubuntu b/packaging/docker/Dockerfile.ubuntu index 5a4a0c506..76c21e2a7 100644 --- a/packaging/docker/Dockerfile.ubuntu +++ b/packaging/docker/Dockerfile.ubuntu @@ -15,6 +15,11 @@ ARG DISTRO ENV DEBIAN_FRONTEND=noninteractive +# Prefer the Azure mirror (archive.ubuntu.com throttles from CI); default kept as fallback +RUN sed -i -E \ + 's#https?://(archive|security)\.ubuntu\.com/ubuntu/?#http://azure.archive.ubuntu.com/ubuntu/ &#g' \ + /etc/apt/sources.list.d/ubuntu.sources 2>/dev/null || true + # Toolchain RUN apt-get update && \ apt-get install -y \ diff --git a/tools/villas-install.sh b/tools/villas-install.sh index 1dfb213b2..7eb25fe3c 100755 --- a/tools/villas-install.sh +++ b/tools/villas-install.sh @@ -11,6 +11,8 @@ set -e # Parameters INSTALL_DIR=${INSTALL_DIR:-/usr/local/bin} INSTALL_PATH="${INSTALL_DIR}/villas" +GITHUB_REPOSITORY=${GITHUB_REPOSITORY:-VILLASframework/node} +VILLAS_TAG=${VILLAS_TAG:-latest} echo "===" echo "=== This script will download a single-binary / standalone build of VILLASnode and install it to ${INSTALL_PATH}" @@ -40,40 +42,35 @@ fi echo "=== [info] Detected supported system: ${ARCH}-${OS}" -GITLAB_URL="https://git.rwth-aachen.de" -GITLAB_PROJECT="79039" -GITLAB_BRANCH="master" -GITLAB_ARTIFACT="artifacts/villas-${ARCH}-${OS}" -GITLAB_JOB="pkg:nix:arx: [${ARCH}-${OS}]" +RELEASE_ASSET="villas-${ARCH}-${OS}" -DOWNLOAD_URL="${GITLAB_URL}/api/v4/projects/${GITLAB_PROJECT}/jobs/artifacts/${GITLAB_BRANCH}/raw/${GITLAB_ARTIFACT}" +if [[ "${VILLAS_TAG}" == "latest" ]]; then + DOWNLOAD_URL="https://github.com/${GITHUB_REPOSITORY}/releases/latest/download/${RELEASE_ASSET}" +else + DOWNLOAD_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${VILLAS_TAG}/${RELEASE_ASSET}" +fi echo "=== [info] Downloading VILLASnode binary" -if $(command -v curl >/dev/null 2>&1); then - echo " from ${DOWNLOAD_URL}?job=${GITLAB_JOB}" +if command -v curl >/dev/null 2>&1; then + echo " from ${DOWNLOAD_URL}" echo " to ${DOWNLOAD_PATH}" if ! curl \ --fail-with-body \ - --get \ --location \ --header "Accept-Encoding: gzip, deflate" \ --output "${DOWNLOAD_PATH}" \ - --data-urlencode "job=${GITLAB_JOB}" \ "${DOWNLOAD_URL}"; then echo "=== [error] curl failed to download VILLASnode binary" + echo "=== [info] Tried release tag: ${VILLAS_TAG}" + echo "=== [info] Override with: VILLAS_TAG= ./tools/villas-install.sh" exit 1 fi else echo "=== [error] curl is not available. Please install it." exit 1 fi -if [[ $? -ne 0 ]]; then - echo "=== [error] Failed to download VILLASnode binary from ${DOWNLOAD_URL}" - exit 1 -fi - chmod +x "${DOWNLOAD_PATH}" if [[ $EUID -ne 0 ]]; then diff --git a/web/webrtc.html b/web/webrtc.html index b0d71e7ca..65b6026ec 100644 --- a/web/webrtc.html +++ b/web/webrtc.html @@ -463,7 +463,7 @@