syntax = "proto3";

// If you make any changes make sure you run: make regenerate-proto

package gitlab.agent.gitops.rpc;

option go_package = "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v16/internal/module/gitops/rpc";

import "internal/tool/grpctool/automata/automata.proto";
//import "github.com/envoyproxy/protoc-gen-validate/blob/master/validate/validate.proto";
import "validate/validate.proto";

// GitRef in the repository to fetch manifests from.
message GitRefCF {
  oneof ref {
    option (validate.required) = true;

    // A Git tag name, without `refs/tags/`
    string tag = 1 [json_name = "tag", (validate.rules).string.min_bytes = 1];
    // A Git branch name, without `refs/heads/`
    string branch = 2 [json_name = "branch", (validate.rules).string.min_bytes = 1];
    // A Git commit SHA
    string commit = 3 [json_name = "commit", (validate.rules).string.min_bytes = 1];
  }
}

message PathCF {
  oneof path {
    option (validate.required) = true;

    // Glob to use to scan for files in the repository.
    // Directories with names starting with a dot are ignored.
    // See https://github.com/bmatcuk/doublestar#about and
    // https://pkg.go.dev/github.com/bmatcuk/doublestar/v2#Match for
    // globbing rules.
    string glob = 1 [json_name = "glob", (validate.rules).string.min_bytes = 1];
    // A single file to fetch.
    string file = 2 [json_name = "file", (validate.rules).string.min_bytes = 1];
  }
}

message ObjectsToSynchronizeRequest {
  // Project to fetch Kubernetes object manifests from.
  // e.g. gitlab-org/cluster-integration/gitlab-agent
  string project_id = 1 [(validate.rules).string.min_bytes = 1];
  // Ref within the project to fetch Kubernetes object manifest from.
  GitRefCF ref = 4;
  // Last processed commit id. Optional.
  // Server will only send objects if the last commit on the branch is
  // a different one. If a connection breaks, this allows to resume
  // the stream without sending the same data again.
  string commit_id = 2;
  // A list of paths inside of the project to scan
  // for .yaml/.yml/.json manifest files.
  repeated PathCF paths = 3 [(validate.rules).repeated.min_items = 1];
}

message ObjectsToSynchronizeResponse {
  // First message of the stream.
  message Header {
    // Commit id of the manifest repository.
    // Can be used to resume connection from where it dropped.
    string commit_id = 1 [(validate.rules).string.min_bytes = 1];
    // Numeric project id of the manifest repository.
    int64 project_id = 2;
  }
  // Subsequent messages of the stream.
  message Object {
    // Source of the YAML e.g. file name.
    // Several subsequent messages may contain the same source string.
    // That means data should be accumulated to form the whole blob of data.
    string source = 1 [(validate.rules).string.min_bytes = 1];

    // YAML object manifest.
    // Might be partial data, see comment for source.
    bytes data = 2;
  }
  // Last message of the stream.
  message Trailer {
  }
  oneof message {

    option (grpctool.automata.first_allowed_field) = 1;
    option (grpctool.automata.first_allowed_field) = -1; // EOF means there is nothing to do
    option (validate.required) = true;

    Header header = 1 [
      (grpctool.automata.next_allowed_field) = 2,
      (grpctool.automata.next_allowed_field) = 3,
      (validate.rules).message.required = true
    ];
    Object object = 2 [
      (grpctool.automata.next_allowed_field) = 2,
      (grpctool.automata.next_allowed_field) = 3,
      (validate.rules).message.required = true
    ];
    Trailer trailer = 3 [
      (grpctool.automata.next_allowed_field) = -1,
      (validate.rules).message.required = true
    ];
  }
}

service Gitops {
  // Fetch Kubernetes objects to synchronize with the cluster.
  // Server closes the stream when it's done transmitting the full batch of
  // objects. New request should be made after that to get the next batch.
  rpc GetObjectsToSynchronize (ObjectsToSynchronizeRequest) returns (stream ObjectsToSynchronizeResponse) {
  }
}
