Skip to content

Conversation

@marcogario
Copy link
Contributor

@marcogario marcogario commented Sep 7, 2020

When the action (or runner) analyzes only a single language, we download a smaller codeql bundle.

The main change here is that we now need to first detect the language and then setup codeQL. The language detection used to be a step of the initConfig step. We move this out and perform it before initCodeQL.

The changes to setupCodeQL are meant to correctly cache the tooling. I.e., if we already have a full bundle in the cache, we should not try to download a platform-language bundle. Similarly, if we did download a platforms-language bundle, then we should not cache it as a full bundle.

We extend this logic to only download the platform specific bundle, so that linux runners do not need to download a package with both windows and osx binaries.

I added this comment in the setupCodeQL to make the flow a bit more clear:

  // The URL identifies the release version. E.g., codeql-20200901 .
  // The plVersion identifies the platform-language combination of the package
  // within the release. E.g., `linux64-cpp` in `codeql-linux64-cpp.tar.gz`.
  // We expect the codeqlUrl (when given) to always point to the main bundle
  // `codeql-bundle.tar.gz`
  //
  // The logic is as follows:
  //  - Always use the Toolcache if available.
  //    - If we would like a platform-language package, but have the
  //      full bundle in the cache, use that.
  //  - If codeqlURL is specified, use that.
  //  - If a single language is being analyzed, try to download the platform-language package.
  //    - If it is not available in the release assets, fallback to the full bundle
  //  - If multiple languages are being anlyzed, use the full bundle

I will like to test/merge this code before merging the code to split the bundles, to ensure that it works if we do not create the platform-language packages (it should, and we have tests, but...).

Merge / deployment checklist

  • Confirm this change is backwards compatible with existing workflows.
  • Confirm the readme has been updated if necessary.

* Add `bundleName` argument to `getCodeQLBundleDownloadURL`
* Add `languages` argument to `setupCodeQL`.

The logic now tries to find the platform-language pkg before defaulting
to the full bundle. We keep the toolcache clean by adding the pl version
to the tool version.
# This is the 1st commit message:

Add logic to download codeql platform-language pkg

* Add `bundleName` argument to `getCodeQLBundleDownloadURL`
* Add `languages` argument to `setupCodeQL`.

The logic now tries to find the platform-language pkg before defaulting
to the full bundle. We keep the toolcache clean by adding the pl version
to the tool version.

# The commit message #2 will be skipped:

# Add simple fallback logic for download

# The commit message #3 will be skipped:

# wip linter

# The commit message #4 will be skipped:

# linter
# This is the 1st commit message:

Add logic to download codeql platform-language pkg

* Add `bundleName` argument to `getCodeQLBundleDownloadURL`
* Add `languages` argument to `setupCodeQL`.

The logic now tries to find the platform-language pkg before defaulting
to the full bundle. We keep the toolcache clean by adding the pl version
to the tool version.

# The commit message #2 will be skipped:

# add test

# The commit message #3 will be skipped:

# cleanup

# The commit message #4 will be skipped:

# linter
* Add `bundleName` argument to `getCodeQLBundleDownloadURL`
* Add `languages` argument to `setupCodeQL`.

The logic now tries to find the platform-language pkg before defaulting
to the full bundle. We keep the toolcache clean by adding the pl version
to the tool version.
@marcogario marcogario marked this pull request as ready for review September 9, 2020 19:08
@robertbrignull robertbrignull self-assigned this Sep 10, 2020
@marcogario
Copy link
Contributor Author

I ran an experiment comparing zip0 and tar.gz decompression time. There is basically no difference between zip and tar.gz. I would keep the tar.gz for consistency.

Copy link
Contributor

@robertbrignull robertbrignull left a comment

Choose a reason for hiding this comment

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

A couple of comments, but I admit I haven't read through all that fully. I'd like to see a demo if possible as that would be best for showing it works. I'm a bit worried about our use of the toolcache as we're really not using it how it intends with regards to the version strings.

Overall though, the approach this is taking looks like it'll be good.

I'm sure you already know this, but probably worth noting we're also trying to get the bundle pre-populated into the actions runners. It's not clear exactly when this will happen but it's looking like it will. So that would mean that splitting up the bundle would be less useful on dotcom, but this is still potentially very useful for GHES or self-hosted runners on dotcom.

@robertbrignull
Copy link
Contributor

Would https://github.com/github/codeql-action-sync-tool need to be changed as part of this?

@marcogario
Copy link
Contributor Author

marcogario commented Sep 10, 2020

Thanks @robertbrignull, I will go through your comments in detail tomorrow and also update the code to match main.

I'm a bit worried about our use of the toolcache as we're really not using it how it intends with regards to the version strings.

I think we need to dig deeper here. My thought was this would improve all settings. Clearly self-hosted runners, but also dotCom, as I understood there is a window between we releasing a new bundle and the base image being rebuilt. However, also given your comment in that discussion, I might be misunderstanding how the version information is used in the toolcache. Do you have more information you can point me to, or shall we try to sync?

@marcogario marcogario force-pushed the platform_lang_pkg branch 5 times, most recently from a43213e to 1e41045 Compare September 11, 2020 10:33
@marcogario
Copy link
Contributor Author

This is an example of how we fallback in the search of the tool:

 ##[debug]Bundle version 20200826 is not in SemVer format. Will treat it as pre-release 0.0.0-20200826.
  ##[debug]PL Version linux64-javascript
  ##[debug]isExplicit: 0.0.0-20200826-linux64-javascript
  ##[debug]explicit? true
  ##[debug]checking cache: /opt/hostedtoolcache/CodeQL/0.0.0-20200826-linux64-javascript/x64
  ##[debug]not found
  ##[debug]isExplicit: 0.0.0-20200826
  ##[debug]explicit? true
  ##[debug]checking cache: /opt/hostedtoolcache/CodeQL/0.0.0-20200826/x64
  ##[debug]not found
  ##[debug]CodeQL not found in cache
  ##[debug]RUNNER_TEMP=/home/runner/work/_temp
  ##[debug]Using CodeQL URL: https://github.com/github/codeql-action/releases/download/codeql-bundle-20200826/codeql-bundle.tar.gz

