Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
c7c279f
fix: Resource.List/ListAll/Iter use collection path, not item path
Snider Mar 22, 2026
1f4c5c6
Merge pull request 'fix: Resource collection path for List/ListAll/It…
Mar 22, 2026
33eb5bc
fix: StateType and TimeStamp are strings, not empty structs
Snider Mar 22, 2026
107c78d
test(services): road-test resource CRUD paths
Snider Mar 22, 2026
71cce73
Merge pull request '[agent/codex] Road-test the go-forge library. Rea…
Mar 22, 2026
206749e
fix: Create uses collection path + road-test suite (Codex)
Snider Mar 22, 2026
fdb6372
Merge pull request 'fix: Create collection path + Codex road-test sui…
Mar 22, 2026
244ff65
feat(commits): add List/Get methods + tests (Codex)
Snider Mar 22, 2026
ecad738
feat(forge): add MilestoneService, fix comment creation
Snider Mar 23, 2026
1cee642
docs: add security attack vector mapping
Mar 23, 2026
103e174
Merge pull request '[agent/codex] Security attack vector mapping. Rea…
Mar 23, 2026
55c5aa4
docs: add convention drift audit
Mar 23, 2026
ec04941
Merge pull request '[agent/codex] Convention drift check. Read CLAUDE…
Mar 23, 2026
ce3108b
docs: add API contract inventory
Mar 23, 2026
ca986fa
Merge pull request '[agent/codex] API contract extraction. For every …
Mar 23, 2026
aa839b0
Delete docs/security-attack-vector-mapping.md
Mar 23, 2026
f99a00c
Delete docs/convention-drift-2026-03-23.md
Mar 23, 2026
3579250
Merge branch 'main' into dev
Mar 23, 2026
1ffb4be
feat: upgrade to core v0.8.0-alpha.1, replace banned stdlib imports
Mar 26, 2026
c147b56
docs(package): fix stale usage example
Mar 26, 2026
551a964
refactor(ax): enforce v0.8.0 polish rules
Mar 26, 2026
2708eef
docs: correct dependency overview
Mar 30, 2026
bfb8cf6
refactor(ax): harden forgegen error flow and sync dev guide
Mar 30, 2026
725fce9
test: add milestone service coverage
Mar 30, 2026
85fde21
Add authenticated user email management
Apr 1, 2026
ef44e7a
Add milestone edit and delete APIs
Apr 1, 2026
7106861
feat: add raw markdown rendering
Apr 1, 2026
80f6912
Add user stopwatch listing
Apr 1, 2026
060de17
Add issue stopwatch delete API
Apr 1, 2026
891e822
Add repo archive download helper
Apr 1, 2026
b9e8b22
Add issue pin repositioning
Apr 1, 2026
5326ece
Add repository tag listing
Apr 1, 2026
6ce4d5e
feat: add misc iterators
Apr 1, 2026
042e886
feat: add wiki iter pages
Apr 1, 2026
2ad117d
feat: add org webhook CRUD
Apr 1, 2026
2f18098
feat: add markup rendering endpoint
Apr 1, 2026
fd621a4
Add repository topics support
Apr 1, 2026
419e622
fix: URL-escape repository path params
Apr 1, 2026
4ef2c27
feat(repo): add new pin allowance getter
Apr 1, 2026
8e238c7
feat(repo): add subscription watch helpers
Apr 1, 2026
c1f3ff5
feat(milestones): add list and iterator helpers
Apr 1, 2026
5257002
feat(issue): add issue subscription endpoints
Apr 1, 2026
60a7c94
Add repo stargazer and subscriber listing
Apr 1, 2026
221c5fa
Add repo topic add/delete helpers
Apr 1, 2026
3b1ed34
feat(repo): add collaborator management helpers
Apr 1, 2026
3a00e9f
feat(repo): add assignee helpers
Apr 1, 2026
8ecc090
Add user webhook API support
Apr 1, 2026
79bb427
feat(webhooks): add git hook helpers
Apr 1, 2026
99867c9
feat(repo): add avatar helpers
Apr 1, 2026
4af621e
feat(repo): add push mirror helpers
Apr 1, 2026
d97b9ba
feat(repos): add issue template listing
Apr 1, 2026
717de80
Add user subscription listing
Apr 1, 2026
36181a7
Add issue timeline listing
Apr 1, 2026
26ea875
Add issue time tracking helpers
Apr 1, 2026
1569bfe
Add repo raw file helper
Apr 1, 2026
43e99eb
Add repo signing key lookup
Apr 1, 2026
67aad89
feat: expose repository pull reviewers
Apr 1, 2026
de54fa8
feat: add pull review request endpoints
Apr 1, 2026
93708fd
Add repo tag endpoints
Apr 1, 2026
85d4ae6
feat(pulls): add scheduled auto-merge cancellation
Apr 1, 2026
0a592fa
Add repository contents listing
Apr 1, 2026
e1f67f6
feat(user): add avatar endpoints
Apr 1, 2026
129c031
Add repo tag protection endpoints
Apr 1, 2026
3621731
feat(repos): add fork listing helpers
Apr 1, 2026
6116316
feat(users): add blocked user listing helpers
Apr 1, 2026
2dd66a0
feat(users): add block user helper
Apr 1, 2026
02534e3
feat(repos): add topic search helpers
Apr 1, 2026
0ab85b1
feat(repos): add repository flags helpers
Apr 1, 2026
b5feca2
feat(actions): add repository action tasks listing
Apr 1, 2026
4fc0484
Add git note commit APIs
Apr 1, 2026
23d879f
feat(issues): add global issue search
Apr 1, 2026
dd8c6ba
Add team member lookup
Apr 1, 2026
ed4a2c7
feat(issues): add dependency relation helpers
Apr 1, 2026
9f140e3
feat(orgs): add organisation block helpers
Apr 1, 2026
c1b7e25
Add notification unread count endpoint
Apr 1, 2026
773713a
feat(repos): add repository search helpers
Apr 1, 2026
272de12
feat(users): add unblock helper
Apr 1, 2026
15265e4
feat: add issue time iterator
Apr 1, 2026
3cb64ca
Add wiki page revision retrieval
Apr 1, 2026
f7c8d7b
Add pull request changed files endpoint
Apr 1, 2026
484ecd1
feat(issues): add attachment helpers
Apr 1, 2026
584f372
feat(issues): add attachment uploads
Apr 2, 2026
5e12785
feat(users): add heatmap endpoint
Apr 2, 2026
4e251de
feat(misc): add instance settings endpoints
Apr 2, 2026
cb54bfe
feat(issues): add pinned issue listing
Apr 2, 2026
61eb6de
feat(repos): add topic iterator
Apr 2, 2026
6dff39c
feat(repos): add template repository generation
Apr 2, 2026
3940f8f
feat(repos): add repository languages endpoint
Apr 2, 2026
4489da4
Add repo raw media endpoint
Apr 2, 2026
c10ae6d
feat(repos): add typed fork options
Apr 2, 2026
1c03ea1
feat(users): add user settings endpoints
Apr 2, 2026
cb54c35
feat(users): add authenticated user quota getter
Apr 2, 2026
b9962f2
feat: add milestone list filters
Apr 2, 2026
e9faaab
feat(releases): add release attachment upload
Apr 2, 2026
7862054
feat(users): add following check
Apr 2, 2026
7c22536
feat(repos): add compare endpoint
Apr 2, 2026
20e0382
feat(users): add starring check
Apr 2, 2026
1f6cfbf
feat(repos): add repository deploy key endpoints
Apr 2, 2026
572a1f1
Add admin email endpoints
Apr 2, 2026
b5792ba
Add latest release helper
Apr 2, 2026
122b68c
feat: add repo notification marking
Apr 2, 2026
de8a3c9
feat(notifications): add notification list filters
Apr 2, 2026
9deb460
feat(admin): add quota group endpoints
Apr 2, 2026
35cf966
feat(admin): add admin hook endpoints
Apr 2, 2026
a555c24
feat(issues): add tracked time deletion
Apr 2, 2026
5d43748
Add admin quota group lookup
Apr 2, 2026
02def0d
feat: add iterator for repository flags
Apr 2, 2026
c7809c0
feat(actions): add repo variable update
Apr 2, 2026
3ed3eca
Add repository activity feed listing
Apr 2, 2026
c722215
forgegen: preserve swagger additionalProperties
Apr 2, 2026
07241a5
feat(orgs): add activity feed listings
Apr 2, 2026
720e2f2
feat(commits): add commit pull request lookup
Apr 2, 2026
c63e45d
Add admin quota rule endpoints
Apr 2, 2026
a383ece
feat(users): add quota artifact listing
Apr 2, 2026
d1c690e
feat(activitypub): add ActivityPub actor service
Apr 2, 2026
02382d1
feat(orgs): add public member endpoints
Apr 2, 2026
9f263a7
feat(repos): add issue config endpoints
Apr 2, 2026
2046969
feat(orgs): add organisation membership check
Apr 2, 2026
232c1fa
feat(repos): add pinned pull request listing
Apr 2, 2026
48c6296
feat(repos): add repository permission lookup
Apr 2, 2026
dabfa7e
fix(actions): align actions paths and add user variables
Apr 2, 2026
7a59181
feat(admin): add quota group membership endpoints
Apr 2, 2026
42286a1
feat(users): add quota attachment endpoints
Apr 2, 2026
0a4b8a8
feat(users): add quota package endpoints
Apr 2, 2026
39742d7
feat(repos): add repository lookup by ID
Apr 2, 2026
4a7743a
feat(pulls): add pull lookup by base and head
Apr 2, 2026
bb5c3c0
Add repo runner registration token
Apr 2, 2026
d2228a0
feat: add repository team management
Apr 2, 2026
a0dee7c
chore: expose client base url
Apr 2, 2026
de60dc0
feat(users): add authenticated starred listing
Apr 2, 2026
9ba98f9
feat(issues): add reaction list endpoints
Apr 2, 2026
391083d
Add release attachment editing
Apr 2, 2026
8a7f969
feat(repos): add repository migration endpoint
Apr 2, 2026
d09236e
Add commit diff download helper
Apr 2, 2026
a26af42
feat(notifications): add bulk mark endpoint
Apr 2, 2026
1f6dc6f
feat(repos): add diff patch endpoint
Apr 2, 2026
628de47
feat(admin): add actions run listing
Apr 2, 2026
11e614a
feat(repos): add editorconfig endpoint
Apr 2, 2026
452b190
feat(users): add oauth2 application management
Apr 2, 2026
2460a7b
feat(users): add user search endpoint
Apr 2, 2026
9f686bf
feat(users): add authenticated GPG key management
Apr 2, 2026
779d017
feat(users): add authenticated public key management
Apr 2, 2026
1a8fdf5
feat(users): add access token and user key endpoints
Apr 2, 2026
3fd4491
docs(forge): align service counts with activitypub
Apr 2, 2026
4912789
docs(forge): align service docs with milestones
Apr 2, 2026
acdcfc0
feat(forge): add missing Forgejo endpoints
Apr 2, 2026
db31014
feat(forge): add iterator variants for list endpoints
Apr 2, 2026
ad2bab3
feat(forge): add missing admin and issue endpoints
Apr 2, 2026
39ae1b3
fix: return repository transfer responses
Apr 2, 2026
55616b5
chore(forge): align stdlib io usage with AX conventions
Apr 2, 2026
870d143
chore(forge): centralise default pagination limit
Apr 2, 2026
7444ad4
chore(forge): centralise default pagination limit
Apr 2, 2026
597f4e0
fix(forge): track rate limits for raw requests
Apr 2, 2026
49daff2
feat(forge): add missing collection wrappers
Apr 2, 2026
c7596df
fix(forge): use canonical org repo creation route
Apr 2, 2026
dab3d47
feat(repos): add deprecated org repo route
Apr 2, 2026
2dcb22f
docs(forge): add usage examples to option types
Apr 2, 2026
3fd449a
docs(forgegen): add usage examples to generated option types
Apr 2, 2026
8473c56
docs(forge): add AX usage examples to core API
Apr 2, 2026
f8224ed
docs(forge): improve top-level usage examples
Apr 2, 2026
84d7c6a
feat(forge): expose top-level client metadata
Apr 2, 2026
933dc98
feat(forge): expose user agent metadata
Apr 2, 2026
0d03174
feat(forge): expose auth metadata
Apr 2, 2026
09ae6e6
feat(forge): expose HTTP client metadata
Apr 2, 2026
9bac6e5
chore(forge): verify AX parity
Apr 2, 2026
194a9d3
feat(forge): add iterator variants for remaining collections
Apr 2, 2026
a5bc1a3
feat(forge): add safe client stringers
Apr 2, 2026
40934c2
feat(forge): add safe Go stringers
Apr 2, 2026
7e8340a
feat(forge): add safe resource stringers
Apr 2, 2026
edbf3f7
fix(forge): make stringers nil-safe
Apr 2, 2026
0dd5916
feat(forge): add config file persistence
Apr 2, 2026
36f9619
feat(forge): add safe stringers for core value types
Apr 2, 2026
b8bc948
feat(forge): add APIError stringers
Apr 2, 2026
bdf669d
feat(forge): add safe stringers for option types
Apr 2, 2026
dba9852
feat(forge): add safe service stringers
Apr 2, 2026
d553cba
fix(forge): correct generated schema aliases
Apr 2, 2026
ddff64b
feat(forge): add missing repo and team helpers
Apr 2, 2026
0e8bc89
fix(forge): clarify top-level client summary
Apr 2, 2026
09d01be
feat(forge): add repository list filters
Apr 2, 2026
4b33c1b
docs(forgegen): expand generated usage examples
Apr 2, 2026
4b27f10
refactor(forge): align config lookup and service docs with AX
Apr 2, 2026
6236446
fix(forge): create config directory before saving
Apr 2, 2026
51dfbe8
fix(forge): honor config precedence before file reads
Apr 2, 2026
61d2b84
fix(forge): wrap helper parse errors
Apr 2, 2026
d331c64
refactor(forge): expose config path helper
Apr 2, 2026
d08c875
chore(forge): verify RFC coverage
Apr 2, 2026
00a3081
fix(forge): make client accessors nil-safe
Apr 2, 2026
88bad49
fix: migrate module paths from forge.lthn.ai to dappco.re
Snider Apr 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ The library is a flat package (`package forge`) with a layered design:

