Skip to content

Commit 0f4a2b0

Browse files
authored
Merge pull request #195 from github/johnbreault-fix-os-filter-matching
Improve UX around --os-include/--os-exclude and --destination-url
2 parents 27598c1 + c363000 commit 0f4a2b0

4 files changed

Lines changed: 76 additions & 6 deletions

File tree

‎README.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ If your GitHub Enterprise Server instance is on a completely isolated network wh
1919
From a machine with access to both GitHub.com and GitHub Enterprise Server use the `./codeql-action-sync sync` command to copy the CodeQL Action and bundles.
2020

2121
**Required Arguments:**
22-
* `--destination-url` - The URL of the GitHub Enterprise Server instance to push the Action to.
22+
* `--destination-url` - The URL of the GitHub Enterprise Server instance to push the Action to. If no protocol scheme is included (e.g. you pass `github.example.com` instead of `https://github.example.com`), `https://` is assumed.
2323
* `--destination-token` - A [Personal Access Token](https://docs.github.com/en/enterprise/user/github/authenticating-to-github/creating-a-personal-access-token) for the destination GitHub Enterprise Server instance. If the destination repository is in an organization that does not yet exist or that you are not an owner of, your token will need to have the `site_admin` scope in order to create the organization or update the repository in it. The organization can also be created manually or an existing organization that you own can be used, in which case the `repo` and `workflow` scopes are sufficient. The token can also be provided by setting the `CODEQL_ACTION_SYNC_TOOL_DESTINATION_TOKEN` environment variable.
2424

2525
**Optional Arguments:**
@@ -29,8 +29,8 @@ From a machine with access to both GitHub.com and GitHub Enterprise Server use t
2929
* `--actions-admin-user` - The name of the Actions admin user, which will be used if you are updating the bundled CodeQL Action. If not specified `actions-admin` will be used.
3030
* `--force` - By default the tool will not overwrite existing repositories. Providing this flag will allow it to.
3131
* `--push-ssh` - Push Git contents over SSH rather than HTTPS. To use this option you must have SSH access to your GitHub Enterprise instance configured.
32-
* `--os-include` - A comma-separated list of operating systems (e.g. `linux64,win64`) to include CodeQL bundle release assets for. Cannot be used together with `--os-exclude`. If neither is specified, assets for all operating systems are synced.
33-
* `--os-exclude` - A comma-separated list of operating systems (e.g. `win64,osx64`) to exclude CodeQL bundle release assets for. Cannot be used together with `--os-include`.
32+
* `--os-include` - A comma-separated list of operating systems to include CodeQL bundle release assets for. Cannot be used together with `--os-exclude`. If neither is specified, assets for all operating systems are synced. Values must exactly match the OS identifier embedded in the asset name (for example `linux64`, `linux-arm64`, `osx64`, `win64` — not shorthand like `linux` or `win`). If a value does not match any asset in the releases being pulled, a warning listing the OS identifiers that were actually found is logged.
33+
* `--os-exclude` - A comma-separated list of operating systems to exclude CodeQL bundle release assets for. Cannot be used together with `--os-include`. Values must exactly match the OS identifier embedded in the asset name (for example `linux64`, `linux-arm64`, `osx64`, `win64`).
3434
* `--compression-format` - The compression format of CodeQL bundle release assets to sync, either `gz` or `zst`. If not specified, both compression formats are synced.
3535

3636
### I don't have a machine that can access both GitHub.com and GitHub Enterprise Server.
@@ -39,16 +39,16 @@ From a machine with access to GitHub.com use the `./codeql-action-sync pull` com
3939
**Optional Arguments:**
4040
* `--cache-dir` - The directory in which to store data downloaded from GitHub.com. If not specified a directory next to the sync tool will be used.
4141
* `--source-token` - A token to access the API of GitHub.com. This is normally not required, but can be provided if you have issues with API rate limiting. The token does not need to have any scopes.
42-
* `--os-include` - A comma-separated list of operating systems (e.g. `linux64,win64`) to include CodeQL bundle release assets for. Cannot be used together with `--os-exclude`. If neither is specified, assets for all operating systems are synced.
43-
* `--os-exclude` - A comma-separated list of operating systems (e.g. `win64,osx64`) to exclude CodeQL bundle release assets for. Cannot be used together with `--os-include`.
42+
* `--os-include` - A comma-separated list of operating systems to include CodeQL bundle release assets for. Cannot be used together with `--os-exclude`. If neither is specified, assets for all operating systems are synced. Values must exactly match the OS identifier embedded in the asset name (for example `linux64`, `linux-arm64`, `osx64`, `win64` — not shorthand like `linux` or `win`). If a value does not match any asset in the releases being pulled, a warning listing the OS identifiers that were actually found is logged.
43+
* `--os-exclude` - A comma-separated list of operating systems to exclude CodeQL bundle release assets for. Cannot be used together with `--os-include`. Values must exactly match the OS identifier embedded in the asset name (for example `linux64`, `linux-arm64`, `osx64`, `win64`).
4444
* `--compression-format` - The compression format of CodeQL bundle release assets to sync, either `gz` or `zst`. If not specified, both compression formats are synced.
4545

4646
Next copy the sync tool and cache directory to another machine which has access to GitHub Enterprise Server.
4747

4848
Now use the `./codeql-action-sync push` command to upload the CodeQL Action and bundles to GitHub Enterprise Server.
4949

5050
**Required Arguments:**
51-
* `--destination-url` - The URL of the GitHub Enterprise Server instance to push the Action to.
51+
* `--destination-url` - The URL of the GitHub Enterprise Server instance to push the Action to. If no protocol scheme is included (e.g. you pass `github.example.com` instead of `https://github.example.com`), `https://` is assumed.
5252
* `--destination-token` - A [Personal Access Token](https://docs.github.com/en/enterprise/user/github/authenticating-to-github/creating-a-personal-access-token) for the destination GitHub Enterprise Server instance. If the destination repository is in an organization that does not yet exist or that you are not an owner of, your token will need to have the `site_admin` scope in order to create the organization or update the repository in it. The organization can also be created manually or an existing organization that you own can be used, in which case the `repo` and `workflow` scopes are sufficient. The token can also be provided by setting the `CODEQL_ACTION_SYNC_TOOL_DESTINATION_TOKEN` environment variable.
5353

5454
**Optional Arguments:**

‎internal/pull/pull.go‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"os"
1010
"regexp"
11+
"sort"
1112
"strings"
1213

1314
log "github.com/sirupsen/logrus"
@@ -50,6 +51,7 @@ type pullService struct {
5051
assetOSIncludes []string
5152
assetOSExcludes []string
5253
assetCompressionFormat string
54+
seenAssetOSs map[string]bool
5355
}
5456

5557
// shouldDownloadAsset determines whether a release asset should be downloaded, based on the
@@ -64,6 +66,11 @@ func (pullService *pullService) shouldDownloadAsset(assetName string) bool {
6466
assetOS := matches[1]
6567
assetCompressionFormat := matches[2]
6668

69+
if pullService.seenAssetOSs == nil {
70+
pullService.seenAssetOSs = map[string]bool{}
71+
}
72+
pullService.seenAssetOSs[assetOS] = true
73+
6774
if len(pullService.assetOSIncludes) > 0 {
6875
included := false
6976
for _, os := range pullService.assetOSIncludes {
@@ -309,9 +316,36 @@ func (pullService *pullService) pullReleases() error {
309316
}
310317
}
311318
}
319+
pullService.warnOnUnmatchedOSFilters()
312320
return nil
313321
}
314322

323+
// warnOnUnmatchedOSFilters logs a warning if none of the configured --os-include or --os-exclude
324+
// values matched the OS identifier of any release asset that was actually encountered. This
325+
// helps surface typos or incorrect assumptions about asset OS identifiers (for example passing
326+
// "linux" when the real identifiers are "linux64"/"linux-arm64"), which would otherwise silently
327+
// filter out every OS-specific asset without any indication of why.
328+
func (pullService *pullService) warnOnUnmatchedOSFilters() {
329+
seenList := make([]string, 0, len(pullService.seenAssetOSs))
330+
for os := range pullService.seenAssetOSs {
331+
seenList = append(seenList, os)
332+
}
333+
sort.Strings(seenList)
334+
335+
checkUnmatched := func(flagName string, values []string) {
336+
for _, value := range values {
337+
if !pullService.seenAssetOSs[value] {
338+
log.Warnf(
339+
"The %s value %q did not match any release asset. The OS identifiers found in the releases pulled were: %s.",
340+
flagName, value, strings.Join(seenList, ", "),
341+
)
342+
}
343+
}
344+
}
345+
checkUnmatched("--os-include", pullService.assetOSIncludes)
346+
checkUnmatched("--os-exclude", pullService.assetOSExcludes)
347+
}
348+
315349
func Pull(ctx context.Context, cacheDirectory cachedirectory.CacheDirectory, sourceToken string, sourceURL string, assetOSIncludes []string, assetOSExcludes []string, assetCompressionFormat string) error {
316350
err := cacheDirectory.CheckOrCreateVersionFile(true, version.Version())
317351
if err != nil {

‎internal/pull/pull_test.go‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/github/codeql-action-sync/internal/cachedirectory"
1010
"github.com/go-git/go-git/v5"
1111
"github.com/go-git/go-git/v5/plumbing"
12+
log "github.com/sirupsen/logrus"
13+
logtest "github.com/sirupsen/logrus/hooks/test"
1214
"github.com/stretchr/testify/require"
1315

1416
"github.com/github/codeql-action-sync/test"
@@ -202,6 +204,36 @@ func TestShouldDownloadAsset(t *testing.T) {
202204
}
203205
}
204206

207+
func TestWarnOnUnmatchedOSFilters(t *testing.T) {
208+
hook := logtest.NewGlobal()
209+
defer hook.Reset()
210+
211+
pullService := pullService{
212+
assetOSIncludes: []string{"linux", "win64"},
213+
seenAssetOSs: map[string]bool{"win64": true, "osx64": true},
214+
}
215+
pullService.warnOnUnmatchedOSFilters()
216+
217+
require.Len(t, hook.Entries, 1)
218+
require.Equal(t, log.WarnLevel, hook.Entries[0].Level)
219+
require.Contains(t, hook.Entries[0].Message, `The --os-include value "linux" did not match any release asset`)
220+
require.Contains(t, hook.Entries[0].Message, "osx64, win64")
221+
}
222+
223+
func TestWarnOnUnmatchedOSFiltersNoWarningWhenAllMatch(t *testing.T) {
224+
hook := logtest.NewGlobal()
225+
defer hook.Reset()
226+
227+
pullService := pullService{
228+
assetOSIncludes: []string{"linux64"},
229+
assetOSExcludes: []string{"win64"},
230+
seenAssetOSs: map[string]bool{"linux64": true, "win64": true, "osx64": true},
231+
}
232+
pullService.warnOnUnmatchedOSFilters()
233+
234+
require.Empty(t, hook.Entries)
235+
}
236+
205237
func TestFindRelevantReleases(t *testing.T) {
206238
temporaryDirectory := test.CreateTemporaryDirectory(t)
207239
pullService := getTestPullService(t, temporaryDirectory, initialActionRepository, "")

‎internal/push/push.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,10 @@ func Push(ctx context.Context, cacheDirectory cachedirectory.CacheDirectory, des
444444
}
445445

446446
destinationURL = strings.TrimRight(destinationURL, "/")
447+
if !strings.Contains(destinationURL, "://") {
448+
log.Warnf("No protocol scheme specified in --destination-url %q, assuming https://.", destinationURL)
449+
destinationURL = "https://" + destinationURL
450+
}
447451
token := oauth2.Token{AccessToken: destinationToken}
448452
tokenSource := oauth2.StaticTokenSource(
449453
&token,

0 commit comments

Comments
 (0)