@marcogario
Copy link
Contributor Author

I was doing some more testing and I ran into the following issue.

initCodeQL takes a codeqlURL that can be a string or undefined. I thought this was because the tool argument could be underspecified, and thus we have logic to detect which bundle to use. This is the case for the runner, but not for the init-action.ts, where this is always set to a string:

core.getInput('tools'),

What could be the best way to deal with this? Can we detect that the value was not specified in the configuration?

@robertbrignull
Copy link
Contributor

initCodeQL takes a codeqlURL that can be a string or undefined. I thought this was because the tool argument could be underspecified, and thus we have logic to detect which bundle to use. This is the case for the runner, but not for the init-action.ts, where this is always set to a string:

Yes, I agree this is a pain. Your analysis is right that for the runner it might be undefined, but for the action it's always a string. If it's not defined in the workflow then it gets set to the emptystring. So this means the best way to check it may be to do convert it to a boolean to see if it's truthy, but I agree this is no ideal.

I think this is a problem we should deal with and be , though doesn't have to be in this PR. Maybe we should convert all emptystrings to undefined when we read the inputs, but there are other options. I'll open an issue as I think we should track this and make sure it gets improved.

@marcogario
Copy link
Contributor Author

marcogario commented Sep 15, 2020

This is ready for review. I am available to walk through the code. The only change I expect is to rebase on #211, as I currently included the changes from #208.

The macos tests are failing due to some sort of rate limiting. I will try to retrigger them tomorrow.

Copy link
Contributor

@robertbrignull robertbrignull left a comment

Choose a reason for hiding this comment

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

I'm re-reviewing but I'm having to step out now so I'm posting what I have so far. I'll continue reviewing the rest later today.

language: ["none", "cpp", "csharp", "go", "java", "javascript", "python"]
runs-on: ${{ matrix.os }}
steps:
# Translate OS
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you explain what this step is doing? I can't tell just looking at it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, this is a left-over. I might use it now, if I want to test the toolcache (as you suggest below). I am adding a comment, but in general, it is setting an env variable called OS with the correct string value depending on the platform.

env:
TEST_MODE: true

single-language-bundles:
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need some check after running the actions to make sure it actually downloaded the right bundles. Currently it could download the full thing each time and still pass.
You should be able to look inside the toolcache directory and see what it has downloaded. You'll find it under /opt/hostedtoolcache (at least on linux) or you can use $AGENT_TOOLSDIRECTORY (which might work on all operating systems).

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 idea was not to require this, although I can see how it would be good to test this in a non-failing way.
I did not want to make the bundle-release process more complex, so these tests should pass with only the main bundle (fallback behavior). I see how outputting a message that we used the smaller bundler would be useful for validation.

Copy link
Contributor

@robertbrignull robertbrignull left a comment

Choose a reason for hiding this comment

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

Ok, I've gone through everything now.

Only one comment and I can't see anything else wrong, though I'm still a bit uneasy about this feature as a whole because it's just quite complicated and I feel I'm not giving it the brain power / testing time it requires.

Also, #211 has been merged now, so this could be rebased onto that to simply things.

src/codeql.ts Outdated
apiURL === util.GITHUB_DOTCOM_URL &&
repository === CODEQL_DEFAULT_ACTION_REPOSITORY
repository === CODEQL_DEFAULT_ACTION_REPOSITORY &&
bundleNames[0] === CODEQL_BUNDLE_NAME
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not convinced this will ever be true. The only place this is called from non-test code, the 0th element is either the platform bundle or the plVersion bundle. The raw full CODEQL_BUNDLE_NAME is never the 0th element. I can see why you're checking this here, because the idea is to not default to using the full bundle unless necessary, but I don't think the logic is quite right.

Since we own the release on github.com/github/codeql-action could you do the same thing of just assuming the release artifacts will be there for all platforms and languages? I realise they aren't there currently so that will delay merging this PR until they are there. The alternative would be to stop treating github.com as special and make the request to discover what assets are there. I don't have a strong favourite between those options as they both have positive and negative aspects.

@marcogario
Copy link
Contributor Author

Thanks for the review. I think there is a conceptual point to address. I did this work trying to be compatible with the current bundle release process. This has a few visible impact in the implementation. As you noted in the review:

  1. Integrations tests are currently designed to pass if we do NOT have the language specific bundle
  2. The code checking for available bundles gets more complicated and expensive as we need to query the API and cannot shortcut effectively.

Since I automated the creation of the smaller bundles, it would seem that changing the release process has some benefits, with few drawbacks.

The only "problem" I see is that this would require to postpone merging this and first:

  1. Change the release process and merge the workflow to generate the language bundles
  2. Update the sync tool
  3. Finally adjust this PR

@robertbrignull WDYT?

@marcogario
Copy link
Contributor Author

I went ahead and prepared the changes to the process as discussed above. I think that is the most reasonable solution.

  • We need to merge Workflow to split the bundle into components #216 first before the tests for this PR can succeed (as we now do not fail gracefully anymore)
  • I tested the codeql-action-sync-tool and indeed it does download all assets
  • Created a PR for the changes to the bundle release process.

@marcogario
Copy link
Contributor Author

As discussed with @robertbrignull , this will be closed in favor of a simpler version that only accounts for platforms.

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.

3 participants