5. **`config.go`** — Config resolution: flags > env (`FORGE_URL`, `FORGE_TOKEN`) > defaults (`http://localhost:3000`).

6. **`forge.go`** — Top-level `Forge` struct aggregating all 18 service fields. Created via `NewForge(url, token)` or `NewForgeFromConfig(flagURL, flagToken)`.
6. **`forge.go`** — Top-level `Forge` struct aggregating all 20 service fields. Created via `NewForge(url, token)` or `NewForgeFromConfig(flagURL, flagToken)`.

7. **Service files** (`repos.go`, `issues.go`, etc.) — Each service struct embeds `Resource[T,C,U]` for standard CRUD, then adds hand-written action methods (e.g. `Fork`, `Pin`, `MirrorSync`). 18 services total: repos, issues, pulls, orgs, users, teams, admin, branches, releases, labels, webhooks, notifications, packages, actions, contents, wiki, commits, misc.
7. **Service files** (`repos.go`, `issues.go`, etc.) — Each service struct embeds `Resource[T,C,U]` for standard CRUD, then adds hand-written action methods (e.g. `Fork`, `Pin`, `MirrorSync`). 20 services total: repos, issues, pulls, orgs, users, teams, admin, branches, releases, labels, webhooks, notifications, packages, actions, contents, wiki, commits, milestones, misc, activitypub.

