package packaging import ( "context" "errors" "fmt" "os" "sync" "github.com/fatih/color" "github.com/mitchellh/gon/notarize" "github.com/mitchellh/gon/staple" "github.com/rs/zerolog/log" ) func notarizePkg(pkgPath string) error { username, ok := os.LookupEnv("AC_USERNAME") if !ok { return errors.New("AC_USERNAME must be set in environment") } password, ok := os.LookupEnv("AC_PASSWORD") if !ok { return errors.New("AC_PASSWORD must be set in environment") } info, err := notarize.Notarize( context.Background(), ¬arize.Options{ File: pkgPath, BundleId: "com.fleetdm.orbit", Username: username, Password: password, Status: &statusHuman{ Lock: &sync.Mutex{}, }, }, ) if err != nil { return fmt.Errorf("notarize: %w", err) } log.Info().Str("logs", info.LogFileURL).Msg("notarization completed") if err := staple.Staple(context.Background(), &staple.Options{File: pkgPath}); err != nil { return fmt.Errorf("staple notarization: %w", err) } return nil } // This status plugin copied from // https://github.com/mitchellh/gon/blob/v0.2.3/cmd/gon/status_human.go since it // is not exposed from the gon library. // statusHuman implements notarize.Status and outputs information to // the CLI for human consumption. type statusHuman struct { Prefix string Lock *sync.Mutex lastStatus string } func (s *statusHuman) Submitting() { s.Lock.Lock() defer s.Lock.Unlock() color.New().Fprintf(os.Stdout, " %sSubmitting file for notarization...\n", s.Prefix) } func (s *statusHuman) Submitted(uuid string) { s.Lock.Lock() defer s.Lock.Unlock() color.New().Fprintf(os.Stdout, " %sSubmitted. Request UUID: %s\n", s.Prefix, uuid) color.New().Fprintf( os.Stdout, " %sWaiting for results from Apple. This can take minutes to hours.\n", s.Prefix) } func (s *statusHuman) Status(info notarize.Info) { s.Lock.Lock() defer s.Lock.Unlock() if info.Status != s.lastStatus { s.lastStatus = info.Status color.New().Fprintf(os.Stdout, " %sStatus: %s\n", s.Prefix, info.Status) } }