github

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package github reads the repository state that workflow files cannot tell us about: which secrets, variables and environments actually exist.

Every lookup here can legitimately fail because the user's token lacks a permission. That is the normal case, not an exception: listing secrets needs admin rights on the repository, which the typical user does not have. So each result carries its own Access status, and a scope that could not be read is reported as UNKNOWN rather than assumed empty. Assuming empty would produce "missing secret" findings for secrets that exist, which is the one mistake the product cannot afford.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindRoot

func FindRoot(dir string) string

FindRoot returns the repository root for dir, falling back to dir itself when there is no git repository. Workflow files are looked up from there.

Types

type Access

type Access int

Access says whether a scope could be read.

const (
	// AccessOK means the listing is complete and can be trusted.
	AccessOK Access = iota
	// AccessDenied means the token lacks the permission. GitHub answers 403 or,
	// for organisation scopes, 404. Both mean the same thing to us.
	AccessDenied
	// AccessMissing means the scope does not exist, for example an environment
	// that is referenced by a job but not configured in the repository.
	AccessMissing
	// AccessError means the call failed for another reason: network, rate limit,
	// server error.
	AccessError
	// AccessSkipped means the lookup was not attempted, in offline mode or
	// without a token.
	AccessSkipped
)

func (Access) Readable

func (a Access) Readable() bool

Readable reports whether the listing can be used to conclude that a name is absent. Only AccessOK allows that conclusion.

func (Access) String

func (a Access) String() string

type Client

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

Client reads secrets, variables and environments from the GitHub API.

func New

func New(owner, repo string, opts Options) (*Client, error)

New builds a client for owner/repo.

func (*Client) Inventory

func (c *Client) Inventory(ctx context.Context, environments []string) (*Inventory, error)

Inventory reads every scope Yumlab needs. environments limits the environment lookups to those actually referenced by the workflows.

Inventory does not fail when a scope cannot be read: the failure is recorded in that scope's Access and the rest of the inventory is still collected. It only returns an error when nothing at all could be reached, which means the result would be meaningless.

type Inventory

type Inventory struct {
	Owner string
	Repo  string

	RepoSecrets   NameSet
	RepoVariables NameSet

	// OrgSecrets and OrgVariables list the organisation entries that are
	// actually granted to this repository, not every entry in the organisation.
	// An organisation secret that exists but is not shared with this repository
	// is unusable here, so counting it would hide a real problem.
	OrgSecrets   NameSet
	OrgVariables NameSet

	// Environments lists the deployment environments configured on the repo.
	Environments NameSet

	EnvSecrets   map[string]NameSet
	EnvVariables map[string]NameSet
}

Inventory is everything Yumlab knows about a repository's configured secrets and variables.

func NewInventory

func NewInventory(owner, repo string, reason string) *Inventory

NewInventory returns an inventory with every scope marked as not attempted.

func (*Inventory) EnvironmentSecrets

func (inv *Inventory) EnvironmentSecrets(env string) NameSet

EnvironmentSecrets returns the secrets of one environment. The zero value is reported as skipped, never as an empty readable set.

func (*Inventory) EnvironmentVariables

func (inv *Inventory) EnvironmentVariables(env string) NameSet

EnvironmentVariables returns the variables of one environment.

type NameSet

type NameSet struct {
	Access Access
	// Reason explains a non-OK access in words the user can act on, typically
	// naming the missing permission.
	Reason string
	// contains filtered or unexported fields
}

NameSet is the set of names in one scope, plus how the listing went.

A NameSet whose Access is not AccessOK is not empty: it is unknown. Callers must check Access before concluding anything from Has.

func NewNameSet

func NewNameSet(names []string) NameSet

NewNameSet builds a readable set, used by the API client and by the declarative fallback in the config file.

func Unavailable

func Unavailable(a Access, reason string) NameSet

Unavailable builds a set that could not be read.

func (NameSet) Has

func (s NameSet) Has(name string) bool

Has reports whether the name is present. It is only meaningful when Access is AccessOK.

func (NameSet) Len

func (s NameSet) Len() int

Len returns the number of known names.

func (NameSet) Merge

func (s NameSet) Merge(o NameSet) NameSet

Merge returns the union of two sets. The result is readable only if both inputs were, since a name absent from an unreadable half proves nothing.

func (NameSet) Names

func (s NameSet) Names() []string

Names returns the sorted names, for diagnostics.

type Options

type Options struct {
	// Token is the GitHub token. It is required.
	Token string
	// BaseURL points at a GitHub Enterprise instance. Empty means github.com.
	BaseURL string
	// Timeout bounds every individual API call.
	Timeout time.Duration
}

Options configures the client.

type Repository

type Repository struct {
	Owner string
	Name  string
	// Source says where the identification came from, so the user can tell why
	// Yumlab is looking at a given repository.
	Source string
}

Repository identifies the repository being scanned.

func DetectRepository

func DetectRepository(dir string) (Repository, error)

DetectRepository works out which repository dir belongs to.

In a GitHub Actions run, GITHUB_REPOSITORY is authoritative. Otherwise the origin remote in .git/config is used. Git itself is never invoked, so Yumlab works in containers that ship no git binary.

func ParseSlug

func ParseSlug(s string) (Repository, error)

ParseSlug reads an "owner/name" string.

func (Repository) String

func (r Repository) String() string

Jump to

Keyboard shortcuts

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