Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
75b194c
fix: handle single test reports and downgrade AppInspect CLI (#537)
mkolasinski-splunk Aug 28, 2026
814ae90
feat: prepare pinned TA Validator exception comment
mkolasinski-splunk Sep 21, 2026
277e223
fix: clear stale TA Validator exception input
mkolasinski-splunk Sep 21, 2026
065943a
feat: fail fast on TA Validator PR exceptions
mkolasinski-splunk Sep 21, 2026
2e488f1
fix: avoid caller issue permission escalation
mkolasinski-splunk Sep 21, 2026
00bfff6
fix: resolve pinned workflow checkout ref
mkolasinski-splunk Sep 21, 2026
e8b39c2
fix: pin TA Validator exception action
mkolasinski-splunk Sep 21, 2026
65b8a19
fix: authorize TA Validator PR comments
mkolasinski-splunk Sep 21, 2026
428415e
fix: stop pinning TA Validator comments
mkolasinski-splunk Sep 21, 2026
046e22a
fix: use unpinned TA Validator comments
mkolasinski-splunk Sep 21, 2026
824a474
fix: use amd64 TA Validator E2E image
mkolasinski-splunk Sep 21, 2026
cbd9251
refactor: use find-comment for TA Validator exceptions
mkolasinski-splunk Sep 21, 2026
cd78573
chore: pin simplified TA Validator comment action
mkolasinski-splunk Sep 21, 2026
8082fab
refactor: simplify TA Validator exception input writer
mkolasinski-splunk Sep 21, 2026
8333e2e
chore: pin simplified exception input writer
mkolasinski-splunk Sep 21, 2026
b43d370
feat: add shared TA Validator runner action
mkolasinski-splunk Sep 21, 2026
cb77d6a
fix: pass PR exception input to TA Validator evaluation
mkolasinski-splunk Sep 21, 2026
ae888d6
refactor: share TA Validator image runner
mkolasinski-splunk Sep 21, 2026
7a46c76
refactor: centralize TA Validator runner setup
mkolasinski-splunk Sep 21, 2026
b7ce3ff
chore: pin centralized TA Validator runner
mkolasinski-splunk Sep 21, 2026
76b27fc
refactor: unify TA Validator evaluation
mkolasinski-splunk Sep 21, 2026
25681dd
fix: restrict TA Validator exception comment source
mkolasinski-splunk Sep 21, 2026
9b2c1bc
chore: pin authenticated exception action
mkolasinski-splunk Sep 21, 2026
2847422
refactor: extract canonical PR exception YAML
mkolasinski-splunk Sep 21, 2026
197dcfb
fix: preserve PR exception YAML newlines
mkolasinski-splunk Sep 21, 2026
e226d17
feat: accept canonical PR exception input
mkolasinski-splunk Sep 21, 2026
93cf91d
feat: pass canonical PR exception input to TA Validator
mkolasinski-splunk Sep 21, 2026
6a0290a
docs: describe canonical PR exception input
mkolasinski-splunk Sep 21, 2026
720cd73
fix: harden TA Validator exception workflow
mkolasinski-splunk Sep 22, 2026
cf4924a
refactor: build one effective TA Validator exception file
mkolasinski-splunk Sep 23, 2026
45787b2
refactor: evaluate one effective TA Validator exception file
mkolasinski-splunk Sep 23, 2026
85125ab
test: add license header to TA Validator workflow tests
mkolasinski-splunk Sep 23, 2026
f9d1bba
refactor: use fixed TA Validator exception paths
mkolasinski-splunk Sep 23, 2026
7b36368
build: pin simplified TA Validator action
mkolasinski-splunk Sep 23, 2026
5fc1283
ci: pin TA Validator exception dependencies
mkolasinski-splunk Sep 23, 2026
77beb8f
ci: pin reusable workflow actions to review fix
mkolasinski-splunk Sep 23, 2026
21887bc
ci: use version tags for third-party actions
mkolasinski-splunk Sep 24, 2026
1f6fe7d
ci: refresh TA Validator action references
mkolasinski-splunk Sep 24, 2026
9e9dc78
fix: use version tag for find-comment action
mkolasinski-splunk Sep 24, 2026
44b3866
chore: refresh TA Validator action references
mkolasinski-splunk Sep 24, 2026
af477f9
refactor: use justification in TA Validator exceptions
mkolasinski-splunk Sep 29, 2026
63de0b9
chore: refresh TA Validator action references
mkolasinski-splunk Sep 29, 2026
f9cdd07
test: keep exception template focused on justification
mkolasinski-splunk Sep 29, 2026
500ca6d
fix: harden TA Validator exception preparation
mkolasinski-splunk Sep 29, 2026
b545916
chore: refresh TA Validator action references
mkolasinski-splunk Sep 29, 2026
11cd0be
fix: use released TA Validator image
mkolasinski-splunk Oct 1, 2026
72250c5
chore: use released version references
mkolasinski-splunk Oct 1, 2026
b33f0cd
docs: align TA Validator version references
mkolasinski-splunk Oct 1, 2026
8eca8f0
Merge branch 'develop' into codex/pr-scoped-gssa-xfail-workflow
mkolasinski-splunk Oct 1, 2026
c113388
fix: pin TA Validator action dependencies
mkolasinski-splunk Oct 1, 2026
f47fcb2
fix: pin delete-artifact action
mkolasinski-splunk Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/actions/prepare-ta-validator-exceptions/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Prepare TA Validator exceptions
description: Find or create the TA Validator exception comment and transport it
inputs:
token:
required: true
repository:
required: true
pull_request_number:
required: true
comment_author:
required: true
output_path:
required: true
runs:
using: composite
steps:
- name: Find TA Validator exception comment
id: find-comment
uses: peter-evans/find-comment@v4.0.0
with:
token: ${{ inputs.token }}
repository: ${{ inputs.repository }}
issue-number: ${{ inputs.pull_request_number }}
comment-author: ${{ inputs.comment_author }}
body-includes: "<!-- ta-validator-exceptions:v1 -->"
- name: Write TA Validator exception document
shell: sh
env:
INPUT_REPOSITORY: ${{ inputs.repository }}
INPUT_PULL_REQUEST_NUMBER: ${{ inputs.pull_request_number }}
INPUT_OUTPUT_PATH: ${{ inputs.output_path }}
INPUT_TOKEN: ${{ inputs.token }}
INPUT_COMMENT_BODY: ${{ steps.find-comment.outputs.comment-body }}
run: python3 "$GITHUB_ACTION_PATH/prepare.py"
157 changes: 157 additions & 0 deletions .github/actions/prepare-ta-validator-exceptions/prepare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
"""Extract the canonical TA Validator exception document from a PR comment."""

import json
import os
import re
import sys
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen


MARKER = "<!-- ta-validator-exceptions:v1 -->"
CONFIG_START_MARKER = "<!-- ta-validator-exceptions-config:start -->"
CONFIG_END_MARKER = "<!-- ta-validator-exceptions-config:end -->"
ACTIVE_YAML_FENCE = re.compile(
r"\A(?:[ \t]*\r?\n)*[ \t]*```yaml[ \t]*\r?\n"
r"(?P<document>.*?\r?\n)[ \t]*```[ \t]*(?:\r?\n[ \t]*)*\Z",
re.DOTALL,
)
FENCE_DELIMITER = re.compile(r"(?m)^[ \t]*```(?!`)")
COMMENT_TEMPLATE = """<!-- ta-validator-exceptions:v1 -->

## Temporary TA Validator exceptions

Edit the YAML below, then rerun all jobs.

<!-- ta-validator-exceptions-config:start -->
```yaml
version: 1
exceptions: []
# Add declarations like:
# - check_slug: sensitive-data
# category: false_positive
# justification: Explain why this exception applies.
```
<!-- ta-validator-exceptions-config:end -->

<details>
<summary>Example</summary>

```yaml
version: 1
exceptions:
- check_slug: sensitive-data
detection_slug: credential-exposure
category: false_positive
justification: Accepted for this PR; tracked in ADDON-12345.
```
</details>
"""


def extract_pull_request_exception_document(comment_body):
"""Return the sole YAML document framed by the active configuration markers."""
marker_positions = {
"comment": (MARKER, comment_body.count(MARKER)),
"configuration start": (CONFIG_START_MARKER, comment_body.count(CONFIG_START_MARKER)),
"configuration end": (CONFIG_END_MARKER, comment_body.count(CONFIG_END_MARKER)),
}
for marker_name, (marker, count) in marker_positions.items():
if count != 1:
raise ValueError(f"Expected exactly one {marker_name} marker")

comment_index = comment_body.index(MARKER)
start_index = comment_body.index(CONFIG_START_MARKER)
end_index = comment_body.index(CONFIG_END_MARKER)
if not comment_index < start_index < end_index:
raise ValueError("TA Validator exception markers are misordered")

active_configuration = comment_body[
start_index + len(CONFIG_START_MARKER) : end_index
]
if len(FENCE_DELIMITER.findall(active_configuration)) != 2:
raise ValueError("Expected exactly one fenced YAML document in the active configuration")
match = ACTIVE_YAML_FENCE.fullmatch(active_configuration)
if not match:
raise ValueError("Expected exactly one fenced YAML document in the active configuration")
return match.group("document")


def write_pull_request_exception_document(output_path, comment_body):
"""Write only the active canonical YAML document from a selected comment."""
path = Path(output_path)
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8", newline="") as output_file:
output_file.write(extract_pull_request_exception_document(comment_body))


def _required_input(name):
value = os.environ.get(f"INPUT_{name}")
if not value:
raise ValueError(f"Missing required input {name.lower()}")
return value


def _workflow_message(level, message):
escaped = str(message).replace("%", "%25").replace("\r", "%0D").replace("\n", "%0A")
print(f"::{level}::{escaped}")


def _positive_integer(value, name):
try:
integer = int(value)
except ValueError as exc:
raise ValueError(f"{name} must be a positive integer") from exc
if integer <= 0:
raise ValueError(f"{name} must be a positive integer")
return integer


def create_pull_request_exception_comment(token, repository, pull_request_number):
"""Create the canonical comment using GitHub's REST API."""
owner, separator, name = repository.partition("/")
if not separator or not owner or not name:
raise ValueError("repository must be in owner/name form")

request = Request(
f"https://api.github.com/repos/{owner}/{name}/issues/{pull_request_number}/comments",
data=json.dumps({"body": COMMENT_TEMPLATE}).encode(),
headers={
"Accept": "application/vnd.github+json",
"Authorization": f"Bearer {token}",
"X-GitHub-Api-Version": "2022-11-28",
},
method="POST",
)
try:
with urlopen(request): # nosec B310 - fixed GitHub API URL
pass
except HTTPError as exc:
raise ValueError(f"Could not create TA Validator exception comment: HTTP {exc.code}") from exc
except URLError as exc:
raise ValueError(f"Could not create TA Validator exception comment: {exc.reason}") from exc

return COMMENT_TEMPLATE


def main():
output_path = _required_input("OUTPUT_PATH")
found_comment_body = os.environ.get("INPUT_COMMENT_BODY")
if found_comment_body:
comment_body = found_comment_body
else:
comment_body = create_pull_request_exception_comment(
_required_input("TOKEN"),
_required_input("REPOSITORY"),
_positive_integer(_required_input("PULL_REQUEST_NUMBER"), "pull_request_number"),
)
write_pull_request_exception_document(output_path, comment_body)


if __name__ == "__main__":
try:
main()
except (OSError, ValueError) as exc:
_workflow_message("error", exc)
raise SystemExit(str(exc)) from exc
94 changes: 94 additions & 0 deletions .github/actions/run-ta-validator/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Run TA Validator
description: Merge TA Validator exceptions or evaluate an add-on in the published image
inputs:
image:
description: Full TA Validator image reference
required: true
mode:
description: Either merge exception documents or evaluate the add-on
required: true
aws-access-key-id:
description: AWS access key used to pull the TA Validator image
required: true
aws-secret-access-key:
description: AWS secret key used to pull the TA Validator image
required: true
aws-region:
description: AWS region containing the TA Validator image
required: true
runs:
using: composite
steps:
- name: Checkout add-on
uses: actions/checkout@v7.0.1
with:
persist-credentials: false
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v6.3.0
with:
aws-access-key-id: ${{ inputs.aws-access-key-id }}
aws-secret-access-key: ${{ inputs.aws-secret-access-key }}
aws-region: ${{ inputs.aws-region }}
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2.1.7
- name: Run TA Validator image
shell: bash
env:
INPUT_IMAGE: ${{ inputs.image }}
INPUT_MODE: ${{ inputs.mode }}
run: |-
set -euo pipefail

image="$INPUT_IMAGE"
mode="$INPUT_MODE"
comment_exceptions_path="$RUNNER_TEMP/ta-validator-comment-exceptions.yaml"
effective_exceptions_path="$RUNNER_TEMP/.ta-validator-exceptions.yaml"
workspace_exceptions_path="$GITHUB_WORKSPACE/.ta-validator-exceptions.yaml"
docker_options=(--rm)

case "$mode" in
merge)
if [ ! -f "$comment_exceptions_path" ] || [ -L "$comment_exceptions_path" ]; then
echo "merge mode requires $comment_exceptions_path to be a regular file" >&2
exit 1
fi

