Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
98 changes: 95 additions & 3 deletions .github/workflows/todos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,98 @@ permissions:

jobs:
todos:
uses: devantler-tech/actions/.github/workflows/scan-for-todo-comments.yaml@0de1d284f879d62d6fe316d3997fd3ea8f092fb3 # v13.2.1
secrets:
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
runs-on: ubuntu-latest
steps:
- name: 🛡️ Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: 📑 Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# The shared workflow does not expose the scanner's ignore input. Keep
# its retry helper pinned here while the KSail-owned job applies the
# repository-specific third-party filter below.
- name: 📥 Checkout devantler-tech/actions
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: devantler-tech/actions
ref: 0de1d284f879d62d6fe316d3997fd3ea8f092fb3 # v13.2.1
path: .devantler-tech-actions
persist-credentials: false

- name: 🔑 Generate GitHub App token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: app-token
with:
client-id: ${{ vars.APP_CLIENT_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
permission-organization-projects: write

- name: 🧰 Preserve retry helper
shell: bash
run: |
retry_helper="${RUNNER_TEMP}/devantler-actions-retry.sh"
cp "${GITHUB_WORKSPACE}/.devantler-tech-actions/.scripts/retry.sh" "$retry_helper"
chmod +x "$retry_helper"

# Re-sync after copying the helper so the scanner cannot inspect the
# checked-out actions repository as part of KSail's own sources.
- name: 📑 Re-sync KSail sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: 📝 Create issues from TODOs
shell: bash
env:
INPUT_REPO: ${{ github.repository }}
INPUT_BEFORE: ${{ github.event.before || github.base_ref }}
INPUT_COMMITS: ${{ toJSON(github.event.commits) }}
INPUT_DIFF_URL: ${{ github.event.pull_request.diff_url }}
INPUT_SHA: ${{ github.sha }}
INPUT_TOKEN: ${{ github.token }}
INPUT_CLOSE_ISSUES: "true"
INPUT_AUTO_P: "true"
INPUT_PROJECT: organization/devantler-tech/5
INPUT_PROJECTS_SECRET: ${{ steps.app-token.outputs.token }}
INPUT_AUTO_ASSIGN: "true"
INPUT_ACTOR: ${{ github.actor }}
INPUT_GITHUB_URL: ${{ github.api_url }}
INPUT_GITHUB_SERVER_URL: ${{ github.server_url }}
INPUT_ESCAPE: "true"
INPUT_NO_STANDARD: "false"
INPUT_INSERT_ISSUE_URLS: "false"
INPUT_IGNORE: "^third_party/"
TODO_TO_ISSUE_IMAGE: ghcr.io/alstr/todo-to-issue-action:v5.1.15@sha256:a1794cab7e7a0306d6f74dd5249734f2c0b49e47d7549c6cdca4421bced67c9d
run: |
retry() { bash "${RUNNER_TEMP}/devantler-actions-retry.sh" "$@"; }

retry docker run --rm \
--workdir /github/workspace \
--volume "$GITHUB_WORKSPACE:/github/workspace" \
--env GITHUB_ACTIONS=true \
--env GITHUB_WORKSPACE=/github/workspace \
--env CI=true \
--env INPUT_REPO \
--env INPUT_BEFORE \
--env INPUT_COMMITS \
--env INPUT_DIFF_URL \
--env INPUT_SHA \
--env INPUT_TOKEN \
--env INPUT_CLOSE_ISSUES \
--env INPUT_AUTO_P \
--env INPUT_PROJECT \
--env INPUT_PROJECTS_SECRET \
--env INPUT_AUTO_ASSIGN \
--env INPUT_ACTOR \
--env INPUT_GITHUB_URL \
--env INPUT_GITHUB_SERVER_URL \
--env INPUT_ESCAPE \
--env INPUT_NO_STANDARD \
--env INPUT_INSERT_ISSUE_URLS \
--env INPUT_IGNORE \
"$TODO_TO_ISSUE_IMAGE"
71 changes: 71 additions & 0 deletions internal/ciharness/todos_workflow_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package ciharness_test

import (
"regexp"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)

// todosWorkflow captures the local job surface that delivers scanner inputs.
//
//nolint:tagliatelle // GitHub Actions defines these external keys in kebab-case.
type todosWorkflow struct {
Jobs map[string]struct {
Uses string `yaml:"uses"`
RunsOn string `yaml:"runs-on"`
Steps []struct {
Env map[string]string `yaml:"env"`
Run string `yaml:"run"`
} `yaml:"steps"`
} `yaml:"jobs"`
}

func TestTODOScannerExcludesOnlyVendoredSources(t *testing.T) {
t.Parallel()

contents := readRepoFile(t, ".github/workflows/todos.yaml")

var workflow todosWorkflow
require.NoError(t, yaml.Unmarshal(contents, &workflow))

job, found := workflow.Jobs["todos"]
require.True(t, found, "TODO workflow must define the todos job")
require.Empty(t, job.Uses, "TODO scanner inputs must be delivered by the KSail-owned job")
require.Equal(t, "ubuntu-latest", job.RunsOn)

var (
scanEnv map[string]string
scanRun string
)

for _, step := range job.Steps {
if _, configured := step.Env["INPUT_IGNORE"]; configured {
scanEnv = step.Env
scanRun = step.Run

break
}
}

require.NotNil(t, scanEnv, "scanner step must configure INPUT_IGNORE")

ignorePattern := scanEnv["INPUT_IGNORE"]
assert.Equal(t, `^third_party/`, ignorePattern)

compiled, err := regexp.Compile(ignorePattern)
require.NoError(t, err)
assert.True(t, compiled.MatchString("third_party/go-archive/archive/tar/reader.go"))
assert.False(t, compiled.MatchString("internal/maintenance/todos.go"))

assert.Contains(t, strings.Join(strings.Fields(scanRun), " "), "--env INPUT_IGNORE")
assert.Equal(
t,
"ghcr.io/alstr/todo-to-issue-action:v5.1.15@sha256:"+
"a1794cab7e7a0306d6f74dd5249734f2c0b49e47d7549c6cdca4421bced67c9d",
scanEnv["TODO_TO_ISSUE_IMAGE"],
)
}
Loading