poll

package
v0.32.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package poll implements the GitLab cron-polling event dispatch loop. It discovers events from the GitLab API, converts them to NormalizedEvents, routes them through the dispatch core, and triggers child pipelines for matched stages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GenerateChildPipelineFromFile

func GenerateChildPipelineFromFile(dispatchesPath, outputPath string) error

GenerateChildPipelineFromFile reads a dispatches JSON file and writes the corresponding child pipeline YAML to outputPath. It is used by the CLI "fullsend poll generate-child-pipeline" subcommand.

Types

type Dispatch

type Dispatch struct {
	Stage           string `json:"stage"`
	EventType       string `json:"event_type"`
	EventPayloadB64 string `json:"event_payload_b64"`
	ResourceKey     string `json:"resource_key"`
}

Dispatch represents a single child pipeline dispatch record.

type EventNote

type EventNote struct {
	ID           int    `json:"id"`
	NoteableType string `json:"noteable_type"`
	NoteableIID  int    `json:"noteable_iid"`
	Body         string `json:"body"`
}

EventNote is the embedded note object in a project event.

type GitLabClient

type GitLabClient interface {
	ListIssuesUpdatedSince(ctx context.Context, owner, repo string, since time.Time) ([]Issue, error)
	ListMergeRequestsUpdatedSince(ctx context.Context, owner, repo string, since time.Time) ([]MergeRequest, error)
	// ListProjectEvents returns events matching targetType (use lowercase
	// "note" for the request param). The after parameter is date-only
	// (ISO 8601 date, exclusive): implementations must widen to at least
	// since.AddDate(0,0,-1) and apply client-side timestamp filtering.
	ListProjectEvents(ctx context.Context, owner, repo string, targetType string, after time.Time) ([]ProjectEvent, error)
	// ListIssueNotes MUST return notes in ascending created_at order.
	ListIssueNotes(ctx context.Context, owner, repo string, issueIID int) ([]Note, error)
	ListMergeRequestNotes(ctx context.Context, owner, repo string, mrIID int) ([]Note, error)
	// ListResourceLabelEvents MUST return events in ascending ID order
	// (the poller iterates in reverse to find the most recent "add").
	ListResourceLabelEvents(ctx context.Context, owner, repo string, issueIID int) ([]ResourceLabelEvent, error)
	GetCIVariable(ctx context.Context, owner, repo, name string) (string, error)
	// UpdateCIVariable creates or updates a CI variable. GitLab CI/CD
	// variable values are capped at 10,000 characters.
	UpdateCIVariable(ctx context.Context, owner, repo, name, value string, protected bool) error
	GetAuthenticatedUser(ctx context.Context) (string, error)
	// CreateNoteAwardEmoji adds an emoji reaction. noteableType must be
	// "Issue" or "MergeRequest" to select the correct API endpoint.
	CreateNoteAwardEmoji(ctx context.Context, owner, repo string, noteableType string, noteableIID, noteID int, emoji string) error
	GetIssue(ctx context.Context, owner, repo string, issueIID int) (*Issue, error)
	// GetMemberAccessLevel returns the access level for a project member.
	// Implementations MUST use the /members/all/:user_id endpoint to
	// include inherited (group-level) membership, not /members/:user_id
	// which only returns direct members.
	GetMemberAccessLevel(ctx context.Context, owner, repo string, userID int) (int, error)
	GetProjectPath(ctx context.Context, projectID int) (string, error)
}

GitLabClient defines the GitLab API surface the poller requires. This interface is separate from forge.Client because the poller needs GitLab-specific methods (label events, project events) that are not part of the forge-neutral abstraction. Phase 1 wiring will provide a concrete type that satisfies this interface, backed by the forge.Client credential and HTTP plumbing.

All List* methods MUST exhaust pagination (per_page=100, follow x-next-page) and return the complete result set. Returning only page 1 (GitLab default: 20 items) causes silent event loss.

type Issue

type Issue struct {
	IID       int       `json:"iid"`
	Title     string    `json:"title"`
	State     string    `json:"state"`
	Labels    []string  `json:"labels"`
	Author    UserRef   `json:"author"`
	UpdatedAt time.Time `json:"updated_at"`
}

