From ca32d15e8bfb006caf4b62c94420cb81497568dd Mon Sep 17 00:00:00 2001 From: ndr_brt Date: Tue, 24 Feb 2026 09:09:17 +0100 Subject: [PATCH] build: move release workflows from Release repository --- .github/CODEOWNERS | 11 +++ .github/workflows/platform-nightly.yml | 96 +++++++++++++++++++ .../workflows/platform-prepare-release.yml | 85 ++++++++++++++++ .github/workflows/platform-release.yml | 86 +++++++++++++++++ README.md | 11 +++ scripts/github_action.sh | 96 +++++++++++++++++++ 6 files changed, 385 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/platform-nightly.yml create mode 100644 .github/workflows/platform-prepare-release.yml create mode 100644 .github/workflows/platform-release.yml create mode 100644 README.md create mode 100755 scripts/github_action.sh diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3ad0201 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,11 @@ +# This file provides an overview of responsibilities in this repository. + +# Please note that this file does not represent all contributions to the code. What persons and organizations +# actually contributed to each file can be seen on GitHub and is documented in the license headers. + +# Linked persons with write permissions are automatically added as reviewers when a pull request is opened. + +# Each line is a file pattern followed by one or more contact persons. The last matching pattern has the most precedence. +# For more details, read the following article on GitHub: https://help.github.com/articles/about-codeowners/. + +* @eclipse-edc/technology-edc-committers diff --git a/.github/workflows/platform-nightly.yml b/.github/workflows/platform-nightly.yml new file mode 100644 index 0000000..66e0f4e --- /dev/null +++ b/.github/workflows/platform-nightly.yml @@ -0,0 +1,96 @@ +name: Nightly + +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" # run at 00:00 UTC + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + Determine-Version: + runs-on: ubuntu-latest + outputs: + VERSION: ${{ steps.get-version.outputs.VERSION }} + steps: + - name: "Extract version" + id: get-version + run: | + wget -cq https://raw.githubusercontent.com/eclipse-edc/Connector/main/gradle.properties + echo "VERSION=$(IFS=.- read -r RELEASE_VERSION_MAJOR RELEASE_VERSION_MINOR RELEASE_VERSION_PATCH SNAPSHOT<<<$(grep "version" gradle.properties | awk -F= '{print $2}') && echo $RELEASE_VERSION_MAJOR.$RELEASE_VERSION_MINOR.$RELEASE_VERSION_PATCH-$(date +"%Y%m%d")-SNAPSHOT)" >> "$GITHUB_OUTPUT" + + Runtime-Metamodel: + runs-on: ubuntu-latest + needs: [ Determine-Version ] + steps: + - uses: actions/checkout@v6 + - name: RuntimeMetamodel ${{ needs.Determine-Version.outputs.VERSION }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "runtime-metamodel" "nightly.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" + + GradlePlugins: + runs-on: ubuntu-latest + needs: [ Runtime-Metamodel ] + steps: + - uses: actions/checkout@v6 + - name: GradlePlugins ${{ needs.Determine-Version.outputs.VERSION }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "gradleplugins" "nightly.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" + + Connector: + runs-on: ubuntu-latest + needs: [ GradlePlugins ] + steps: + - uses: actions/checkout@v6 + - name: Connector ${{ needs.Determine-Version.outputs.VERSION }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "connector" "nightly.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" + + IdentityHub-FederatedCatalog: + runs-on: ubuntu-latest + needs: [ Connector ] + strategy: + fail-fast: false + matrix: + repository: [ "identityhub", "federatedcatalog" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ needs.Determine-Version.outputs.VERSION }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "nightly.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" + + Technology: + runs-on: ubuntu-latest + needs: [ IdentityHub-FederatedCatalog ] + continue-on-error: true + strategy: + fail-fast: false + matrix: + repository: [ "technology-aws", "technology-azure", "technology-gcp", "technology-huaweicloud" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ needs.Determine-Version.outputs.VERSION }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "nightly.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" + + Post-To-Discord: + needs: [ Determine-Version, Runtime-Metamodel, GradlePlugins, Connector, IdentityHub-FederatedCatalog, Technology ] + if: "always()" + runs-on: ubuntu-latest + steps: + - uses: sarisia/actions-status-discord@v1 + name: "Invoke discord webhook" + with: + webhook: ${{ secrets.DISCORD_GITHUB_CI_WEBHOOK }} + status: ${{ needs.Runtime-Metamodel.result && needs.GradlePlugins.result && needs.Connector.result && needs.IdentityHub-FederatedCatalog.result && needs.Technology.result }} + title: "Nightly Build" + description: "Build and publish ${{ needs.Determine-Version.outputs.VERSION }}" + username: GitHub Actions diff --git a/.github/workflows/platform-prepare-release.yml b/.github/workflows/platform-prepare-release.yml new file mode 100644 index 0000000..0084adf --- /dev/null +++ b/.github/workflows/platform-prepare-release.yml @@ -0,0 +1,85 @@ +name: Prepare release + +on: + workflow_dispatch: + inputs: + version: + description: Semantic Version string to use for this release + required: true + branch: + description: Source ranch from which the version should be created. If omitted, 'main' is used. Please note that the branch should be available in all the core repositories. + required: false + default: main + +jobs: + + Runtime-Metamodel: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: RuntimeMetamodel ${{ inputs.version }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "runtime-metamodel" "prepare-release.yml" "{\"version\": \"${{ inputs.version }}\"}" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + GradlePlugins: + runs-on: ubuntu-latest + needs: [ Runtime-Metamodel ] + steps: + - uses: actions/checkout@v6 + - name: GradlePlugins ${{ inputs.version }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "gradleplugins" "prepare-release.yml" "{\"version\": \"${{ inputs.version }}\"}" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Connector: + runs-on: ubuntu-latest + needs: [ GradlePlugins ] + steps: + - uses: actions/checkout@v6 + - name: Connector ${{ inputs.version }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "connector" "prepare-release.yml" "{\"version\": \"${{ inputs.version }}\"}" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + IdentityHub-FederatedCatalog: + runs-on: ubuntu-latest + needs: [ Connector ] + strategy: + fail-fast: false + matrix: + repository: [ "identityhub", "federatedcatalog" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ inputs.version }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "prepare-release.yml" "{\"version\": \"${{ inputs.version }}\"}" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Technology: + runs-on: ubuntu-latest + needs: [ IdentityHub-FederatedCatalog ] + strategy: + fail-fast: false + matrix: + repository: [ "technology-aws", "technology-azure", "technology-gcp", "technology-huaweicloud" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ inputs.version }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "prepare-release.yml" "{\"version\": \"${{ inputs.version }}\"}" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Post-To-Discord: + needs: [ Runtime-Metamodel, GradlePlugins, Connector, IdentityHub-FederatedCatalog, Technology ] + if: "always()" + runs-on: ubuntu-latest + steps: + - uses: sarisia/actions-status-discord@v1 + name: "Invoke discord webhook" + with: + webhook: ${{ secrets.DISCORD_GITHUB_CI_WEBHOOK }} + status: ${{ needs.Runtime-Metamodel.result && needs.GradlePlugins.result && needs.Connector.result && needs.IdentityHub-FederatedCatalog.result && needs.Technology.result }} + title: "Release Preparation" + description: "Release preparation ${{ inputs.version }}" + username: GitHub Actions diff --git a/.github/workflows/platform-release.yml b/.github/workflows/platform-release.yml new file mode 100644 index 0000000..911b56b --- /dev/null +++ b/.github/workflows/platform-release.yml @@ -0,0 +1,86 @@ +name: Release + +on: + workflow_dispatch: + inputs: + branch: + description: Source branch from which the version should be created. 'main' should never be used, to create a release branch please trigger the "prepare" workflow before. + required: true + + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + + Runtime-Metamodel: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: RuntimeMetamodel ${{ inputs.branch }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "runtime-metamodel" "release.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + GradlePlugins: + runs-on: ubuntu-latest + needs: [ Runtime-Metamodel ] + steps: + - uses: actions/checkout@v6 + - name: GradlePlugins ${{ inputs.branch }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "gradleplugins" "release.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Connector: + runs-on: ubuntu-latest + needs: [ GradlePlugins ] + steps: + - uses: actions/checkout@v6 + - name: Connector ${{ inputs.branch }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "connector" "release.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + IdentityHub-FederatedCatalog: + runs-on: ubuntu-latest + needs: [ Connector ] + strategy: + fail-fast: false + matrix: + repository: [ "identityhub", "federatedcatalog" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ inputs.branch }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "release.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Technology: + runs-on: ubuntu-latest + needs: [ IdentityHub-FederatedCatalog ] + strategy: + fail-fast: false + matrix: + repository: [ "technology-aws", "technology-azure", "technology-gcp", "technology-huaweicloud" ] + steps: + - uses: actions/checkout@v6 + - name: ${{ matrix.repository }} ${{ inputs.branch }} + run: | + chmod +x ./scripts/github_action.sh + ./scripts/github_action.sh "eclipse-edc" "${{ matrix.repository }}" "release.yml" "" "${{ secrets.ORG_GITHUB_BOT_USER }}" "${{ secrets.ORG_GITHUB_BOT_TOKEN }}" "${{ inputs.branch }}" + + Post-To-Discord: + needs: [ Runtime-Metamodel, GradlePlugins, Connector, IdentityHub-FederatedCatalog, Technology ] + if: "always()" + runs-on: ubuntu-latest + steps: + - uses: sarisia/actions-status-discord@v1 + name: "Invoke discord webhook" + with: + webhook: ${{ secrets.DISCORD_GITHUB_CI_WEBHOOK }} + status: ${{ needs.Runtime-Metamodel.result && needs.GradlePlugins.result && needs.Connector.result && needs.IdentityHub-FederatedCatalog.result && needs.Technology.result }} + title: "Nightly Build" + description: "Release ${{ inputs.branch }}" + username: GitHub Actions diff --git a/README.md b/README.md new file mode 100644 index 0000000..f68e5e3 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Eclipse Dataspace Components .github + +This repository contains common workflows and templates for the EDC projects. + +## Release + +To release all the components, run the [`platform-prepare-release.yml`](./.github/workflows/platform-prepare-release.yml) +workflow to prepare the release in all the repositories. + +After it finishes, [`platform-release.yml`](./.github/workflows/platform-release.yml) can be triggered, and all the +repositories will be released in the correct order. diff --git a/scripts/github_action.sh b/scripts/github_action.sh new file mode 100755 index 0000000..6a043ce --- /dev/null +++ b/scripts/github_action.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +OWNER="$1" +REPO_NAME="$2" +WORKFLOW="$3" +INPUTS="$4" +USER="$5" +PWD="$6" +BRANCH="$7" + +if [ "$#" -eq 5 ]; then + # use cURL with a Personal Access Token + echo "Using USER as personal access token for the GitHub API" + PARAMS=(-H "Authorization: Bearer $USER" -H "Accept: application/vnd.github.v3+json") + +elif [ "$#" -ge 6 ]; then + # use basic auth with cUrl + echo "Using USER/PWD authentication for the GitHub API" + PARAMS=(-u "$USER":"$PWD" -H "Accept: application/vnd.github.v3+json") + +else + echo "Usage: github_action.sh OWNER REPO_NAME WORKFLOW INPUTS USER [PWD]" + echo "OWNER = the owner/org of the github repo" + echo "REPO_NAME = the name of the github repo" + echo "WORKFLOW = the name of the workflow file to run, or its ID" + echo "INPUTS = json representation of the workflow input" + echo "USER = the username to use for authentication against the GitHub API, or an API token" + echo "PWD = the password of USER. if not specified, USER will be interpreted as token" + echo "BRANCH" = the branch on which to execute the action. Defaults to "main" + exit 1 +fi + +REPO="$OWNER/$REPO_NAME" +WORKFLOW_PATH="$REPO/actions/workflows/$WORKFLOW" + +# run actions on "main" by default +if [ -z "${BRANCH}" ]; then + BRANCH="main" +fi + +if [ -z "${INPUTS}" ]; then + TRIGGER_BODY="{\"ref\": \"${BRANCH}\"}" +else + TRIGGER_BODY="{\"ref\": \"${BRANCH}\", \"inputs\": ${INPUTS}}" +fi + +echo "$WORKFLOW_PATH :: $(date) :: Trigger the workflow with ${TRIGGER_BODY}" +STATUSCODE=$(curl --location --request POST --write-out "%{http_code}" "https://api.github.com/repos/${WORKFLOW_PATH}/dispatches" \ + "${PARAMS[@]}" \ + --data-raw "${TRIGGER_BODY}") + +if [ "$STATUSCODE" != 204 ]; then + echo "$WORKFLOW_PATH :: $(date) :: Cannot trigger workflow. Response code: $STATUSCODE" + exit 1 +fi + +# this is not working anymore, details: https://github.com/orgs/community/discussions/53266 +# numRuns=0 +# echo "$WORKFLOW_PATH :: $(date) :: Waiting for workflow to start" +# while [ "$numRuns" -le "0" ]; do +# sleep 3 +# # fetch the latest run triggered by a workflow_dispatch event +# runs=$(curl --fail -sSl "${PARAMS[@]}" -X GET "https://api.github.com/repos/${WORKFLOW_PATH}/runs?event=workflow_dispatch&status=in_progress") +# numRuns=$(echo "$runs" | jq -r '.total_count') +# echo "$WORKFLOW_PATH :: $(date) :: found $numRuns runs" +# done + +status= +echo "$WORKFLOW_PATH :: $(date) :: Waiting for workflow to start" +while [ "$status" != "in_progress" ]; do + sleep 5 + # fetch the latest run triggered by a workflow_dispatch event + runs=$(curl --fail -sSl "${PARAMS[@]}" -X GET "https://api.github.com/repos/${WORKFLOW_PATH}/runs?event=workflow_dispatch&per_page=1") + status=$(echo "$runs" | jq -r '.workflow_runs[0].status') + echo "$WORKFLOW_PATH :: $(date) :: status $status" +done + +# contains the ID of the latest/most recent run +RUN_ID=$(echo "$runs" | jq -r '.workflow_runs[0].id') + +echo "$WORKFLOW_PATH :: $(date) :: Waiting for run $RUN_ID to complete" +while [ "$status" != "completed" ]; do + json=$(curl --fail -sSl "${PARAMS[@]}" -X GET "https://api.github.com/repos/${REPO}/actions/runs/${RUN_ID}") + status=$(echo "$json" | jq -r '.status') + conclusion=$(echo "$json" | jq -r '.conclusion') + echo "$WORKFLOW_PATH :: $(date) :: Run $RUN_ID is $status" + if [ "$status" != "completed" ]; then + sleep 30 # sleep for 30 seconds before we check again, lets keep API requests low + fi +done + +echo "$WORKFLOW_PATH :: $(date) :: Run completed, conclusion: $conclusion" + +if [ "$conclusion" != "success" ]; then + exit 1 +fi