Add helm-lint, shellcheck, and tag-check actions

These are the remaining verification jobs on our main list, outside
of sanity tests.
Since none of these have any overlap in their implementation (that is,
no two jobs use the exact same combination of actions), no new shared
workflows are being added.

Signed-off-by: Eric Ball <eball@linuxfoundation.org>
Change-Id: I912f0d5a8c1baed84657bccfadbf9c7caecbcdc2
diff --git a/.github/actions/shellcheck-action/README.md b/.github/actions/shellcheck-action/README.md
new file mode 100644
index 0000000..fa5b0a8
--- /dev/null
+++ b/.github/actions/shellcheck-action/README.md
@@ -0,0 +1,75 @@
+<!--
+SPDX-License-Identifier: Apache-2.0
+SPDX-FileCopyrightText: 2026 The Linux Foundation
+-->
+
+# ShellCheck Action
+
+A GitHub Action that lints shell scripts using ShellCheck.
+
+## Description
+
+This composite action finds all shell scripts (`.sh` and `.bash` files) in the specified path and validates them using ShellCheck. It reports any issues and fails if linting errors are found.
+
+## Usage
+
+```yaml
+- name: Lint Shell Scripts
+  uses: ./.github/actions/shellcheck-action
+```
+
+### Inputs
+
+| Input | Description | Required | Default |
+|-------|-------------|----------|---------|
+| `path` | Path to search for shell scripts | No | `.` |
+| `severity` | Minimum severity level (error, warning, info, style) | No | `style` |
+| `exclude` | Comma-separated list of ShellCheck codes to exclude | No | `""` |
+
+### Example Workflow
+
+```yaml
+name: Shell Script Lint
+
+on:
+  pull_request:
+  push:
+    branches:
+      - main
+
+jobs:
+  shellcheck:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+
+      - name: Lint shell scripts
+        uses: ./.github/actions/shellcheck-action
+        with:
+          path: scripts
+          severity: warning
+          exclude: SC1090,SC2034
+```
+
+## How It Works
+
+The action performs the following steps:
+
+1. Installs ShellCheck if not already present
+2. Finds all `.sh` and `.bash` files in the specified path
+3. Runs ShellCheck on each file with the configured severity level
+4. Reports pass/fail status for each file
+5. Fails the action if any script has linting errors
+
+## Severity Levels
+
+- `error` - Only show errors
+- `warning` - Show errors and warnings
+- `info` - Show errors, warnings, and informational messages
+- `style` - Show all issues including style suggestions (default)
+
+## Requirements
+
+- Ubuntu runner (ShellCheck is installed via apt-get)
+- Repository checkout step should precede this action
diff --git a/.github/actions/shellcheck-action/action.yaml b/.github/actions/shellcheck-action/action.yaml
new file mode 100644
index 0000000..e3004c0
--- /dev/null
+++ b/.github/actions/shellcheck-action/action.yaml
@@ -0,0 +1,85 @@
+---
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: 2026 The Linux Foundation
+
+name: ShellCheck Lint
+description: "Lint shell scripts with ShellCheck"
+
+inputs:
+  path:
+    description: "Path to search for shell scripts"
+    required: false
+    default: "."
+  severity:
+    description: "Minimum severity level (error, warning, info, style)"
+    required: false
+    default: "style"
+  exclude:
+    description: "Comma-separated list of ShellCheck codes to exclude (e.g., SC1090,SC2034)"
+    required: false
+    default: ""
+
+runs:
+  using: "composite"
+  steps:
+    - name: Install ShellCheck
+      shell: bash
+      run: |
+        if ! command -v shellcheck &> /dev/null; then
+          echo "Installing ShellCheck..."
+          sudo apt-get update
+          sudo apt-get install -y shellcheck
+        fi
+        echo "ShellCheck version:"
+        shellcheck --version
+
+    - name: Run ShellCheck
+      shell: bash
+      run: |
+        set +e
+        fail_shellcheck=0
+        files_checked=0
+
+        echo "=> Linting shell scripts with ShellCheck"
+        echo "   Path: ${{ inputs.path }}"
+        echo "   Severity: ${{ inputs.severity }}"
+
+        # Build exclude argument if provided
+        exclude_arg=""
+        if [[ -n "${{ inputs.exclude }}" ]]; then
+          exclude_arg="--exclude=${{ inputs.exclude }}"
+          echo "   Excluding: ${{ inputs.exclude }}"
+        fi
+
+        # Find and check all shell scripts
+        while IFS= read -r -d '' script; do
+          echo ""
+          echo "==> CHECKING: ${script}"
+          files_checked=$((files_checked + 1))
+
+          if [[ -n "${exclude_arg}" ]]; then
+            shellcheck --severity="${{ inputs.severity }}" "${exclude_arg}" "${script}"
+          else
+            shellcheck --severity="${{ inputs.severity }}" "${script}"
+          fi
+
+          rc=$?
+          if [[ $rc -ne 0 ]]; then
+            echo "==> FAILED: ${script}"
+            fail_shellcheck=1
+          else
+            echo "==> PASSED: ${script}"
+          fi
+        done < <(find "${{ inputs.path }}" \( -name "*.sh" -o -name "*.bash" \) -type f -print0)
+
+        echo ""
+        echo "=> Summary: ${files_checked} file(s) checked"
+
+        if [[ ${files_checked} -eq 0 ]]; then
+          echo "=> No shell scripts found"
+        elif [[ ${fail_shellcheck} -eq 0 ]]; then
+          echo "=> All checks passed"
+        else
+          echo "=> Some checks failed"
+          exit 1
+        fi