-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(analytics): Add client-side functionality for analytics collection #5249
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1212,6 +1212,34 @@ function Out-UTF8File { | |
} | ||
} | ||
|
||
function Get-CIEnvironment { | ||
foreach ($ci_env in @{ | ||
'APPVEYOR' = 'AppVeyor' | ||
'TF_BUILD' = 'Azure Pipelines' | ||
'bamboo.buildKey' = 'Bamboo' | ||
'BUILDKITE' = 'Buildkite' | ||
'CIRCLECI' = 'Circle CI' | ||
'CIRRUS_CI' = 'Cirrus CI' | ||
'CODEBUILD_BUILD_ID' = 'CodeBuild' | ||
'GITHUB_ACTIONS' = 'Github Actions' | ||
'GITLAB_CI' = 'GitLab CI' | ||
'HEROKU_TEST_RUN_ID' = 'Heroku CI' | ||
'TEAMCITY_VERSION' = 'TeamCity' | ||
'TRAVIS' = 'Travis CI' | ||
}.GetEnumerator()) { | ||
if (-not [String]::IsNullOrEmpty((Get-Item "Env:/$($ci_env.Key)" -ErrorAction Ignore).Value)) { | ||
return $ci_env.Value | ||
} | ||
} | ||
foreach ($ci_env in 'BUILD_ID', 'CI') { | ||
if (-not [String]::IsNullOrEmpty((Get-Item "Env:/$($ci_env)" -ErrorAction Ignore).Value)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above |
||
return 'generic' | ||
} | ||
} | ||
|
||
return "" | ||
} | ||
|
||
################## | ||
# Core Bootstrap # | ||
################## | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,128 @@ | ||||||||||||||||||||||||||||||||
# Usage: scoop analytics | ||||||||||||||||||||||||||||||||
# Summary: Collects and sends Scoop usage analytics to a remote server | ||||||||||||||||||||||||||||||||
# Help: This is an internal command. It is used to collect and send usage analytics | ||||||||||||||||||||||||||||||||
# to a remote server, at an interval of 7 days. The following data is collected: | ||||||||||||||||||||||||||||||||
# - Randomly generated (one-time) anonymous ID | ||||||||||||||||||||||||||||||||
# - Machine info | ||||||||||||||||||||||||||||||||
# - OS build number | ||||||||||||||||||||||||||||||||
# - OS Architecture | ||||||||||||||||||||||||||||||||
# - PowerShell Desktop version | ||||||||||||||||||||||||||||||||
# - PowerShell Core version | ||||||||||||||||||||||||||||||||
# - Scoop version | ||||||||||||||||||||||||||||||||
# - Apps installed from public buckets (private apps are filtered out) | ||||||||||||||||||||||||||||||||
# - Name | ||||||||||||||||||||||||||||||||
# - Version | ||||||||||||||||||||||||||||||||
# - Last updated | ||||||||||||||||||||||||||||||||
# - Source | ||||||||||||||||||||||||||||||||
# - Architecture | ||||||||||||||||||||||||||||||||
# - User or Global installation | ||||||||||||||||||||||||||||||||
# - Installation status | ||||||||||||||||||||||||||||||||
# - Public buckets (private buckets are filtered out) | ||||||||||||||||||||||||||||||||
# - Name | ||||||||||||||||||||||||||||||||
# - Source | ||||||||||||||||||||||||||||||||
# - Last updated | ||||||||||||||||||||||||||||||||
# - Manifest count | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
. "$PSScriptRoot\..\lib\json.ps1" # 'ConvertToPrettyJson' | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Just skip the whole script if analytics.scoop.sh can't be resolved (because it will get added to public blocklists 😄) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, good idea. But I notice that it takes 10 seconds to time out, isn't that a bit much? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, it returns instantly for me. Maybe because I use a local Adguard in my network. 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that it takes time when connected to my Azure VPN server. On other networks it returns instantly. It's useful regardless, so I'll add it. |
||||||||||||||||||||||||||||||||
if ([String]::IsNullOrEmpty((get_config ANALYTICS_ID))) { | ||||||||||||||||||||||||||||||||
set_config ANALYTICS_ID (New-Guid).Guid | Out-Null | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
Comment on lines
+28
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use random ID is better IMO |
||||||||||||||||||||||||||||||||
$def_arch = Get-DefaultArchitecture | ||||||||||||||||||||||||||||||||
$known_sources = foreach ($item in (known_bucket_repos).PSObject.Properties) { $item.Value } | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
function Test-PublicSource($source) { | ||||||||||||||||||||||||||||||||
# Known sources | ||||||||||||||||||||||||||||||||
if ($source -in $known_sources) { | ||||||||||||||||||||||||||||||||
return $true | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
# Local file paths, SSH remotes, and remotes with usernames | ||||||||||||||||||||||||||||||||
if ($source -match '^/[A-Za-z]:/|^[A-Za-z]:/|^\./|^\.\./|file:/|ssh:/|@') { | ||||||||||||||||||||||||||||||||
return $false | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
return $true | ||||||||||||||||||||||||||||||||
Comment on lines
+35
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$stats = [ordered]@{} | ||||||||||||||||||||||||||||||||
$stats.id = get_config ANALYTICS_ID | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$stats.machine = [ordered]@{ | ||||||||||||||||||||||||||||||||
Build = [System.Environment]::OSVersion.Version.ToString() | ||||||||||||||||||||||||||||||||
Arch = $def_arch | ||||||||||||||||||||||||||||||||
Desktop = (Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine -Name 'PowerShellVersion').PowerShellVersion | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this useful? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All that information is also available in |
||||||||||||||||||||||||||||||||
Core = if (Get-Command pwsh -ErrorAction Ignore) { | ||||||||||||||||||||||||||||||||
(Get-Item (Get-Command pwsh).Source).VersionInfo.ProductVersionRaw.ToString() | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||
"" | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
Scoop = if (Test-Path "$PSScriptRoot\..\.git") { | ||||||||||||||||||||||||||||||||
$branch = (Get-Content "$PSScriptRoot\..\.git\HEAD").Replace('ref: ', '') | ||||||||||||||||||||||||||||||||
"$(Get-Content (Join-Path "$PSScriptRoot\..\.git" $branch)) ($($branch.Split('/')[-1]))" | ||||||||||||||||||||||||||||||||
} elseif (Test-Path "$PSScriptRoot\..\CHANGELOG.md") { | ||||||||||||||||||||||||||||||||
(Select-String '^## .*([\d]{4}-[\d]{2}-[\d]{2})' "$PSScriptRoot\..\CHANGELOG.md").Matches.Groups[1].Value | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
The version number is better. I don't think there's user used v0.1.0 and lower. |
||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||
"" | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See above, the |
||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$bucket_names = @() | ||||||||||||||||||||||||||||||||
$stats.buckets = @() | ||||||||||||||||||||||||||||||||
foreach ($item in list_buckets) { | ||||||||||||||||||||||||||||||||
# Filter out private buckets | ||||||||||||||||||||||||||||||||
if (Test-PublicSource $item.Source) { | ||||||||||||||||||||||||||||||||
$stats.buckets += $item | ||||||||||||||||||||||||||||||||
$bucket_names += $item.Name | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$stats.apps = @() | ||||||||||||||||||||||||||||||||
foreach ($item in @(& "$PSScriptRoot\scoop-list.ps1" 6>$null)) { | ||||||||||||||||||||||||||||||||
# Filter out private apps | ||||||||||||||||||||||||||||||||
if ($item.Source -notin $bucket_names) { | ||||||||||||||||||||||||||||||||
continue | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$info = $item.Info -Split ', ' | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$newitem = [ordered]@{} | ||||||||||||||||||||||||||||||||
$newitem.Name = $item.Name | ||||||||||||||||||||||||||||||||
$newitem.Version = $item.Version | ||||||||||||||||||||||||||||||||
$newitem.Source = $item.Source | ||||||||||||||||||||||||||||||||
$newitem.Updated = $item.Updated | ||||||||||||||||||||||||||||||||
$newitem.Global = 'Global install' -in $info | ||||||||||||||||||||||||||||||||
$newitem.Arch = if ('64bit' -in $info -and '64bit' -ne $def_arch) { | ||||||||||||||||||||||||||||||||
'64bit' | ||||||||||||||||||||||||||||||||
} elseif ('32bit' -in $info -and '32bit' -ne $def_arch) { | ||||||||||||||||||||||||||||||||
'32bit' | ||||||||||||||||||||||||||||||||
} elseif ('arm64' -in $info -and 'arm64' -ne $def_arch) { | ||||||||||||||||||||||||||||||||
'arm64' | ||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||
$def_arch | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
$newitem.Status = if ('Held package' -in $info) { | ||||||||||||||||||||||||||||||||
'Held' | ||||||||||||||||||||||||||||||||
} elseif ('Install failed' -in $info) { | ||||||||||||||||||||||||||||||||
'Failed' | ||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||
'OK' | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$stats.apps += $newitem | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
$payload = $stats | ConvertToPrettyJSON | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The payload needn't be prettified, right? |
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||
Invoke-RestMethod -Method Post ` | ||||||||||||||||||||||||||||||||
-Uri 'https://analytics.scoop.sh/post' ` | ||||||||||||||||||||||||||||||||
-Body $payload ` | ||||||||||||||||||||||||||||||||
-ContentType "application/json" | ||||||||||||||||||||||||||||||||
set_config ANALYTICS_TIMESTAMP ([System.DateTime]::Now.ToString('o')) | Out-Null | ||||||||||||||||||||||||||||||||
} catch { | ||||||||||||||||||||||||||||||||
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ | ||||||||||||||||||||||||||||||||
Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
exit 0 | ||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And why there's
/
afterEnv:
?