Skip to content

[K9VULN-10939] Refactor from container action to composite action#55

Merged
jasonforal merged 2 commits intomainfrom
jf/K9VULN-10939
Jan 28, 2026
Merged

[K9VULN-10939] Refactor from container action to composite action#55
jasonforal merged 2 commits intomainfrom
jf/K9VULN-10939

Conversation

@jasonforal
Copy link
Contributor

@jasonforal jasonforal commented Jan 26, 2026

What this PR does

Refactors the action from a Docker container action to a composite action.

In practice, this reduces the lower bound of the cold start of the action from ~66 seconds to ~7 seconds.

All users of Github Actions will be able to upgrade without issue. However, this will be released as a new major version (v3) because self-hosted runners might require migrations if either of the following apply:

  • Runners operate in a restricted environment (e.g. allowlist-based firewall policies)
  • Runners are stripped-down (e.g. no curl, node, or bash, etc.)

Before (~66s)

#4 [1/2] FROM ghcr.io/datadog/datadog-static-analyzer:latest@sha256:208bc9d6cbab20fe96f166c1f3a7c5d86bf18c857a8996259c8c88d8d473601e
...
#4 DONE 14.8s

#5 [2/2] RUN npm install -g @datadog/datadog-ci@^3 && npm list -g @datadog/datadog-ci
...
#5 DONE 45.6s

#6 exporting to image
...
#6 DONE 6.0s

After (~7s)

Installed datadog-static-analyzer in 1.0s
Fetching datadog-ci 4.4.0 release
4.4.0
Installed datadog-ci in 6.3s

Rationale

#51 introduced a shim Dockerfile to ensure datadog-ci was always up-to-date. While this works, it's inefficient, as it requires a new Docker container to be built for each execution. For a standard GitHub runner, this introduces a minimum of 1 minute overhead.

Implementation Details

The bulk of the new code in this PR relates to fetching datadog-static-analyzer and datadog-ci in the most efficient manner possible. The actual configuration and param passing to the analyzer is a copy/paste of the old implementation found in datadog-static-analyzer/misc/github-action.sh, so there is no behavior change.

Installing datadog-static-analyzer

  • Inspect the runner's operating system and architecture
  • Use them to format a string for the correct binary (e.g. datadog-static-analyzer-aarch64-unknown-linux-gnu.zip) from the official GitHub releases. The version used will always be "latest".
  • Download directly and place in $PATH

Installing datadog-ci

This is where it gets more complex. The strategy here is:

Attempt a direct GitHub release download:

  • Resolve a list of published datadog-ci versions using npm list. npm returns matching versions as a list, e.g.:
[
  "4.0.0",
  "4.0.1",
  "4.0.2",
  "4.1.0",
  "4.1.1",
  "4.2.0",
  "4.3.0"
]
  • Choose the maximum satisfying version. Given that the npm cli uses the semver package, we can utilize it directly without an explicit install.
  • Inspect the runner's operating system and architecture
  • Use them to format a string for the correct file (e.g. datadog-ci_linux-arm64) from the official GitHub releases.
  • Download directly and place in $PATH.

If any of the above steps fail:

  • Fall back to npm install.
    • (This could happen if, for example, an NPM release has been made but the corresponding GitHub release hasn't been published yet)

Testing

  • CI tests have been added for all major platforms (Windows x86, MacOS arm64, Linux x86/arm64). This is strictly an improvement in coverage, as the previous action did not have tests.
    • Moving a non-trivial amount of logic into GitHub actions is...not ideal because it requires somewhat hacky workarounds to ensure all code paths are tested.

You'll want to confirm that this PR implements the exact logic from datadog-static-analyzer/misc/github-action.sh (paying attention to small details like shell quoting or lack thereof)

Notes

  • The architecture input has been deprecated. Turns out it never did anything anyway, so no need to have a formal deprecation window.
  • Using npx would've simplified the implementation by avoiding the npm view song and dance. However, when specifying a semver range (e.g. ^4), two separate calls could resolve to two separate versions. Ensuring a stable version introduces a comparable amount of complexity, and so it feels cleaner this way.
  • README.md is updated by Update docs #56

@jasonforal jasonforal marked this pull request as ready for review January 26, 2026 22:05
exit 1
fi

sed -i.bak "s/$test_hook/echo 'Simulating cURL error...'; exit 1/" action.yml
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we route to stderr for proper logging? echo 'Simulating cURL error...' >&2; exit 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only care about showing a message in GitHub actions UI for what's happening (it's conceptually a console.log rather than an error message). But regardless, not sure that's necessary as the UI doesn't distinguish stdout vs stderr
image

dd_api_key: ${{ secrets.DD_API_KEY }}
dd_app_key: ${{ secrets.DD_APP_KEY }}
dd_site: ${{ vars.DD_SITE }}
diff_aware: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to test the diff_aware:false case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in my opinion. The diff_aware:true strictly adds new behavior to the workflow:

- name: Upload git metadata to Datadog
if: ${{ inputs.diff_aware == 'true' }}
shell: bash
run: |
cd "$GITHUB_WORKSPACE"
git config --unset extensions.worktreeConfig || true
echo "Uploading git metadata to Datadog"
datadog-ci git-metadata upload
echo "Done"

So setting it to false will hit all the same code paths as when it's true

git config --global user.name "User"
git config --global user.email "user@example.com"
# (A dummy commit is added so a new commit hash is always uploaded to Datadog)
git commit -m "Commit" --allow-empty
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we make the commit message a little clearer in case anyone comes up on this without context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit is ephemeral and the message is never uploaded (so no one sees it), so I think the code comment above suffices.


if [ -n "$resolved_version" ] && (
echo "Fetching datadog-ci $resolved_version release"
TEST_HOOK_FORCE_NPM_INSTALL="" # (Test hook to simulate an error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is meant to force npm install during testing (as the comment suggests), it should be checking the variable's value, not setting it right? I'm a little confused about how setting it to an empty string forces the npm install

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent for here is to have a no-op statement that can be found/replaced with arbitrary logic (not sure if there's a better way to test more complex control flow in GHA like this...)

This could've also been

echo "Fetching datadog-ci $resolved_version release"
### <TEST_HOOK_FORCE_NPM_INSTALL_DO_NOT_DELETE_THIS> ###
filename="datadog-ci_$DDCI_OS-$DDCI_ARCH"

Or anything else that no-ops when left alone.

Happy to rename if you think it would be more clear

-f sarif \
--cpus "$CPU_COUNT" \
"$ENABLE_PERFORMANCE_STATISTICS" \
--debug $DEBUG_ARGUMENT_VALUE \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need to quote this like the other args?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically yes, but that's a bug that exists in the current implementation, so we need to preserve it 🥲 :

https://github.com/DataDog/datadog-static-analyzer/blob/e046bf73ad6f1285e3538d62caf02f8b3bda5232/misc/github-action.sh#L101

@jasonforal jasonforal merged commit 8340f18 into main Jan 28, 2026
9 checks passed
@jasonforal jasonforal deleted the jf/K9VULN-10939 branch January 28, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants