You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/09/07 09:45:25 UTC

(opendal) 01/01: fix(ci): dispatch weekly RC builds and notify release managers

This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a commit to branch xuanwo/weekly-release-handoff
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 93119984c8eeeab24354f2bfe0107b02a2495382
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Mon Sep 7 17:45:07 2026 +0800

    fix(ci): dispatch weekly RC builds and notify release managers
---
 .github/workflows/docs.yml           |  8 +++-
 .github/workflows/release_ruby.yml   |  5 ++-
 .github/workflows/weekly_release.yml | 80 ++++++++++++++++++++++++++++++++++++
 website/community/release/weekly.md  | 22 ++++++++--
 4 files changed, 107 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index c1e8396e7b..cf0e1a59a3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -37,6 +37,10 @@ on:
     paths: *paths
   workflow_dispatch:
     inputs:
+      deploy-nightlies:
+        description: "Deploy built documentation to nightlies"
+        type: boolean
+        default: true
       release_version:
         description: "Release tag to deploy to nightlies"
         required: true
@@ -642,7 +646,7 @@ jobs:
           OPENDAL_WEBSITE_NOT_LATEST: true
 
       - name: Deploy to nightlies for tagged version
-        if: ${{ (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'rc')) || github.event_name == 'workflow_dispatch' }}
+        if: ${{ (github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'rc')) || (github.event_name == 'workflow_dispatch' && inputs.deploy-nightlies) }}
         shell: bash
         env:
           NIGHTLIES_RSYNC_HOST: ${{ secrets.NIGHTLIES_RSYNC_HOST }}
@@ -670,7 +674,7 @@ jobs:
           OPENDAL_WEBSITE_BASE_URL: /opendal/opendal-docs-stable/
 
       - name: Deploy to nightlies for stable version