docker_options+=(
--user "$(id -u):$(id -g)"
-v "$GITHUB_WORKSPACE:/addon:ro"
-v "$comment_exceptions_path:/run/additional.yaml:ro"
-v "$RUNNER_TEMP:/output"
)
command=(merge --repository /addon --additional-file /run/additional.yaml --output /output/.ta-validator-exceptions.yaml)
;;
evaluate)
if [ -L "$effective_exceptions_path" ]; then
echo "$effective_exceptions_path must not be a symbolic link" >&2
exit 1
fi
if [ -f "$effective_exceptions_path" ]; then
if [ -L "$workspace_exceptions_path" ]; then
echo "$workspace_exceptions_path must not be a symbolic link" >&2
exit 1
fi
cp "$effective_exceptions_path" "$workspace_exceptions_path"
fi

docker_options+=(
-v "$GITHUB_WORKSPACE:/addon"
-e GITHUB_TOKEN
-e GITHUB_USERNAME
-e AWS_ACCESS_KEY_ID
-e AWS_SECRET_ACCESS_KEY
-e AWS_DEFAULT_REGION
-e APPINSPECT_USER
-e APPINSPECT_PASS
-e GS_VERSION
)
command=()
;;
*) echo "mode must be merge or evaluate" >&2; exit 1 ;;
esac

docker pull "$image"
docker run "${docker_options[@]}" "$image" "${command[@]}"
Loading
Loading