@@ -36,20 +36,20 @@ var ociHandleUploadsFunc = oci.HandleUploads
3636
3737// initNewRelic initializes the New Relic application
3838// Returns nil if APM_CONTROL_NR_LICENSE_KEY is not set (silent no-op mode)
39- func initNewRelic () * newrelic.Application {
39+ func initNewRelic (ctx context. Context ) * newrelic.Application {
4040 licenseKey := config .GetNRAgentLicenseKey ()
4141 if licenseKey == "" {
42- _ , _ = fmt . Fprintln ( os . Stderr , "::warn:: Failed to init New Relic - missing license key" )
42+ logging . Warn ( ctx , "Failed to init New Relic - missing license key" )
4343 return nil
4444 }
4545
4646 // Hardcode staging environment
4747 err := config .SetNRAgentHost ()
4848 if err != nil {
49- _ , _ = fmt . Fprintf ( os . Stderr , "::warn:: Failed to init New Relic, missing host: %v\n " , err )
49+ logging . Warnf ( ctx , "Failed to init New Relic, missing host: %v" , err )
5050 return nil
5151 }
52- fmt . Println ( "::notice:: Using New Relic staging environment" )
52+ logging . Notice ( ctx , " Using New Relic staging environment" )
5353
5454 app , err := newrelic .NewApplication (
5555 newrelic .ConfigAppName ("agent-metadata-action" ),
@@ -64,34 +64,43 @@ func initNewRelic() *newrelic.Application {
6464 )
6565
6666 if err != nil {
67- _ , _ = fmt . Fprintf ( os . Stderr , "::warn:: Failed to init New Relic: %v\n " , err )
67+ logging . Warnf ( ctx , "Failed to init New Relic: %v" , err )
6868 return nil
6969 }
7070
71- fmt . Println ( "::notice:: New Relic APM enabled - waiting for connection..." )
71+ logging . Notice ( ctx , " New Relic APM enabled - waiting for connection..." )
7272
7373 // Wait for the app to connect (max 10 seconds)
7474 if err := app .WaitForConnection (10 * time .Second ); err != nil {
75- fmt . Printf ( "::warn:: New Relic connection timeout: %v - will try to send data anyway\n " , err )
75+ logging . Warnf ( ctx , " New Relic connection timeout: %v - will try to send data anyway" , err )
7676 } else {
77- fmt . Println ( "::notice:: New Relic connected successfully" )
77+ logging . Notice ( ctx , " New Relic connected successfully" )
7878 }
7979
8080 return app
8181}
8282
8383func main () {
84- nrApp := initNewRelic ()
84+ // Create base context for early logging
85+ ctx := context .Background ()
8586
86- if err := run ( nrApp ); err != nil {
87- _ , _ = fmt . Fprintf ( os . Stderr , "::error::%v \n " , err )
88- os . Exit ( 1 )
89- }
87+ nrApp := initNewRelic ( ctx )
88+
89+ // Run the action
90+ err := run ( nrApp )
9091
92+ // Ensure New Relic shuts down gracefully (even on error)
93+ // Must happen BEFORE os.Exit() since os.Exit bypasses defers
9194 if nrApp != nil {
92- fmt . Println ( "::notice:: Shutting down New Relic - waiting up to 15 seconds to send data..." )
95+ logging . Notice ( ctx , " Shutting down New Relic - waiting up to 15 seconds to send data..." )
9396 nrApp .Shutdown (15 * time .Second )
94- fmt .Println ("::notice::New Relic shutdown complete" )
97+ logging .Notice (ctx , "New Relic shutdown complete" )
98+ }
99+
100+ // Exit with appropriate code
101+ if err != nil {
102+ logging .Errorf (ctx , "%v" , err )
103+ os .Exit (1 )
95104 }
96105}
97106
@@ -134,16 +143,31 @@ func run(nrApp *newrelic.Application) error {
134143func validateEnvironment (ctx context.Context ) (workspace string , token string , err error ) {
135144 workspace = config .GetWorkspace ()
136145 if workspace == "" {
137- return "" , "" , fmt .Errorf ("GITHUB_WORKSPACE is required but not set" )
146+ err := fmt .Errorf ("GITHUB_WORKSPACE is required but not set" )
147+ logging .NoticeErrorWithCategory (ctx , err , "environment.validation" , map [string ]interface {}{
148+ "error.operation" : "validate_workspace" ,
149+ "error.field" : "GITHUB_WORKSPACE" ,
150+ })
151+ return "" , "" , err
138152 }
139153
140154 if _ , err := os .Stat (workspace ); err != nil {
141- return "" , "" , fmt .Errorf ("workspace directory does not exist: %s" , workspace )
155+ noticeErr := fmt .Errorf ("workspace directory does not exist: %s" , workspace )
156+ logging .NoticeErrorWithCategory (ctx , noticeErr , "environment.validation" , map [string ]interface {}{
157+ "error.operation" : "validate_workspace" ,
158+ "workspace.path" : workspace ,
159+ })
160+ return "" , "" , noticeErr
142161 }
143162
144163 token = config .GetToken ()
145164 if token == "" {
146- return "" , "" , fmt .Errorf ("NEWRELIC_TOKEN is required but not set" )
165+ err := fmt .Errorf ("NEWRELIC_TOKEN is required but not set" )
166+ logging .NoticeErrorWithCategory (ctx , err , "environment.validation" , map [string ]interface {}{
167+ "error.operation" : "validate_token" ,
168+ "error.field" : "NEWRELIC_TOKEN" ,
169+ })
170+ return "" , "" , err
147171 }
148172
149173 logging .Notice (ctx , "Environment validated successfully" )
@@ -152,7 +176,7 @@ func validateEnvironment(ctx context.Context) (workspace string, token string, e
152176
153177// runAgentFlow handles the agent repository workflow
154178func runAgentFlow (ctx context.Context , client metadataClient , workspace , agentType , agentVersion string ) error {
155- logging .Debug (ctx , "Running agent repository flow" )
179+ logging .Debugf (ctx , "Running agent repository flow for %s version %s" , agentType , agentVersion )
156180
157181 // Check for .fleetControl directory
158182 fleetControlPath := filepath .Join (workspace , config .GetRootFolderForAgentRepo ())
@@ -161,15 +185,28 @@ func runAgentFlow(ctx context.Context, client metadataClient, workspace, agentTy
161185 }
162186
163187 // Load configuration definitions (required)
164- configs , err := loader .ReadConfigurationDefinitions (workspace )
188+ configs , err := loader .ReadConfigurationDefinitions (ctx , workspace )
165189 if err != nil {
190+ logging .NoticeErrorWithCategory (ctx , err , "configuration.load" , map [string ]interface {}{
191+ "error.operation" : "load_configuration_definitions" ,
192+ "agent.type" : agentType ,
193+ "agent.version" : agentVersion ,
194+ "workflow.type" : "agent" ,
195+ })
166196 return fmt .Errorf ("failed to read configuration definitions: %w" , err )
167197 }
168198 logging .Noticef (ctx , "Loaded %d configuration definitions" , len (configs ))
169199
170200 // Load agent control definitions (optional)
171- agentControl , err := loader .ReadAgentControlDefinitions (workspace )
201+ agentControl , err := loader .ReadAgentControlDefinitions (ctx , workspace )
172202 if err != nil {
203+ logging .NoticeErrorWithCategory (ctx , err , "configuration.load" , map [string ]interface {}{
204+ "error.operation" : "load_agent_control_definitions" ,
205+ "agent.type" : agentType ,
206+ "agent.version" : agentVersion ,
207+ "workflow.type" : "agent" ,
208+ "error.severity" : "warning" , // Graceful error
209+ })
173210 logging .Warnf (ctx , "Unable to load agent control definitions: %v - continuing without them" , err )
174211 agentControl = nil
175212 } else {
@@ -183,21 +220,38 @@ func runAgentFlow(ctx context.Context, client metadataClient, workspace, agentTy
183220 AgentControlDefinitions : agentControl ,
184221 }
185222
186- printJSON ("Agent Metadata" , metadata )
223+ printJSON (ctx , "Agent Metadata" , metadata )
187224
188225 // Step 1: Send to metadata service
189226 if err := client .SendMetadata (ctx , agentType , agentVersion , & metadata ); err != nil {
227+ logging .NoticeErrorWithCategory (ctx , err , "metadata.send" , map [string ]interface {}{
228+ "error.operation" : "send_metadata" ,
229+ "agent.type" : agentType ,
230+ "agent.version" : agentVersion ,
231+ "workflow.type" : "agent" ,
232+ })
190233 return fmt .Errorf ("failed to send metadata for %s: %w" , agentType , err )
191234 }
192235
193236 ociConfig , err := oci .LoadConfig ()
194237 if err != nil {
238+ logging .NoticeErrorWithCategory (ctx , err , "oci.configuration" , map [string ]interface {}{
239+ "error.operation" : "load_oci_config" ,
240+ "agent.type" : agentType ,
241+ "agent.version" : agentVersion ,
242+ })
195243 return fmt .Errorf ("error loading OCI config: %w" , err )
196244 }
197245
198246 // Step 2: Upload binaries
199- uploadResults , err := ociHandleUploadsFunc (& ociConfig , workspace , agentType , agentVersion )
247+ uploadResults , err := ociHandleUploadsFunc (ctx , & ociConfig , workspace , agentType , agentVersion )
200248 if err != nil {
249+ logging .NoticeErrorWithCategory (ctx , err , "oci.upload" , map [string ]interface {}{
250+ "error.operation" : "upload_binaries" ,
251+ "oci.registry" : ociConfig .Registry ,
252+ "agent.type" : agentType ,
253+ "agent.version" : agentVersion ,
254+ })
201255 return fmt .Errorf ("binary upload failed: %w" , err )
202256 }
203257
@@ -225,7 +279,7 @@ func runAgentFlow(ctx context.Context, client metadataClient, workspace, agentTy
225279 return fmt .Errorf ("NEWRELIC_TOKEN is required for artifact signing" )
226280 }
227281
228- if err := sign .SignArtifacts (successfulUploads , ociConfig .Registry , token , repoName , agentVersion ); err != nil {
282+ if err := sign .SignArtifacts (ctx , successfulUploads , ociConfig .Registry , token , repoName , agentVersion ); err != nil {
229283 return fmt .Errorf ("artifact signing failed: %w" , err )
230284 }
231285 } else {
@@ -242,8 +296,12 @@ func runDocsFlow(ctx context.Context, client metadataClient) error {
242296 logging .Debug (ctx , "Running documentation flow" )
243297
244298 // Load metadata from changed MDX files
245- metadataList , err := loader .LoadMetadataForDocs ()
299+ metadataList , err := loader .LoadMetadataForDocs (ctx )
246300 if err != nil {
301+ logging .NoticeErrorWithCategory (ctx , err , "docs.load" , map [string ]interface {}{
302+ "error.operation" : "load_metadata_from_docs" ,
303+ "workflow.type" : "docs" ,
304+ })
247305 return fmt .Errorf ("failed to load metadata from docs: %w" , err )
248306 }
249307
@@ -258,7 +316,13 @@ func runDocsFlow(ctx context.Context, client metadataClient) error {
258316 successCount := 0
259317 for _ , entry := range metadataList {
260318 if err := sendDocsMetadata (ctx , client , entry ); err != nil {
261- logging .Warnf (ctx , "Failed to send metadata for %s: %v" , entry .AgentType , err )
319+ logging .NoticeErrorWithCategory (ctx , err , "docs.send" , map [string ]interface {}{
320+ "error.operation" : "send_docs_metadata" ,
321+ "agent.type" : entry .AgentType ,
322+ "workflow.type" : "docs" ,
323+ "error.severity" : "warning" , // Graceful error
324+ })
325+ logging .Errorf (ctx , "Failed to send metadata for %s: %v" , entry .AgentType , err )
262326 continue
263327 }
264328 successCount ++
@@ -276,7 +340,7 @@ func sendDocsMetadata(ctx context.Context, client metadataClient, entry loader.M
276340 Metadata : entry .AgentMetadataFromDocs ,
277341 }
278342
279- printJSON (fmt .Sprintf ("Docs Metadata (%s %s)" , entry .AgentType , version ), entry .AgentMetadataFromDocs )
343+ printJSON (ctx , fmt .Sprintf ("Docs Metadata (%s %s)" , entry .AgentType , version ), entry .AgentMetadataFromDocs )
280344
281345 if err := client .SendMetadata (ctx , entry .AgentType , version , & metadata ); err != nil {
282346 return err
@@ -287,11 +351,11 @@ func sendDocsMetadata(ctx context.Context, client metadataClient, entry loader.M
287351}
288352
289353// printJSON marshals data to JSON and prints it with a debug annotation
290- func printJSON (label string , data any ) {
354+ func printJSON (ctx context. Context , label string , data any ) {
291355 jsonData , err := json .MarshalIndent (data , "" , " " )
292356 if err != nil {
293- fmt . Printf ( "::debug:: Failed to marshal %s: %v\n " , label , err )
357+ logging . Debugf ( ctx , " Failed to marshal %s: %v" , label , err )
294358 return
295359 }
296- fmt . Printf ( "::debug:: %s: %s\n " , label , string (jsonData ))
360+ logging . Debugf ( ctx , " %s: %s" , label , string (jsonData ))
297361}
0 commit comments