8. **`types/`** — Generated Go types from `swagger.v1.json` (229 types). The `//go:generate` directive lives in `types/generate.go`. **Do not hand-edit generated type files** — modify `cmd/forgegen/` instead.

Expand Down
194 changes: 179 additions & 15 deletions actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ package forge

import (
"context"
"fmt"
"iter"
"net/url"
"strconv"

core "dappco.re/go/core"
"dappco.re/go/core/forge/types"
)

// ActionsService handles CI/CD actions operations across repositories and
// organisations — secrets, variables, and workflow dispatches.
// organisations — secrets, variables, workflow dispatches, and tasks.
// No Resource embedding — heterogeneous endpoints across repo and org levels.
//
// Usage:
//
// f := forge.NewForge("https://forge.lthn.ai", "token")
// _, err := f.Actions.ListRepoSecrets(ctx, "core", "go-forge")
type ActionsService struct {
client *Client
}
Expand All @@ -21,82 +28,239 @@ func newActionsService(c *Client) *ActionsService {

// ListRepoSecrets returns all secrets for a repository.
func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string) ([]types.Secret, error) {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/secrets", owner, repo)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/secrets", pathParams("owner", owner, "repo", repo))
return ListAll[types.Secret](ctx, s.client, path, nil)
}

// IterRepoSecrets returns an iterator over all secrets for a repository.
func (s *ActionsService) IterRepoSecrets(ctx context.Context, owner, repo string) iter.Seq2[types.Secret, error] {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/secrets", owner, repo)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/secrets", pathParams("owner", owner, "repo", repo))
return ListIter[types.Secret](ctx, s.client, path, nil)
}

