// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package build_event_stream;

option java_package = "com.google.devtools.build.lib.buildeventstream";
option java_outer_classname = "BuildEventStreamProtos";

// Identifier for a build event. It is deliberately structured to also provide
// information about which build target etc the event is related to.
//
// Events are chained via the event id as follows: each event has an id and a
// set of ids of children events such that apart from the initial event each
// event has an id that is mentioned as child id in an earlier event and a build
// invocation is complete if and only if all direct and indirect children of the
// initial event have been posted.
message BuildEventId {
  // Generic identifier for a build event. This is the default type of
  // BuildEventId, but should not be used outside testing; nevertheless,
  // tools should handle build events with this kind of id gracefully.
  message UnknownBuildEventId {
    string details = 1;
  }

  // Identifier of an event reporting progress. Those events are also used to
  // chain in events that come early.
  message ProgressId {
    // Unique identifier. No assumption should be made about how the ids are
    // assigned; the only meaningful operation on this field is test for
    // equality.
    int32 opaque_count = 1;
  }

  // Identifier of an event indicating the beginning of a build; this will
  // normally be the first event.
  message BuildStartedId {
  }

  // Identifier of an event indicating that a target pattern has been expanded
  // further.
  message PatternExpandedId {
    repeated string pattern = 1;
  }

  // Identifier of an event indicating that a target was built completely; this
  // does not include running the test if the target is a test target.
  message TargetCompletedId {
    string label = 1;
  }

  // Identifier of an event reporting that an action was completed (not all
  // actions are reported, only the onces that can be considered important;
  // this includes all failed actions).
  message ActionCompletedId {
    string primary_output = 1;
  }

  // Identifier of an event reporting the summary of a test.
  message TestSummaryId {
    string label = 1;
  }

  oneof id {
    UnknownBuildEventId unknown = 1;
    ProgressId progress = 2;
    BuildStartedId started = 3;
    PatternExpandedId pattern = 4;
    TargetCompletedId target_completed = 5;
    ActionCompletedId action_completed = 6;
    TestSummaryId test_summary = 7;
  }
}

// Payload of an event summarizing the progress of the build so far. Those
// events are also used to be parents of events where the more logical parent
// event cannot be posted yet as the needed information is not yet complete.
message Progress {
}

// Payload of an event indicating that an expected event will not come, as
// the build is aborted prematurely for some reason.
message Aborted {
  enum AbortReason {
    UNKNOWN = 0;

    // The user requested the build to be aborted (e.g., by hitting Ctl-C).
    USER_INTERRUPTED = 1;

    // The build or target was aborted as a timeout was exceeded.
    TIME_OUT = 2;

    // The build or target was aborted as some remote environment (e.g., for
    // remote execution of actions) was not available in the expected way.
    REMOTE_ENVIRONMENT_FAILURE = 3;

    // Failure due to reasons entirely internal to the build tool, e.g.,
    // running out of memory.
    INTERNAL = 4;
  }
  AbortReason reason = 1;

  // A human readable description with more details about there reason, where
  // available and useful.
  string description = 2;
}

// Payload of an event indicating the beginning of a new build. Usually, events
// of those type start a new build-event stream. The target pattern requested
// to be build is contained in one of the announced child events; it is an
// invariant that precisely one of the announced child events has a non-empty
// target pattern.
message BuildStarted {
  string uuid = 1;

  // Start of the build in ms since the epoche.
  int64 start_time_milis = 2;

  // Version of the build tool that is running.
  string build_tool_version = 3;

  // A human-readable description of all the non-default option settings
  string options_description = 4;

  // The name of the command that the user invoked.
  string command = 5;

  // The working directory from which the build tool was invoked.
  string working_directory = 6;

  // The directory of the workspace.
  string workspace_directory = 7;
}

// Payload of the event indicating the expansion of a target pattern.
// The main information is in the chaining part: the id will contain the
// target pattern that was expanded and the children id will contain the
// target or target pattern it was expanded to.
message PatternExpanded {
}

message File {
  // identifier indicating the nature of the file (e.g., "stdout", "stderr")
  string name = 1;

  oneof file {
    // A location where the contents of the file can be found.
    string uri = 2;
    // The conents of the file, if they are guaranteed to be short.
    bytes contents = 3;
  }
}

// Payload of the event indicating the completion of an action. The main purpose
// of posting those events is to provide details on the root cause for a target
// failing; however, consumers of the build-event protocol should not assume
// that only failed actions are posted.
message ActionExecuted {
  bool success = 1;

  // The exit code of the action, if it is available.
  int32 exit_code = 2;

  // Location where to find the standard output of the action
  // (e.g., a file path).
  File stdout = 3;

  // Location where to find the standard error of the action
  // (e.g., a file path).
  File stderr = 4;

  // Optionally, the label of the owner of the action, for reference.
  string label = 5;
}

// Payload of the event indicating the completion of a target. The target is
// specified in the id. If the target failed the root causes are provided as
// children events.
message TargetComplete {
  bool success = 1;
}

// Payload of the event summarizing a test.
// TODO(aehlig): extend event with additional information as soon as we known
// which additional information we need for test summaries.
message TestSummary {
  // Total number of runs
  int32 total_run_count = 1;

  // Path to logs of passed runs.
  repeated File passed = 3;

  // Path to logs of failed runs;
  repeated File failed = 4;
}

// Message describing a build event. Events will have an identifier that
// is unique within a given build invocation; they also announce follow-up
// events as children. More details, which are specific to the kind of event
// that is observed, is provided in the payload. More options for the payload
// might be added in the future.
message BuildEvent {
  BuildEventId id = 1;
  repeated BuildEventId children = 2;
  oneof payload {
    Progress progress = 3;
    Aborted aborted = 4;
    BuildStarted started = 5;
    PatternExpanded expanded = 6;
    ActionExecuted action = 7;
    TargetComplete completed = 8;
    TestSummary test_summary = 9;
  };
}
