From a457ac42459e1bc077e04da69bece798ce1043e8 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 17 Apr 2024 16:56:16 +0200 Subject: [PATCH 1/7] Ignore default windows icons --- service/profile/api.go | 7 ++++++- service/profile/binmeta/icons.go | 13 +++++++++++++ service/profile/binmeta/ignore.go | 30 ++++++++++++++++++++++++++++++ service/profile/profile.go | 8 +++++++- 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 service/profile/binmeta/ignore.go diff --git a/service/profile/api.go b/service/profile/api.go index 7b02e914..b7fa8079 100644 --- a/service/profile/api.go +++ b/service/profile/api.go @@ -100,7 +100,12 @@ func handleGetProfileIcon(ar *api.Request) (data []byte, err error) { // Get profile icon. data, err = binmeta.GetProfileIcon(name) - if err != nil { + switch { + case err == nil: + // Continue + case errors.Is(err, binmeta.IconIgnored): + return nil, api.ErrorWithStatus(err, http.StatusNotFound) + default: return nil, err } diff --git a/service/profile/binmeta/icons.go b/service/profile/binmeta/icons.go index 595fbb10..04a8bcb2 100644 --- a/service/profile/binmeta/icons.go +++ b/service/profile/binmeta/icons.go @@ -19,6 +19,9 @@ import ( // Must not be changed once set. var ProfileIconStoragePath = "" +// IconIgnored is returned when the icon should be ignored. +var IconIgnored = errors.New("icon is ignored") + // GetProfileIcon returns the profile icon with the given ID and extension. func GetProfileIcon(name string) (data []byte, err error) { // Check if enabled. @@ -26,6 +29,11 @@ func GetProfileIcon(name string) (data []byte, err error) { return nil, errors.New("api icon storage not configured") } + // Check if icon should be ignored. + if IgnoreIcon(name) { + return nil, IconIgnored + } + // Build storage path. iconPath := filepath.Clean( filepath.Join(ProfileIconStoragePath, name), @@ -59,6 +67,11 @@ func UpdateProfileIcon(data []byte, ext string) (filename string, err error) { } sum := hex.EncodeToString(h.Sum(nil)) + // Check if icon should be ignored. + if IgnoreIcon(sum) { + return "", IconIgnored + } + // Check ext. ext = strings.ToLower(ext) switch ext { diff --git a/service/profile/binmeta/ignore.go b/service/profile/binmeta/ignore.go new file mode 100644 index 00000000..e708ae84 --- /dev/null +++ b/service/profile/binmeta/ignore.go @@ -0,0 +1,30 @@ +package binmeta + +import ( + "strings" +) + +var ignoreIcons = map[string]struct{}{ + // Windows Default Icons. + "a27898ddfa4e0481b62c69faa196919a738fcade": {}, + "5a3eea8bcd08b9336ce9c5083f26185164268ee9": {}, + "573393d6ad238d255b20dc1c1b303c95debe6965": {}, + "d459b2cb23c27cc31ccab5025533048d5d8301bf": {}, + "d35a0d91ebfda81df5286f68ec5ddb1d6ad6b850": {}, + "cc33187385498384f1b648e23be5ef1a2e9f5f71": {}, +} + +// IgnoreIcon returns whether an icon should be ignored or not. +func IgnoreIcon(name string) bool { + // Make lower case. + name = strings.ToLower(name) + // Remove extension. + extIndex := strings.Index(name, ".") + if extIndex > 0 { + name = name[:extIndex] + } + + // Check if ID is in list. + _, found := ignoreIcons[name] + return found +} diff --git a/service/profile/profile.go b/service/profile/profile.go index fff41908..a97cd38c 100644 --- a/service/profile/profile.go +++ b/service/profile/profile.go @@ -515,7 +515,13 @@ func (profile *Profile) updateMetadataFromSystem(ctx context.Context, md Matchin // Get binary icon and name. newIcon, newName, err := binmeta.GetIconAndName(ctx, profile.PresentationPath, home) - if err != nil { + switch { + case err == nil: + // Continue + case errors.Is(err, binmeta.IconIgnored): + newIcon = nil + // Continue + default: log.Warningf("profile: failed to get binary icon/name for %s: %s", profile.PresentationPath, err) } From cdabffafcd4e97e5ea54f691b7d73b27c7a2eb4a Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 17 Apr 2024 17:01:37 +0200 Subject: [PATCH 2/7] Fix error naming --- service/profile/api.go | 2 +- service/profile/binmeta/icons.go | 8 ++++---- service/profile/profile.go | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/service/profile/api.go b/service/profile/api.go index b7fa8079..04834856 100644 --- a/service/profile/api.go +++ b/service/profile/api.go @@ -103,7 +103,7 @@ func handleGetProfileIcon(ar *api.Request) (data []byte, err error) { switch { case err == nil: // Continue - case errors.Is(err, binmeta.IconIgnored): + case errors.Is(err, binmeta.ErrIconIgnored): return nil, api.ErrorWithStatus(err, http.StatusNotFound) default: return nil, err diff --git a/service/profile/binmeta/icons.go b/service/profile/binmeta/icons.go index 04a8bcb2..3abe6ce8 100644 --- a/service/profile/binmeta/icons.go +++ b/service/profile/binmeta/icons.go @@ -19,8 +19,8 @@ import ( // Must not be changed once set. var ProfileIconStoragePath = "" -// IconIgnored is returned when the icon should be ignored. -var IconIgnored = errors.New("icon is ignored") +// ErrIconIgnored is returned when the icon should be ignored. +var ErrIconIgnored = errors.New("icon is ignored") // GetProfileIcon returns the profile icon with the given ID and extension. func GetProfileIcon(name string) (data []byte, err error) { @@ -31,7 +31,7 @@ func GetProfileIcon(name string) (data []byte, err error) { // Check if icon should be ignored. if IgnoreIcon(name) { - return nil, IconIgnored + return nil, ErrIconIgnored } // Build storage path. @@ -69,7 +69,7 @@ func UpdateProfileIcon(data []byte, ext string) (filename string, err error) { // Check if icon should be ignored. if IgnoreIcon(sum) { - return "", IconIgnored + return "", ErrIconIgnored } // Check ext. diff --git a/service/profile/profile.go b/service/profile/profile.go index a97cd38c..a11f7dd9 100644 --- a/service/profile/profile.go +++ b/service/profile/profile.go @@ -518,7 +518,7 @@ func (profile *Profile) updateMetadataFromSystem(ctx context.Context, md Matchin switch { case err == nil: // Continue - case errors.Is(err, binmeta.IconIgnored): + case errors.Is(err, binmeta.ErrIconIgnored): newIcon = nil // Continue default: From e957b90b1328a1dc0309717cc158b8af801e1d23 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 18 Apr 2024 13:50:47 +0200 Subject: [PATCH 3/7] Ignore default Windows icons in UI better --- .../src/lib/app-profile.types.ts | 2 +- .../src/app/shared/app-icon/app-icon.ts | 23 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/desktop/angular/projects/safing/portmaster-api/src/lib/app-profile.types.ts b/desktop/angular/projects/safing/portmaster-api/src/lib/app-profile.types.ts index 986d62ff..b73a9254 100644 --- a/desktop/angular/projects/safing/portmaster-api/src/lib/app-profile.types.ts +++ b/desktop/angular/projects/safing/portmaster-api/src/lib/app-profile.types.ts @@ -50,7 +50,7 @@ export interface TagDescription { } export interface Icon { - Type: 'database' | 'path' | 'api'; + Type: '' | 'database' | 'path' | 'api'; Source: '' | 'user' | 'import' | 'core' | 'ui'; Value: string; } diff --git a/desktop/angular/src/app/shared/app-icon/app-icon.ts b/desktop/angular/src/app/shared/app-icon/app-icon.ts index f013f4e8..ccd98329 100644 --- a/desktop/angular/src/app/shared/app-icon/app-icon.ts +++ b/desktop/angular/src/app/shared/app-icon/app-icon.ts @@ -40,7 +40,7 @@ export interface IDandName { // Some icons we don't want to show on the UI. // Note that this works on a best effort basis and might // start breaking with updates to the built-in icons... -const iconsToIngore = [ +const iconBlobsToIgnore = [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABU0lEQVRYhe2WTUrEQBCF36i4ctm4FsdTKF5AEFxL0knuILgQXAy4ELxDfgTXguAFRG/hDXKCAbtcOB3aSVenMjPRTb5NvdCE97oq3QQYGflnJlbc3T/QXxrfXF9NAGBraKPTk2Nvtey4D1l8OUiIo8ODX/Xt/cMfQCk1SAAi8upWgLquWy8rpbB7+yk2m8+mYvNWAAB4fnlt9MX5WaP397ZhCPgygCFa1IUmwJifCgB5nrMBtdbhAK6pi9QcALIs8+5c1AEOqTmwZge4EUjNiQhpmjbarcvaG4AbgcTcUhSFfwFAHMfhABxScwBIkgRA9wnwBgiOQGBORCjLkl2PoigcgB2BwNzifmi97wEOqTkRoaoqdr2zA9wIJOYWrTW785VPQR+WO2B3vdYIpBBRc9Qkp2Cw/4GVR+BjPpt23u19tUXUgU2aBzuQPz5J8oyMjGyUb9+FOUOmulVPAAAAAElFTkSuQmCC', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACLElEQVR4nO2av07DMBDGP1DFxtaFmbeg6gtUqtQZtU3yDkgMSAxIDEi8Q/8gMVdC4m1YYO0TMNQspErdOG3Md25c7rc0st3E353v7EsLKIqiKIqiKMq/5MRueHx6NoeYSCjubm82NJ8eaiISdDtX6HauKq9tWsFmF4DPr6+d1zalBshG18RpNYfJy+tW21GFgA+lK6DdboeeBwVjyvO3qx1wGGC5XO71wCYZykc8QEqCZ/cfjNs4+X64rOz3FQ/sMMDi7R2Dfg+Lt/eN9kG/tzX24rwFA8AYYGXM+nr9aQADs9mG37FWW3HsqqBhMpnsFFRGkiTOvkoD5ELLBNtIiLcdmGXZ5jP/4Pkc2i4gIb5KRl3xrnbaQSiEeN8QGI/Hzj5aDgjh+SzLaJ7P4eWAiJZ9EVoIhBA/nU695uYdAnUI4fk0TUvbXeP3gZcDhMS7CLIL1DsHyIv3DYHRaOTs44YAZD2fpik9EfIOQohn2Rch5wBZ8bPZzOObfwiBurWAtOftoqaO511jaSEgJd4FQzwgmAQlxPuGwHA4dPbJ1QICnk+ShOb5HJlaoOHLvgi/FhAUP5/P9xpbteRtyDlA1vN2UVPH8+K7gJR45/MI4gHyK7HYxANsA7BuVvkcnniAXAtIwxYPRPTboIR4IBIDMMSL7wIhYZbF0RmgsS9EQtDY1+L5r7esCUrGvA3xHBCfeIBkgBjEi+0CMYsHHDmg7N9UiqIoiqIoiqIcFT++NKIXgDvowAAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAABqUlEQVRYhe2XP2rDMBSHfymhU0dDD5BbJOQCgUDmEv+7Q6FDoUOgQ6F3cJxC50Agt+nSrD5BBr8OqVyrtfWkl8ShoG+SjJE+/95DwoDH4/nf9NTg+eWVLinym8eH+x4AXF1i8/FoiPFoaBwr+p3bAfjc7dixQhNMw7szatmTvb1XY00wCILOZYjIONcEi6JoXSgIAlw/fYhF9ouBsxzQ0IPrzRaz6QTrzbZ6NptOqvHtTR8EQklAWQIl4WdOQEkEqsaHefm9b5Zl7IfEcWwWVDJ1Ke0rHeXqmaRpeljDIrlWQQ5XufreNglGUWQW5EoslQOAJEm0uagHuRJL5YgIy+Wycc06bIIcEjmFStCUnPGYASxKLJQDYJVgGIZmQZsSS+SAv0eIKblWQQ6pHBEhz3N2fTZBrsQSOYVK0JQc24N2JXaXA2CV4Hw+NwtySOUA/QixvU1kPSiQIyKsViv2vaMTlMgpoihik2N7kEMqB6AxwXpiVlfduSAi7Qix7cGL/DS5XHWdC7rIAY4l3i8GTk1+zLsKpwS7lnMS7ErOeMzU/0c9Ho/nNHwBdUH2gB9vJRsAAAAASUVORK5CYII=', @@ -48,6 +48,15 @@ const iconsToIngore = [ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAByUlEQVRYhe1WQUoDQRCs2UTwEBS8R//gwU+I4DFXX2AENRgQEcGr8RFCHuPRFxgPnkQ0F9Ht9rAzsz0zO8luTFzB1GHDZENXdVX3EGCJ/w7VO+3eJKrZrYOc+GuQ/Ab57t5+4Weiml111jvmy6vrRWsoxMV5H0ktzAJNeRgOhxiPxwCAVquFTqcDANi5e8bTewqAwQzoB8BwvxPn9loD9webE+sGAuQLidHbpy0OBpg5e8GsxRhNpH8HjF5pat1AQBREBV2yIwrM+mgEcanSpSJgyjoN7JekDDDrrtk+JtYNBMSs4jT18jadSydycbnQyXUDATEYB2xRMwfCbmX5dVyYZwRpaomd/MUwknTBy//HEZjq7LjgzQS0U0ap0DCHCMgOnPLXECyIEbozBZW2AGBQgf0sZsM5VxUQj4CyFbMbaIZSv5eDV6H7QEAMZghtZ8RahEuWRaWFzCIgHgF5q+YNonDEnY+KAqIXkZ4BsiKKtiEXMvM9EIXegnzfxVXMDAUlruFFbEFKTubGZmVsB3lxlOIOBcQiaK+v4PHlQxPlXZK/DQJbG6vVBcTw0N8uVWwW1P6XTPVOjgZJ0jisg5yIb+vgXeJv4RvrxrtwzfCUqAAAAABJRU5ErkJggg==', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADo0lEQVRYhe2Wu28cVRTGf+fcuzZeY0NCUqTgD3C8mzRU0KDQEgmqoBSGhoKWAlFEKYyQAAkrTRRqOpCQkOhAkUCio4D4IYSAzkkKB+wQbLy7c8+hmNmd2WecDQoFfNJodGfn7vc4Z84M/I9/GfLeB1cutdqH7zxSUli9fOntd4EsmrVXL1xcodVqAf6PEl37+AveWDk/dP78s08vA1eBvSgSDnd3bs49DJGKICIg+dod3J3XXn6Ogz9+49WXnu07F1gA9mOWJRqNBrNRcJ8mAQF8ZHYyuBYhI/DlV9cBAqARnBAj2agdjwARoBaETnK+/eY7NMwfaaPZPueefwaA73+4MfKeM80GAC+8+QkA19cukCQOC+ga1zDPR1//jIgjWhzBEQWNBupoNESdldNn2dm5w/FjT/SIpkEcvLAwX0PUQRwNXQGOBCvXoVpxZ31jc2ICEwWY+1y19AvzEQr3GgAtiLUUo8F690tB5DhC3sgiw800f2p/fAJ/tTtoyMOo1yOqnscdnINOIqNDO+vQbrdwMTRWEnBhfXNyAvOn9qmfOBgvwKxwC9TnAskTN3f32PnzHi1robEbv6HFUVGQJ+AOIvkQgL4U6icOqC9OSKCKu4cH/HT7Nh3P0GiEWkEcc+LBEhylB+qL+ywe+328gGrFNre3kWiE6EjsOi5EqPVS6EGEZrOJW0JVR5KMIy8TqCjQmlUcl7GLlvGrlgLcYWNzY2ICk1CUoFSgtdRPHAwtYteQeimUCuDsmebEMX7l3Pv3E1BCY+lUgqNaFZJ663ID3Fh/6ARKhFrqNVq15lVy1dRP1FjGRaZ6lQwnEKqkw+Si/QLMATwnHxhA7o65k2UJM0NwanOP30dATAPkhmjlmuYiuhCcja0fR7prNhqA4W5Fjwz3ydBTEGLZaKoV99p13y8AnGZjeeT4dfd8LrnnCYyoUQTQQsGtW7/y+tPnR7oZxPb2LywvncRd2dzaGnnP6aUlzBLJvKt1tIAsObUAF195kZ2dO0cSsLx0EgAz6yWQO3aSGeZOJ8swS5gNj+c+AeYwE4QgxlPHF6nNzkBKpGQ4EGMAnSksOGCA41nisJP/eTfuVIjAHQRCCITiPaPjBAC0kwMKMkvW7vuJTgZQffSkOBRCLqeL0cN4PKLA6trah2/FGB97wL05oSohKCEEzMBSRkpp4gf+3d3dq+SOTIAZ4Enyz+QwjYgpkIB7wF6RIxGo8eAJTgsDOpB/jP+38TcKdstukjAxWQAAAABJRU5ErkJggg==', ]; +const iconIDsToIgnore = [ + "a27898ddfa4e0481b62c69faa196919a738fcade", + "5a3eea8bcd08b9336ce9c5083f26185164268ee9", + "573393d6ad238d255b20dc1c1b303c95debe6965", + "d459b2cb23c27cc31ccab5025533048d5d8301bf", + "d35a0d91ebfda81df5286f68ec5ddb1d6ad6b850", + "cc33187385498384f1b648e23be5ef1a2e9f5f71", +]; + const profilesToIgnore = ['local/_unidentified', 'local/_unsolicited']; @@ -86,7 +95,7 @@ export class AppIconComponent implements OnInit, OnDestroy { this._profile = p || null; if (this.initDone) { - this.updateView(); + this.updateView(true); } } get profile(): IDandName | null | undefined { @@ -125,7 +134,7 @@ export class AppIconComponent implements OnInit, OnDestroy { } this.requestedAnimationFrame = requestAnimationFrame(() => { - this.__updateView(); + this.__updateView(skipIcon); }) } @@ -266,7 +275,13 @@ export class AppIconComponent implements OnInit, OnDestroy { ) .subscribe({ next: (icon) => { - if (iconsToIngore.some((i) => i === icon)) { + if (iconBlobsToIgnore.some((i) => i === icon)) { + icon = ''; + } else if (iconIDsToIgnore.some((i) => icon.includes(i))) { + // TODO: This just checks if the value (blob, URL, etc.) contains + // the SHA1 sum of the icon, which is used in the URL of api icon types. + // This is very unlikely to have false positivies, but this could still + // be done a lot cleaner. icon = ''; } if (icon !== '') { From 2d45a1c7128b08ba69b2d5ae69fd79c2a668980a Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 18 Apr 2024 13:51:05 +0200 Subject: [PATCH 4/7] Fix UI performance issue on Windows --- desktop/angular/src/app/shared/app-icon/app-icon.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/desktop/angular/src/app/shared/app-icon/app-icon.ts b/desktop/angular/src/app/shared/app-icon/app-icon.ts index ccd98329..e62d9899 100644 --- a/desktop/angular/src/app/shared/app-icon/app-icon.ts +++ b/desktop/angular/src/app/shared/app-icon/app-icon.ts @@ -261,6 +261,14 @@ export class AppIconComponent implements OnInit, OnDestroy { case 'api': return of(`${this.httpAPI}/v1/profile/icon/${firstIcon.Value}`); + case 'path': + // TODO: Silently ignore for now. + return of(''); + + case '': + // Icon is not set. + return of(''); + default: console.error(`Icon type ${firstIcon.Type} not yet supported`); } From 21c4fa456be42cd8885135f0a4ce4744886a07b7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 18 Apr 2024 13:51:20 +0200 Subject: [PATCH 5/7] Do not re-evaluate ended connections --- service/firewall/packet_handler.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service/firewall/packet_handler.go b/service/firewall/packet_handler.go index 46cc83f0..766ff2b0 100644 --- a/service/firewall/packet_handler.go +++ b/service/firewall/packet_handler.go @@ -111,12 +111,17 @@ func resetAllConnectionVerdicts() { func resetConnectionVerdict(ctx context.Context, conn *network.Connection) (verdictChanged bool) { tracer := log.Tracer(ctx) - // Remove any active prompt as we settings are being re-evaluated. + // Remove any active prompt as the settings are being re-evaluated. conn.RemovePrompt() conn.Lock() defer conn.Unlock() + // Do not re-evaluate connection that have already ended. + if conn.Ended > 0 { + return false + } + // Update feature flags. if err := conn.UpdateFeatures(); err != nil && !errors.Is(err, access.ErrNotLoggedIn) { tracer.Warningf("filter: failed to update connection feature flags: %s", err) From 0c61f2c35e9b8c221147f977a97cd4ef891a5d13 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 18 Apr 2024 14:24:43 +0200 Subject: [PATCH 6/7] Fix some typescript linter errors --- .../src/app/shared/app-icon/app-icon.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/desktop/angular/src/app/shared/app-icon/app-icon.ts b/desktop/angular/src/app/shared/app-icon/app-icon.ts index e62d9899..826c89c0 100644 --- a/desktop/angular/src/app/shared/app-icon/app-icon.ts +++ b/desktop/angular/src/app/shared/app-icon/app-icon.ts @@ -1,4 +1,3 @@ -import { Min } from './../../../../dist-lib/safing/portmaster-api/lib/netquery.service.d'; import { ChangeDetectionStrategy, ChangeDetectorRef, @@ -19,10 +18,10 @@ import { Record, deepClone, } from '@safing/portmaster-api'; -import { Subscription, map, of, throwError } from 'rxjs'; -import { catchError, switchMap } from 'rxjs/operators'; -import { INTEGRATION_SERVICE, ProcessInfo } from 'src/app/integration'; +import { Subscription, map, of } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; import { AppIconResolver } from './app-icon-resolver'; +import { AppProfile } from 'projects/safing/portmaster-api/src/public-api'; // Interface that must be satisfied for the profile-input // of app-icon. @@ -107,11 +106,11 @@ export class AppIconComponent implements OnInit, OnDestroy { isIgnoredProfile = false; /** If not icon is available, this holds the first - uppercased - letter of the app - name */ - letter: string = ''; + letter = ''; /** @private The background color of the component, based on icon availability and generated by ID */ @HostBinding('style.background-color') - color: string = 'var(--text-tertiary)'; + color = 'var(--text-tertiary)'; constructor( private profileService: AppProfileService, @@ -167,7 +166,7 @@ export class AppIconComponent implements OnInit, OnDestroy { } if (!skipIcon) { - this.tryGetSystemIcon(p); + this.tryGetSystemIcon(); } } else { @@ -204,7 +203,7 @@ export class AppIconComponent implements OnInit, OnDestroy { return null; } - let id = this.profile.ID; + const id = this.profile.ID; if (!id) { return null; } @@ -215,7 +214,7 @@ export class AppIconComponent implements OnInit, OnDestroy { } // otherwise, ID likely contains the source - let [source, ...rest] = id.split('/'); + const [source, ...rest] = id.split('/'); if (rest.length > 0) { return [source, rest.join('/')]; } @@ -229,7 +228,7 @@ export class AppIconComponent implements OnInit, OnDestroy { * Tries to get the application icon form the system. * Requires the app to be running in the electron wrapper. */ - private tryGetSystemIcon(p: IDandName) { + private tryGetSystemIcon() { const sourceAndId = this.getIDAndSource(); if (sourceAndId === null) { return; @@ -240,7 +239,7 @@ export class AppIconComponent implements OnInit, OnDestroy { this.sub = this.profileService .watchAppProfile(sourceAndId[0], sourceAndId[1]) .pipe( - switchMap((profile) => { + switchMap((profile: AppProfile) => { this.updateLetter(profile); if (!!profile.Icons?.length) { From a223250f006da9a3c1c601b2056b927a8dead4bf Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 18 Apr 2024 14:25:21 +0200 Subject: [PATCH 7/7] Improve/fix build system and CI --- .github/workflows/angular.yml | 4 +-- .github/workflows/go.yml | 4 +-- Earthfile | 63 ++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml index 7ca183b8..ee8b30df 100644 --- a/.github/workflows/angular.yml +++ b/.github/workflows/angular.yml @@ -17,7 +17,7 @@ on: jobs: lint: - name: Linter + name: Lint runs-on: ubuntu-latest defaults: run: @@ -56,4 +56,4 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Build angular projects - run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +build-angular + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +angular-release diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 5a604e12..4b3b5257 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -48,7 +48,7 @@ jobs: run: go vet ./... test: - name: Test + name: Test & Build runs-on: ubuntu-latest steps: - uses: earthly/actions-setup@v1 @@ -64,4 +64,4 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Run Go Tests - run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +test-go + run: earthly --ci --remote-cache=ghcr.io/safing/build-cache --push +go-ci diff --git a/Earthfile b/Earthfile index 5acdb828..a6265aee 100644 --- a/Earthfile +++ b/Earthfile @@ -15,14 +15,15 @@ ARG --global outputDir = "./dist" # to GOOS, GOARCH and GOARM when building go binaries. See the +RUST_TO_GO_ARCH_STRING # helper method at the bottom of the file. - ARG --global architectures = "x86_64-unknown-linux-gnu" \ "aarch64-unknown-linux-gnu" \ "x86_64-pc-windows-gnu" - -# Compile errors here: -# "armv7-unknown-linux-gnueabihf" \ -# "arm-unknown-linux-gnueabi" \ + # TODO: Compile errors here: + # "aarch64-pc-windows-gnu" \ + # "x86_64-apple-darwin" \ + # "aarch64-apple-darwin" + # "armv7-unknown-linux-gnueabihf" \ + # "arm-unknown-linux-gnueabi" # Import the earthly rust lib since it already provides some useful # build-targets and methods to initialize the rust toolchain. @@ -84,7 +85,7 @@ go-base: SAVE IMAGE --cache-hint # updates all go dependencies and runs go mod tidy, saving go.mod and go.sum locally. -update-go-deps: +go-update-deps: FROM +go-base RUN go get -u ./.. @@ -100,9 +101,9 @@ mod-tidy: SAVE ARTIFACT go.mod AS LOCAL go.mod SAVE ARTIFACT --if-exists go.sum AS LOCAL go.sum -# build-go runs 'go build ./cmds/...', saving artifacts locally. +# go-build runs 'go build ./cmds/...', saving artifacts locally. # If --CMDS is not set, it defaults to building portmaster-start, portmaster-core and hub -build-go: +go-build: FROM +go-base # Arguments for cross-compilation. @@ -136,10 +137,10 @@ build-go: # Test one or more go packages. # Test are always run as -short, as "long" tests require a full desktop system. -# Run `earthly +test-go` to test all packages -# Run `earthly +test-go --PKG="service/firewall"` to only test a specific package. -# Run `earthly +test-go --TESTFLAGS="-args arg1"` to add custom flags to go test (-args in this case) -test-go: +# Run `earthly +go-test` to test all packages +# Run `earthly +go-test --PKG="service/firewall"` to only test a specific package. +# Run `earthly +go-test --TESTFLAGS="-args arg1"` to add custom flags to go test (-args in this case) +go-test: FROM +go-base ARG GOOS=linux @@ -155,16 +156,16 @@ test-go: RUN --no-cache go test -cover -short ${pkg} ${TESTFLAGS} END -test-go-all-platforms: +go-test-all: FROM ${work_image} FOR arch IN ${architectures} DO +RUST_TO_GO_ARCH_STRING --rustTarget="${arch}" - BUILD +test-go --GOARCH="${GOARCH}" --GOOS="${GOOS}" --GOARM="${GOARM}" + BUILD +go-test --GOARCH="${GOARCH}" --GOOS="${GOOS}" --GOARM="${GOARM}" END # Builds portmaster-start, portmaster-core, hub and notifier for all supported platforms -build-go-release: +go-release: FROM ${work_image} FOR arch IN ${architectures} @@ -178,14 +179,19 @@ build-go-release: RUN echo "Failed to extract GOOS for ${arch}"; exit 1 END - BUILD +build-go --GOARCH="${GOARCH}" --GOOS="${GOOS}" --GOARM="${GOARM}" + BUILD +go-build --GOARCH="${GOARCH}" --GOOS="${GOOS}" --GOARM="${GOARM}" END # Builds all binaries from the cmds/ folder for linux/windows AMD64 # Most utility binaries are never needed on other platforms. -build-utils: - BUILD +build-go --CMDS="" --GOARCH=amd64 --GOOS=linux - BUILD +build-go --CMDS="" --GOARCH=amd64 --GOOS=windows +go-build-utils: + BUILD +go-build --CMDS="" --GOARCH=amd64 --GOOS=linux + BUILD +go-build --CMDS="" --GOARCH=amd64 --GOOS=windows + +# All targets that should run in CI for go. +go-ci: + BUILD +go-release + BUILD +go-test # Prepares the angular project by installing dependencies angular-deps: @@ -361,7 +367,7 @@ tauri-src: # Explicitly cache here. SAVE IMAGE --cache-hint -build-tauri: +tauri-build: FROM +tauri-src ARG --required target @@ -383,7 +389,7 @@ build-tauri: # the app. Make sure we copy portmaster-start and portmaster-core in all architectures supported. # See documentation for externalBins for more information on how tauri searches for the binaries. - COPY (+build-go/output --GOOS="${GOOS}" --CMDS="portmaster-start portmaster-core" --GOARCH="${GOARCH}" --GOARM="${GOARM}") /tmp/gobuild + COPY (+go-build/output --GOOS="${GOOS}" --CMDS="portmaster-start portmaster-core" --GOARCH="${GOARCH}" --GOARM="${GOARM}") /tmp/gobuild # Place them in the correct folder with the rust target tripple attached. FOR bin IN $(ls /tmp/gobuild) @@ -445,11 +451,11 @@ tauri-release: ARG bundle="none" FOR arch IN ${architectures} - BUILD +build-tauri --target="${arch}" --bundle="${bundle}" + BUILD +tauri-build --target="${arch}" --bundle="${bundle}" END -build-all: - BUILD +build-go-release +build: + BUILD +go-release BUILD +angular-release BUILD +tauri-release @@ -493,14 +499,17 @@ RUST_TO_GO_ARCH_STRING: LET goos="" IF [ -z "${rustTarget##*linux*}" ] SET goos="linux" - ELSE + ELSE IF [ -z "${rustTarget##*windows*}" ] SET goos="windows" + ELSE IF [ -z "${rustTarget##*darwin*}" ] + SET goos="darwin" + ELSE + RUN echo "GOOS not detected"; \ + exit 1; END - LET goarch="" LET goarm="" - IF [ -z "${rustTarget##*x86_64*}" ] SET goarch="amd64" ELSE IF [ -z "${rustTarget##*arm*}" ]