-        if: ${{ (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'rc')) || github.event_name == 'workflow_dispatch' }}
+        if: ${{ (github.event_name != 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/') && !contains(github.ref, 'rc')) || (github.event_name == 'workflow_dispatch' && inputs.deploy-nightlies) }}
         shell: bash
         env:
           NIGHTLIES_RSYNC_HOST: ${{ secrets.NIGHTLIES_RSYNC_HOST }}
diff --git a/.github/workflows/release_ruby.yml b/.github/workflows/release_ruby.yml
index a88ce0d461..2e9134d4ad 100644
--- a/.github/workflows/release_ruby.yml
+++ b/.github/workflows/release_ruby.yml
@@ -34,7 +34,8 @@ on:
   # a release process. For now, we can rely on artifacts for testing pre-releases.
   # In the future, we could consider a GitHub private registry for pre-releases.
   #
-  # omits `workflow_dispatch` to tighten this release workflow.
+  # Manual dispatch supports candidate builds only; publishing still requires a tag push.
+  workflow_dispatch:
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
@@ -196,7 +197,7 @@ jobs:
   publish:
     # RC tags only build artifacts for release verification. RubyGems does not
     # provide a staging registry, so publish only from the final release tag.
-    if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')
+    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')
 
     needs: [build, smoke-test, build-native]
     runs-on: ubuntu-latest
diff --git a/.github/workflows/weekly_release.yml b/.github/workflows/weekly_release.yml
index d5fdeb266a..47a87eacec 100644
--- a/.github/workflows/weekly_release.yml
+++ b/.github/workflows/weekly_release.yml
@@ -118,3 +118,83 @@ jobs:
       rc: ${{ needs.prepare.outputs.rc }}
     secrets:
       GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }}
+
+  builds:
+    needs: prepare
+    runs-on: ubuntu-latest
+    permissions:
+      actions: write
+      contents: read
+    steps:
+      - name: Dispatch existing RC workflows
+        env:
+          GH_TOKEN: ${{ github.token }}
+          RC: ${{ needs.prepare.outputs.rc }}
+          SHA: ${{ needs.prepare.outputs.sha }}
+        run: |
+          # GITHUB_TOKEN pushes do not trigger the existing tag workflows.
+          for workflow in ci_bindings_{c,cpp,d,dart,dotnet,go,haskell,java,lua,nodejs,ocaml,php,ruby,swift,zig}.yml release_{dart,dotnet,java,nodejs,python,ruby,rust}.yml docs.yml; do
+            # Reuse runs already accepted before a partial dispatch failure.
+            count=$(gh run list --repo apache/opendal --workflow "$workflow" --commit "$SHA" --event workflow_dispatch --limit 1 --json databaseId --jq length)
+            if [ "$count" -gt 0 ]; then continue; fi
+            args=()
+            case "$workflow" in
+              release_nodejs.yml) args=(-f nodejs-publish=false -f nodejs-publish-dry-run=false) ;;
+              release_dotnet.yml) args=(-f release_type=none) ;;
+              docs.yml) args=(-f release_version="v$RC" -f deploy-nightlies=false) ;;
+            esac
+            gh workflow run "$workflow" --repo apache/opendal --ref "v$RC" "${args[@]}"
+          done
+
+  notify:
+    needs: [prepare, compose, builds]
+    runs-on: ubuntu-latest
+    permissions:
+      discussions: write
+      contents: read
+    steps:
+      - name: Announce staged candidate for RM verification
+        env:
+          GH_TOKEN: ${{ github.token }}
+          RC: ${{ needs.prepare.outputs.rc }}
+          SHA: ${{ needs.prepare.outputs.sha }}
+        run: |
+          title="Source candidate ready: $RC"
+          # GraphQL variables must reach the API without shell expansion.
+          # shellcheck disable=SC2016
+          gh api graphql --paginate --slurp -f query='
+            query($endCursor: String) {
+              repository(owner: "apache", name: "opendal") {
+                id
+                discussionCategories(first: 100) { nodes { id name } }
+                discussions(first: 100, after: $endCursor) {
+                  nodes { title url }
+                  pageInfo { hasNextPage endCursor }
+                }
+              }
+            }' > "$RUNNER_TEMP/discussions.json"
+          existing=$(jq -r --arg title "$title" '[.[].data.repository.discussions.nodes[] | select(.title == $title) | .url][0] // empty' "$RUNNER_TEMP/discussions.json")
+          if [ -n "$existing" ]; then
+            echo "$existing" >> "$GITHUB_STEP_SUMMARY"
+            exit 0
+          fi
+          repository=$(jq -er '.[0].data.repository.id' "$RUNNER_TEMP/discussions.json")
+          category=$(jq -er '.[0].data.repository.discussionCategories.nodes[] | select(.name == "General") | .id' "$RUNNER_TEMP/discussions.json")
+          cat > "$RUNNER_TEMP/candidate-notice.md" <<EOF
+          Source candidate **$RC** has been built, signed and uploaded to ATR.
+
+          - [ATR candidate](https://releases.apache.org/compose/opendal/$RC)
+          - [RC tag](https://github.com/apache/opendal/releases/tag/v$RC), commit: \`$SHA\`
+          - [Source build and signed artifacts](https://github.com/apache/opendal/actions/runs/$GITHUB_RUN_ID)
+          - [RC builds and binding checks](https://github.com/apache/opendal/actions?query=branch%3Av$RC)
+
+          RC build workflows have been dispatched; this notice does not mean they have passed.
+          Release manager: check their results and staging outputs, inspect ATR checks, and independently verify the candidate before starting the formal vote. This Discussion is a preparation notice, not a vote.
+          EOF
+          # shellcheck disable=SC2016
+          gh api graphql -f query='
+            mutation($repository: ID!, $category: ID!, $title: String!, $body: String!) {
+              createDiscussion(input: {repositoryId: $repository, categoryId: $category, title: $title, body: $body}) {
+                discussion { url }
+              }
+            }' -f repository="$repository" -f category="$category" -f title="$title" -F body=@"$RUNNER_TEMP/candidate-notice.md" --jq '.data.createDiscussion.discussion.url' >> "$GITHUB_STEP_SUMMARY"
diff --git a/website/community/release/weekly.md b/website/community/release/weekly.md
index d605b961ec..2f10b22cf4 100644
--- a/website/community/release/weekly.md
+++ b/website/community/release/weekly.md
@@ -47,10 +47,24 @@ retains its caller's identity. The actor initiating a manual run or owning the
 schedule must have the required ASF-linked project permissions. An RM should
 maintain the cron expression, which determines the scheduled actor.
 
-The workflow ends at ATR compose. It does not start votes, announce releases,
-create final tags, synchronize main or publish language packages. These remain
-steps in the existing release procedure. Keep the candidate branch and signed
-artifacts until that procedure is complete.
+After pushing the RC tag, the workflow explicitly dispatches the existing tag
+builds, binding checks and documentation workflow against that tag. GitHub does
+not trigger downstream push workflows for tags created with `GITHUB_TOKEN`.
+These dispatches retain the RC behavior: Java stages to Nexus, Python uses
+TestPyPI, NodeJS performs a publish dry run, Ruby and .NET retain artifacts, and
+Rust does not publish. Documentation retains RC staging without deploying to
+nightlies. A retry skips workflows already dispatched for the candidate commit;
+rerun failed downstream jobs from their own runs.
+
+After ATR upload and dispatch succeed, the workflow posts a candidate preparation
+notice in GitHub Discussions with the ATR, tag, source artifact and build links.
+It reuses an existing notice for the same RC when retried. This notice does not
+assert that downstream builds or ATR checks passed. The RM verifies those results
+and the candidate before starting the formal vote.
+
+The workflow does not start votes, announce final releases, create final tags or
+synchronize main. These remain steps in the existing release procedure. Keep the
+candidate branch and signed artifacts until that procedure is complete.
 
 Installing this workflow on main activates the schedule. The initiating actor and
 reusable workflow's ATR OIDC identity still require a live rehearsal; local checks