// CreateRepoSecret creates or updates a secret in a repository.
// Forgejo expects a PUT with {"data": "secret-value"} body.
func (s *ActionsService) CreateRepoSecret(ctx context.Context, owner, repo, name string, data string) error {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/secrets/%s", owner, repo, name)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/secrets/{secretname}", pathParams("owner", owner, "repo", repo, "secretname", name))
body := map[string]string{"data": data}
return s.client.Put(ctx, path, body, nil)
}

// DeleteRepoSecret removes a secret from a repository.
func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) error {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/secrets/%s", owner, repo, name)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/secrets/{secretname}", pathParams("owner", owner, "repo", repo, "secretname", name))
return s.client.Delete(ctx, path)
}

// ListRepoVariables returns all action variables for a repository.
func (s *ActionsService) ListRepoVariables(ctx context.Context, owner, repo string) ([]types.ActionVariable, error) {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables", owner, repo)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/variables", pathParams("owner", owner, "repo", repo))
return ListAll[types.ActionVariable](ctx, s.client, path, nil)
}

// IterRepoVariables returns an iterator over all action variables for a repository.
func (s *ActionsService) IterRepoVariables(ctx context.Context, owner, repo string) iter.Seq2[types.ActionVariable, error] {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables", owner, repo)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/variables", pathParams("owner", owner, "repo", repo))
return ListIter[types.ActionVariable](ctx, s.client, path, nil)
}