Issue represents a GitLab issue as returned by the API. Author is a nested object in the GitLab v4 response.

type LabelAuthor

type LabelAuthor struct {
	ID       int
	Username string
	IsBot    bool
}

LabelAuthor identifies who applied a label.

type LabelState

type LabelState map[int][]string

LabelState tracks previously-seen labels per issue IID.

type MergeRequest

type MergeRequest struct {
	IID             int       `json:"iid"`
	Title           string    `json:"title"`
	State           string    `json:"state"`
	Labels          []string  `json:"labels"`
	SourceProjectID int       `json:"source_project_id"`
	TargetProjectID int       `json:"target_project_id"`
	SourceBranch    string    `json:"source_branch"`
	TargetBranch    string    `json:"target_branch"`
	Author          UserRef   `json:"author"`
	MergeUser       UserRef   `json:"merge_user"`
	MergedBy        UserRef   `json:"merged_by"`
	MergedAt        time.Time `json:"merged_at"`
	UpdatedAt       time.Time `json:"updated_at"`
}

MergeRequest represents a GitLab merge request as returned by the API. Fields are derived from nested API objects (author, merge_user); GitLab does not expose flat author_id/merged_by_id fields on MRs.

type Note

type Note struct {
	ID        int       `json:"id"`
	Body      string    `json:"body"`
	Author    UserRef   `json:"author"`
	CreatedAt time.Time `json:"created_at"`
}

Note represents a GitLab note (comment) on an issue or MR.

type Options

type Options struct {
	SlashCommandsOnly bool
	BotUserID         int
	OutputPath        string
	GitLabURL         string
}

Options configures the poller.

type Poller

type Poller struct {
	// contains filtered or unexported fields
}

Poller discovers GitLab events and dispatches agent stages.

func New

func New(client GitLabClient, router dispatch.EventRouter, projectPath string, opts Options) *Poller

New creates a Poller for the given project.

func (*Poller) Run

func (p *Poller) Run(ctx context.Context) error

Run executes a single poll cycle: read watermark, discover events, filter, deduplicate, convert to NormalizedEvent, route, dispatch, and advance the watermark.

type ProjectEvent

type ProjectEvent struct {
	ID        int       `json:"id"`
	Author    UserRef   `json:"author"`
	Note      EventNote `json:"note"`
	CreatedAt time.Time `json:"created_at"`
}

ProjectEvent represents an event from the GitLab Events API.

type ResourceLabelEvent

type ResourceLabelEvent struct {
	ID     int    `json:"id"`
	Action string `json:"action"`
	Label  struct {
		Name string `json:"name"`
	} `json:"label"`
	User UserRef `json:"user"`
}

ResourceLabelEvent represents a label change event from the GitLab API.

type RoutableEvent

type RoutableEvent struct {
	Type            string
	IID             int
	UpdatedAt       time.Time
	Labels          []string // full label set at event time
	ChangedLabel    string   // the label that was added/removed (label events only)
	NoteBody        string
	NoteID          int
	NoteAuthorID    int
	NoteAuthorLogin string
	IsBot           bool
	MRSource        int
	MRTarget        int
	SourceBranch    string
	TargetBranch    string
	MRAuthorID      int
	MRAuthorLogin   string
	MergedByLogin   string
}

RoutableEvent is an intermediate representation of a detected change, produced by event discovery and consumed by the poll loop for NormalizedEvent conversion and dispatch.

func (RoutableEvent) Key

func (e RoutableEvent) Key() string

Key returns a deduplication key for the event. Note events use their globally unique NoteID. Label events include UpdatedAt so that a remove-then-re-add of the same label produces a distinct key. MR merge events use type+IID+timestamp.

type UserRef

type UserRef struct {
	ID       int    `json:"id"`
	Username string `json:"username"`
	Bot      bool   `json:"bot"`
}

UserRef is a minimal user reference from the GitLab API. The Bot field is not present in all API responses (notably the Notes API author object omits it). Use isBotEvent() for reliable bot detection, which combines the API field, botUserID, and username-pattern heuristics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL