[VOL-5495] Add full GHA suite

Combines verify, release, and dependabot workflows.

Signed-off-by: Eric Ball <eball@linuxfoundation.org>
Change-Id: I5a85b7feead8a66fbc1ec3d83cdba717413eb920
diff --git a/.github/workflows/call-github2gerrit.yaml b/.github/workflows/call-github2gerrit.yaml
new file mode 100644
index 0000000..e2c7b6e
--- /dev/null
+++ b/.github/workflows/call-github2gerrit.yaml
@@ -0,0 +1,37 @@
+---
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2026 The Linux Foundation
+
+name: call-github2gerrit
+
+# yamllint disable-line rule:truthy
+on:
+  workflow_dispatch:
+  pull_request_target:
+    types: [opened, reopened, edited, synchronize]
+    branches:
+      - master
+      - main
+
+permissions:
+  contents: read
+  pull-requests: write
+  issues: write
+
+concurrency:
+  # yamllint disable-line rule:line-length
+  group: ${{ github.workflow }}-${{ github.run_id }}
+  cancel-in-progress: true
+
+jobs:
+  submit-to-gerrit:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Submit PR to Gerrit
+        id: g2g
+        uses: lfreleng-actions/github2gerrit-action@main
+        with:
+          GERRIT_KNOWN_HOSTS: ${{ vars.GERRIT_KNOWN_HOSTS }}
+          GERRIT_SSH_PRIVKEY_G2G: ${{ secrets.GERRIT_SSH_PRIVKEY_G2G }}
+          GERRIT_SSH_USER_G2G: ${{ vars.GERRIT_SSH_USER_G2G }}
+          GERRIT_SSH_USER_G2G_EMAIL: ${{ vars.GERRIT_SSH_USER_G2G_EMAIL }}
diff --git a/.github/workflows/gerrit-comment-handler.yaml b/.github/workflows/gerrit-comment-handler.yaml
new file mode 100644
index 0000000..e6fbbda
--- /dev/null
+++ b/.github/workflows/gerrit-comment-handler.yaml
@@ -0,0 +1,126 @@
+---
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: 2026 The Linux Foundation
+name: Gerrit Comment Handler
+
+# yamllint disable-line rule:truthy
+on:
+  workflow_dispatch:
+    inputs:
+      GERRIT_BRANCH:
+        description: "Branch that change is against"
+        required: true
+        type: string
+      GERRIT_CHANGE_ID:
+        description: "The ID for the change"
+        required: true
+        type: string
+      GERRIT_CHANGE_NUMBER:
+        description: "The Gerrit number"
+        required: true
+        type: string
+      GERRIT_CHANGE_URL:
+        description: "URL to the change"
+        required: true
+        type: string
+      GERRIT_EVENT_TYPE:
+        description: "Gerrit event type"
+        required: true
+        type: string
+      GERRIT_PATCHSET_NUMBER:
+        description: "The patch number for the change"
+        required: true
+        type: string
+      GERRIT_PATCHSET_REVISION:
+        description: "The revision sha"
+        required: true
+        type: string
+      GERRIT_PROJECT:
+        description: "Project in Gerrit"
+        required: true
+        type: string
+      GERRIT_REFSPEC:
+        description: "Gerrit refspec of change"
+        required: true
+        type: string
+      GERRIT_COMMENT:
+        description: "The full gha-run command line from the Gerrit comment"
+        required: true
+        type: string
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.inputs.GERRIT_CHANGE_ID || github.run_id }}
+  cancel-in-progress: true
+
+jobs:
+  # ==========================================================================
+  # JOB 1: parse-command
+  # ==========================================================================
+  # Parse GERRIT_COMMENT into a job name and parameters.
+  # ==========================================================================
+  parse-command:
+    runs-on: ubuntu-latest
+    outputs:
+      job-name: ${{ steps.parse.outputs.job-name }}
+      params: ${{ steps.parse.outputs.params }}
+    steps:
+      - name: Parse gha-run command
+        id: parse
+        env:
+          GERRIT_COMMENT: ${{ inputs.GERRIT_COMMENT }}
+        run: |
+          # Strip the leading "gha-run" verb.
+          command="${GERRIT_COMMENT#gha-run }"
+          # The first remaining token is the job name.
+          job_name="${command%% *}"
+          # Everything after the job name is the parameter string.
+          params="${command#"${job_name}"}"
+          params="${params# }"
+          echo "job-name=${job_name}" >> "${GITHUB_OUTPUT}"
+          echo "params=${params}" >> "${GITHUB_OUTPUT}"
+          echo "Parsed job name: ${job_name}"
+          echo "Parsed parameters: ${params}"
+
+  # ==========================================================================
+  # JOB 2: run-job (Route and Execute)
+  # ==========================================================================
+  # Use the parsed job name to decide what to do. A case statement keeps the
+  # routing explicit and rejects unknown job names.
+  # ==========================================================================
+  run-job:
+    needs: parse-command
+    if: ${{ needs.parse-command.outputs.job-name == 'sanity-test' }}
+    uses: opencord/shared-workflows/.github/workflows/sanity-test.yaml@main
+    secrets: inherit
+    with:
+      GERRIT_URL: ${{ inputs.GERRIT_URL }}
+      GERRIT_REFSPEC: ${{ inputs.GERRIT_REFSPEC }}
+      GERRIT_PROJECT: ${{ inputs.GERRIT_PROJECT }}
+      EXTRA_HELM_FLAGS: "--set global.image_tag=master --set onos-classic.image.tag=master"
+
+  # ==========================================================================
+  # JOB 3: report-status (Comment-Only Result Notification)
+  # ==========================================================================
+  # Report the outcome back to the Gerrit change as a comment. Use comment-only
+  # mode so the handler never casts a Verified vote on demand.
+  # ==========================================================================
+  report-status:
+    if: ${{ always() }}
+    needs: [parse-command, run-job]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Get workflow conclusion
+        # yamllint disable-line rule:line-length
+        uses: im-open/workflow-conclusion@fce18569e28a9f2ed1feca1e6d4251e6a7365fdc # v2.2.4
+      - name: Report workflow conclusion
+        # yamllint disable-line rule:line-length
+        uses: lfreleng-actions/gerrit-review-action@c9df844dc6efe28b85b297c1c6d40390bfa4a378 # v1.0.0
+        with:
+          host: ${{ vars.GERRIT_SERVER }}
+          username: ${{ vars.GERRIT_SSH_USER }}
+          key: ${{ secrets.GERRIT_SSH_PRIVKEY }}
+          known_hosts: ${{ vars.GERRIT_KNOWN_HOSTS }}
+          gerrit-change-number: ${{ inputs.GERRIT_CHANGE_NUMBER }}
+          gerrit-patchset-number: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
+          vote-type: ${{ env.WORKFLOW_CONCLUSION }}
+          comment-only: "true"
diff --git a/.github/workflows/gerrit-verify.yaml b/.github/workflows/gerrit-verify.yaml
new file mode 100644
index 0000000..d2ef906
--- /dev/null
+++ b/.github/workflows/gerrit-verify.yaml
@@ -0,0 +1,67 @@
+---
+name: Call Verify Workflow(s)
+
+# yamllint disable-line rule:truthy
+on:
+  workflow_dispatch:
+    inputs:
+      GERRIT_BRANCH:
+        description: "Branch that change is against"
+        required: true
+        type: string
+      GERRIT_CHANGE_ID:
+        description: "The ID for the change"
+        required: true
+        type: string
+      GERRIT_CHANGE_NUMBER:
+        description: "The Gerrit number"
+        required: true
+        type: string
+      GERRIT_CHANGE_URL:
+        description: "URL to the change"
+        required: true
+        type: string
+      GERRIT_EVENT_TYPE:
+        description: "Type of Gerrit event"
+        required: true
+        type: string
+      GERRIT_PATCHSET_NUMBER:
+        description: "The patch number for the change"
+        required: true
+        type: string
+      GERRIT_PATCHSET_REVISION:
+        description: "The revision sha"
+        required: true
+        type: string
+      GERRIT_PROJECT:
+        description: "Project in Gerrit"
+        required: true
+        type: string
+      GERRIT_REFSPEC:
+        description: "Gerrit refspec of change"
+        required: true
+        type: string
+
+concurrency:
+  # yamllint disable-line rule:line-length
+  group: ${{ github.repository }}-${{ github.workflow }}-${{ github.event.inputs.GERRIT_CHANGE_ID || github.run_id }}
+  cancel-in-progress: true
+
+permissions: read-all
+
+jobs:
+  call-composed-verify:
+    # yamllint disable-line rule:line-length
+    uses: opencord/shared-workflows/.github/workflows/verify-unit-tests.yaml@main
+    with:
+      GERRIT_BRANCH: ${{ inputs.GERRIT_BRANCH }}
+      GERRIT_CHANGE_ID: ${{ inputs.GERRIT_CHANGE_ID }}
+      GERRIT_CHANGE_NUMBER: ${{ inputs.GERRIT_CHANGE_NUMBER }}
+      GERRIT_CHANGE_URL: ${{ inputs.GERRIT_CHANGE_URL }}
+      GERRIT_EVENT_TYPE: ${{ inputs.GERRIT_EVENT_TYPE }}
+      GERRIT_PATCHSET_NUMBER: ${{ inputs.GERRIT_PATCHSET_NUMBER }}
+      GERRIT_PATCHSET_REVISION: ${{ inputs.GERRIT_PATCHSET_REVISION }}
+      GERRIT_PROJECT: ${{ inputs.GERRIT_PROJECT }}
+      GERRIT_REFSPEC: ${{ inputs.GERRIT_REFSPEC }}
+    secrets:
+      GERRIT_SSH_PRIVKEY: ${{ secrets.GERRIT_SSH_PRIVKEY }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..8173e84
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,38 @@
+---
+# SPDX-License-Identifier: Apache-2.0
+# Copyright 2026 The Linux Foundation
+
+name: voltha-openolt-adapter release
+
+# yamllint disable-line rule:truthy
+on:
+  workflow_dispatch:
+  push:
+    # Only invoked on release tag pushes
+    tags:
+      - v*.*.*
+
+permissions:
+  contents: write
+
+jobs:
+  release:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        # yamllint disable-line rule:line-length
+        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+        with:
+          fetch-depth: 0
+
+      - name: Build and publish Docker image
+        # yamllint disable-line rule:line-length
+        uses: opencord/shared-workflows/.github/actions/docker-publish-action@main
+        with:
+          docker-registry: ""
+          docker-repository: "voltha/"
+          image-name: ${{ github.event.repository.name }}
+          branch-tag: ${{ github.ref_name }}
+          docker-username: ${{ secrets.DOCKER_USERNAME }}
+          docker-password: ${{ secrets.DOCKER_PASSWORD }}
+          extra-environment-vars: "BUILD_PROFILED=true BUILD_RACE=true"