// CreateRepoVariable creates a new action variable in a repository.
// Forgejo expects a POST with {"value": "var-value"} body.
func (s *ActionsService) CreateRepoVariable(ctx context.Context, owner, repo, name, value string) error {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/%s", owner, repo, name)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/variables/{variablename}", pathParams("owner", owner, "repo", repo, "variablename", name))
body := types.CreateVariableOption{Value: value}
return s.client.Post(ctx, path, body, nil)
}

// UpdateRepoVariable updates an existing action variable in a repository.
func (s *ActionsService) UpdateRepoVariable(ctx context.Context, owner, repo, name string, opts *types.UpdateVariableOption) error {
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/variables/{variablename}", pathParams("owner", owner, "repo", repo, "variablename", name))
return s.client.Put(ctx, path, opts, nil)
}

// DeleteRepoVariable removes an action variable from a repository.
func (s *ActionsService) DeleteRepoVariable(ctx context.Context, owner, repo, name string) error {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/variables/%s", owner, repo, name)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/variables/{variablename}", pathParams("owner", owner, "repo", repo, "variablename", name))
return s.client.Delete(ctx, path)
}

// ListOrgSecrets returns all secrets for an organisation.
func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string) ([]types.Secret, error) {
path := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets", org)
path := ResolvePath("/api/v1/orgs/{org}/actions/secrets", pathParams("org", org))
return ListAll[types.Secret](ctx, s.client, path, nil)
}

// IterOrgSecrets returns an iterator over all secrets for an organisation.
func (s *ActionsService) IterOrgSecrets(ctx context.Context, org string) iter.Seq2[types.Secret, error] {
path := fmt.Sprintf("/api/v1/orgs/%s/actions/secrets", org)
path := ResolvePath("/api/v1/orgs/{org}/actions/secrets", pathParams("org", org))
return ListIter[types.Secret](ctx, s.client, path, nil)
}

// ListOrgVariables returns all action variables for an organisation.
func (s *ActionsService) ListOrgVariables(ctx context.Context, org string) ([]types.ActionVariable, error) {
path := fmt.Sprintf("/api/v1/orgs/%s/actions/variables", org)
path := ResolvePath("/api/v1/orgs/{org}/actions/variables", pathParams("org", org))
return ListAll[types.ActionVariable](ctx, s.client, path, nil)
}

// IterOrgVariables returns an iterator over all action variables for an organisation.
func (s *ActionsService) IterOrgVariables(ctx context.Context, org string) iter.Seq2[types.ActionVariable, error] {
path := fmt.Sprintf("/api/v1/orgs/%s/actions/variables", org)
path := ResolvePath("/api/v1/orgs/{org}/actions/variables", pathParams("org", org))
return ListIter[types.ActionVariable](ctx, s.client, path, nil)
}

// GetOrgVariable returns a single action variable for an organisation.
func (s *ActionsService) GetOrgVariable(ctx context.Context, org, name string) (*types.ActionVariable, error) {
path := ResolvePath("/api/v1/orgs/{org}/actions/variables/{variablename}", pathParams("org", org, "variablename", name))
var out types.ActionVariable
if err := s.client.Get(ctx, path, &out); err != nil {
return nil, err
}
return &out, nil
}

// CreateOrgVariable creates a new action variable in an organisation.
func (s *ActionsService) CreateOrgVariable(ctx context.Context, org, name, value string) error {
path := ResolvePath("/api/v1/orgs/{org}/actions/variables/{variablename}", pathParams("org", org, "variablename", name))
body := types.CreateVariableOption{Value: value}
return s.client.Post(ctx, path, body, nil)
}

// UpdateOrgVariable updates an existing action variable in an organisation.
func (s *ActionsService) UpdateOrgVariable(ctx context.Context, org, name string, opts *types.UpdateVariableOption) error {
path := ResolvePath("/api/v1/orgs/{org}/actions/variables/{variablename}", pathParams("org", org, "variablename", name))
return s.client.Put(ctx, path, opts, nil)
}

// DeleteOrgVariable removes an action variable from an organisation.
func (s *ActionsService) DeleteOrgVariable(ctx context.Context, org, name string) error {
path := ResolvePath("/api/v1/orgs/{org}/actions/variables/{variablename}", pathParams("org", org, "variablename", name))
return s.client.Delete(ctx, path)
}

// CreateOrgSecret creates or updates a secret in an organisation.
func (s *ActionsService) CreateOrgSecret(ctx context.Context, org, name, data string) error {
path := ResolvePath("/api/v1/orgs/{org}/actions/secrets/{secretname}", pathParams("org", org, "secretname", name))
body := map[string]string{"data": data}
return s.client.Put(ctx, path, body, nil)
}

// DeleteOrgSecret removes a secret from an organisation.
func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) error {
path := ResolvePath("/api/v1/orgs/{org}/actions/secrets/{secretname}", pathParams("org", org, "secretname", name))
return s.client.Delete(ctx, path)
}

// ListUserVariables returns all action variables for the authenticated user.
func (s *ActionsService) ListUserVariables(ctx context.Context) ([]types.ActionVariable, error) {
return ListAll[types.ActionVariable](ctx, s.client, "/api/v1/user/actions/variables", nil)
}

// IterUserVariables returns an iterator over all action variables for the authenticated user.
func (s *ActionsService) IterUserVariables(ctx context.Context) iter.Seq2[types.ActionVariable, error] {
return ListIter[types.ActionVariable](ctx, s.client, "/api/v1/user/actions/variables", nil)
}

// GetUserVariable returns a single action variable for the authenticated user.
func (s *ActionsService) GetUserVariable(ctx context.Context, name string) (*types.ActionVariable, error) {
path := ResolvePath("/api/v1/user/actions/variables/{variablename}", pathParams("variablename", name))
var out types.ActionVariable
if err := s.client.Get(ctx, path, &out); err != nil {
return nil, err
}
return &out, nil
}

// CreateUserVariable creates a new action variable for the authenticated user.
func (s *ActionsService) CreateUserVariable(ctx context.Context, name, value string) error {
path := ResolvePath("/api/v1/user/actions/variables/{variablename}", pathParams("variablename", name))
body := types.CreateVariableOption{Value: value}
return s.client.Post(ctx, path, body, nil)
}

// UpdateUserVariable updates an existing action variable for the authenticated user.
func (s *ActionsService) UpdateUserVariable(ctx context.Context, name string, opts *types.UpdateVariableOption) error {
path := ResolvePath("/api/v1/user/actions/variables/{variablename}", pathParams("variablename", name))
return s.client.Put(ctx, path, opts, nil)
}

// DeleteUserVariable removes an action variable for the authenticated user.
func (s *ActionsService) DeleteUserVariable(ctx context.Context, name string) error {
path := ResolvePath("/api/v1/user/actions/variables/{variablename}", pathParams("variablename", name))
return s.client.Delete(ctx, path)
}

// CreateUserSecret creates or updates a secret for the authenticated user.
func (s *ActionsService) CreateUserSecret(ctx context.Context, name, data string) error {
path := ResolvePath("/api/v1/user/actions/secrets/{secretname}", pathParams("secretname", name))
body := map[string]string{"data": data}
return s.client.Put(ctx, path, body, nil)
}

// DeleteUserSecret removes a secret for the authenticated user.
func (s *ActionsService) DeleteUserSecret(ctx context.Context, name string) error {
path := ResolvePath("/api/v1/user/actions/secrets/{secretname}", pathParams("secretname", name))
return s.client.Delete(ctx, path)
}

// DispatchWorkflow triggers a workflow run.
func (s *ActionsService) DispatchWorkflow(ctx context.Context, owner, repo, workflow string, opts map[string]any) error {
path := fmt.Sprintf("/api/v1/repos/%s/%s/actions/workflows/%s/dispatches", owner, repo, workflow)
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/workflows/{workflowname}/dispatches", pathParams("owner", owner, "repo", repo, "workflowname", workflow))
return s.client.Post(ctx, path, opts, nil)
}

// ListRepoTasks returns a single page of action tasks for a repository.
func (s *ActionsService) ListRepoTasks(ctx context.Context, owner, repo string, opts ListOptions) (*types.ActionTaskResponse, error) {
path := ResolvePath("/api/v1/repos/{owner}/{repo}/actions/tasks", pathParams("owner", owner, "repo", repo))

if opts.Page > 0 || opts.Limit > 0 {
u, err := url.Parse(path)
if err != nil {
return nil, core.E("ActionsService.ListRepoTasks", "forge: parse path", err)
}
q := u.Query()
if opts.Page > 0 {
q.Set("page", strconv.Itoa(opts.Page))
}
if opts.Limit > 0 {
q.Set("limit", strconv.Itoa(opts.Limit))
}
u.RawQuery = q.Encode()
path = u.String()
}

var out types.ActionTaskResponse
if err := s.client.Get(ctx, path, &out); err != nil {
return nil, err
}
return &out, nil
}

// IterRepoTasks returns an iterator over all action tasks for a repository.
func (s *ActionsService) IterRepoTasks(ctx context.Context, owner, repo string) iter.Seq2[types.ActionTask, error] {
return func(yield func(types.ActionTask, error) bool) {
const limit = 50
var seen int64
for page := 1; ; page++ {
resp, err := s.ListRepoTasks(ctx, owner, repo, ListOptions{Page: page, Limit: limit})
if err != nil {
yield(*new(types.ActionTask), err)
return
}
for _, item := range resp.Entries {
if !yield(*item, nil) {
return
}
seen++
}
if resp.TotalCount > 0 {
if seen >= resp.TotalCount {
return
}
continue
}
if len(resp.Entries) < limit {
return
}
}
}
}
Loading
Loading