actions-up 1.12.0 → 1.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,4 @@
1
- /** Run the CLI. */
1
+ /**
2
+ * Run the CLI.
3
+ */
2
4
  export declare function run(): void;
@@ -1,10 +1,14 @@
1
- /** Options for resolving scan directories from CLI flags. */
1
+ /**
2
+ * Options for resolving scan directories from CLI flags.
3
+ */
2
4
  interface ResolveScanDirectoriesOptions {
3
5
  dir?: string[] | string;
4
6
  recursive?: boolean;
5
7
  cwd: string;
6
8
  }
7
- /** Resolved directory with root and relative directory. */
9
+ /**
10
+ * Resolved directory with root and relative directory.
11
+ */
8
12
  interface ResolvedDirectory {
9
13
  root: string;
10
14
  dir: string;
@@ -2,19 +2,19 @@ import { normalizeVersion } from "../versions/normalize-version.js";
2
2
  import { isSemverLike } from "../versions/is-semver-like.js";
3
3
  import { createGitHubClient } from "./create-github-client.js";
4
4
  import semver from "semver";
5
- async function checkUpdates(i, o, c) {
6
- let l = c?.client ?? createGitHubClient(o), u = c?.includeBranches ?? !1, d = i.filter((e) => e.type === "external" || e.type === "reusable-workflow");
7
- if (d.length === 0) return [];
8
- let f = /* @__PURE__ */ new Map();
9
- for (let e of d) {
10
- let t = f.get(e.name) ?? [];
11
- t.push(e), f.set(e.name, t);
5
+ async function checkUpdates(i, o, l) {
6
+ let u = l?.client ?? createGitHubClient(o), d = l?.includeBranches ?? !1, f = i.filter((e) => e.type === "external" || e.type === "reusable-workflow");
7
+ if (f.length === 0) return [];
8
+ let p = /* @__PURE__ */ new Map();
9
+ for (let e of f) {
10
+ let t = p.get(e.name) ?? [];
11
+ t.push(e), p.set(e.name, t);
12
12
  }
13
- let p = {
13
+ let m = {
14
14
  rateLimitError: null,
15
15
  rateLimitHit: !1
16
- }, m = await [...f.keys()].reduce((n, i) => n.then(async (n) => {
17
- if (p.rateLimitHit) return [...n, {
16
+ }, h = await [...p.keys()].reduce((n, i) => n.then(async (n) => {
17
+ if (m.rateLimitHit) return [...n, {
18
18
  publishedAt: null,
19
19
  version: null,
20
20
  actionName: i,
@@ -27,16 +27,16 @@ async function checkUpdates(i, o, c) {
27
27
  actionName: i,
28
28
  sha: null
29
29
  }];
30
- let [o, c] = a;
31
- if (!o || !c) return [...n, {
30
+ let [o, l] = a;
31
+ if (!o || !l) return [...n, {
32
32
  publishedAt: null,
33
33
  version: null,
34
34
  actionName: i,
35
35
  sha: null
36
36
  }];
37
37
  try {
38
- let a = f.get(i)[0]?.version;
39
- if (a && !isSha(a) && !isSemverLike(a) && await l.getRefType(o, c, a) === "branch" && !u) return [...n, {
38
+ let a = p.get(i)[0]?.version;
39
+ if (a && !isSha(a) && !isSemverLike(a) && await u.getRefType(o, l, a) === "branch" && !d) return [...n, {
40
40
  skipReason: "branch",
41
41
  status: "skipped",
42
42
  publishedAt: null,
@@ -44,37 +44,39 @@ async function checkUpdates(i, o, c) {
44
44
  actionName: i,
45
45
  sha: null
46
46
  }];
47
- let d = await l.getLatestRelease(o, c);
48
- if (!d) {
49
- let e = await l.getAllReleases(o, c, 1);
50
- d = e.find((e) => !e.isPrerelease) ?? e[0] ?? null;
47
+ let f = await u.getLatestRelease(o, l);
48
+ if (!f) {
49
+ let e = await u.getAllReleases(o, l, 1);
50
+ f = e.find((e) => !e.isPrerelease) ?? e[0] ?? null;
51
51
  }
52
- if (d) {
53
- let { publishedAt: a, version: s, sha: u } = d, f = !1;
52
+ if (f) {
53
+ let { publishedAt: a, version: s, sha: d } = f, p = !1;
54
54
  {
55
55
  let n = normalizeVersion(s), i = !!(s && s.trim() !== ""), a = i && /^v?\d+$/u.test(s.trim()), o = semver.valid(n);
56
- f = !i || a || !o || !isSemverLike(s);
56
+ p = !i || a || !o || !isSemverLike(s);
57
57
  }
58
- if (f) {
59
- let a = await l.getAllTags(o, c, 30);
58
+ if (p) {
59
+ let a = await u.getAllTags(o, l, 30);
60
60
  if (a.length > 0) {
61
- let u = a.filter((e) => isSemverLike(e.tag)).map((t) => ({
61
+ let d = a.filter((e) => isSemverLike(e.tag)).map((t) => ({
62
62
  v: semver.valid(normalizeVersion(t.tag)),
63
63
  raw: t
64
64
  }));
65
- if (u.length > 0) {
66
- u.sort((e, t) => {
65
+ if (d.length > 0) {
66
+ d.sort((e, t) => {
67
67
  let n = semver.rcompare(e.v, t.v);
68
68
  if (n !== 0) return n;
69
69
  let i = /\d+\.\d+/u.test(e.raw.tag) ? 1 : 0;
70
70
  return (/\d+\.\d+/u.test(t.raw.tag) ? 1 : 0) - i;
71
71
  });
72
- let t = u[0].raw, a = semver.valid(normalizeVersion(s) ?? void 0);
73
- if (!a || semver.gt(u[0].v, a) || semver.eq(u[0].v, a) && /\d+\.\d+/u.test(t.tag)) {
72
+ let t = d[0].raw, a = semver.valid(normalizeVersion(s) ?? void 0);
73
+ if (!a || semver.gt(d[0].v, a) || semver.eq(d[0].v, a) && /\d+\.\d+/u.test(t.tag)) {
74
74
  let e = t.tag, r = t.sha?.length ? t.sha : null;
75
75
  if (!r && e) try {
76
- r = await l.getTagSha(o, c, e);
77
- } catch {}
76
+ r = await u.getTagSha(o, l, e);
77
+ } catch (e) {
78
+ if (isRateLimitError(e)) throw e;
79
+ }
78
80
  return [...n, {
79
81
  version: e,
80
82
  publishedAt: null,
@@ -85,20 +87,26 @@ async function checkUpdates(i, o, c) {
85
87
  }
86
88
  }
87
89
  }
88
- if (!u && s) try {
89
- u = await l.getTagSha(o, c, s);
90
- } catch {}
90
+ if (s) {
91
+ let e = d;
92
+ try {
93
+ d = await u.getTagSha(o, l, s) ?? e;
94
+ } catch (t) {
95
+ if (isRateLimitError(t)) throw t;
96
+ d = e;
97
+ }
98
+ }
91
99
  return [...n, {
92
100
  status: "ok",
93
101
  publishedAt: a,
94
102
  actionName: i,
95
103
  version: s,
96
- sha: u
104
+ sha: d
97
105
  }];
98
106
  }
99
- let p = await l.getAllTags(o, c, 30);
100
- if (p.length > 0) {
101
- let a = p.filter((e) => isSemverLike(e.tag)).map((t) => ({
107
+ let m = await u.getAllTags(o, l, 30);
108
+ if (m.length > 0) {
109
+ let a = m.filter((e) => isSemverLike(e.tag)).map((t) => ({
102
110
  v: semver.valid(normalizeVersion(t.tag)),
103
111
  raw: t
104
112
  })), s;
@@ -107,17 +115,19 @@ async function checkUpdates(i, o, c) {
107
115
  if (n !== 0) return n;
108
116
  let i = /\d+\.\d+/u.test(e.raw.tag) ? 1 : 0;
109
117
  return (/\d+\.\d+/u.test(t.raw.tag) ? 1 : 0) - i;
110
- }), s = a[0].raw) : s = p[0];
111
- let u = s.tag, d = s.sha?.length ? s.sha : null;
112
- if (!d && u) try {
113
- d = await l.getTagSha(o, c, u);
114
- } catch {}
118
+ }), s = a[0].raw) : s = m[0];
119
+ let d = s.tag, f = s.sha?.length ? s.sha : null;
120
+ if (!f && d) try {
121
+ f = await u.getTagSha(o, l, d);
122
+ } catch (e) {
123
+ if (isRateLimitError(e)) throw e;
124
+ }
115
125
  return [...n, {
116
126
  status: "ok",
117
127
  publishedAt: null,
118
128
  actionName: i,
119
- version: u,
120
- sha: d
129
+ version: d,
130
+ sha: f
121
131
  }];
122
132
  }
123
133
  return [...n, {
@@ -127,7 +137,7 @@ async function checkUpdates(i, o, c) {
127
137
  sha: null
128
138
  }];
129
139
  } catch (e) {
130
- return e instanceof Error && e.name === "GitHubRateLimitError" ? (p.rateLimitHit = !0, p.rateLimitError = e, [...n, {
140
+ return e instanceof Error && e.name === "GitHubRateLimitError" ? (m.rateLimitHit = !0, m.rateLimitError = e, [...n, {
131
141
  publishedAt: null,
132
142
  version: null,
133
143
  actionName: i,
@@ -140,12 +150,12 @@ async function checkUpdates(i, o, c) {
140
150
  }]);
141
151
  }
142
152
  }), Promise.resolve([]));
143
- if (p.rateLimitError) {
144
- let e = !!(o ?? process.env.GITHUB_TOKEN), t = `${p.rateLimitError.message || "GitHub API rate limit exceeded."}\n${e ? "Wait for reset or reduce request rate." : "Please set GITHUB_TOKEN environment variable to increase the limit.\nSee: https://github.com/azat-io/actions-up?tab=readme-ov-file#using-github-token-for-higher-rate-limits"}`, n = Error(t);
153
+ if (m.rateLimitError) {
154
+ let e = !!(o ?? process.env.GITHUB_TOKEN), t = `${m.rateLimitError.message || "GitHub API rate limit exceeded."}\n${e ? "Wait for reset or reduce request rate." : "Please set GITHUB_TOKEN environment variable to increase the limit.\nSee: https://github.com/azat-io/actions-up?tab=readme-ov-file#github-token"}`, n = Error(t);
145
155
  throw n.name = "GitHubRateLimitError", n;
146
156
  }
147
- let h = /* @__PURE__ */ new Map();
148
- for (let e of m) h.set(e.actionName, {
157
+ let g = /* @__PURE__ */ new Map();
158
+ for (let e of h) g.set(e.actionName, {
149
159
  publishedAt: e.publishedAt,
150
160
  actionName: e.actionName,
151
161
  skipReason: e.skipReason,
@@ -153,23 +163,23 @@ async function checkUpdates(i, o, c) {
153
163
  status: e.status,
154
164
  sha: e.sha
155
165
  });
156
- let g = [];
157
- for (let e of d) {
158
- let t = h.get(e.name);
159
- t ? g.push(createUpdate(e, {
166
+ let _ = [];
167
+ for (let e of f) {
168
+ let t = g.get(e.name);
169
+ t ? _.push(createUpdate(e, {
160
170
  publishedAt: t.publishedAt,
161
171
  version: t.version,
162
172
  sha: t.sha
163
173
  }, {
164
174
  skipReason: t.skipReason,
165
175
  status: t.status
166
- })) : g.push(createUpdate(e, {
176
+ })) : _.push(createUpdate(e, {
167
177
  publishedAt: null,
168
178
  version: null,
169
179
  sha: null
170
180
  }));
171
181
  }
172
- return g;
182
+ return _;
173
183
  }
174
184
  function createUpdate(t, n, i = {}) {
175
185
  let { version: a, sha: c, publishedAt: l } = n, u = t.version ?? "unknown", d = normalizeVersion(u), f = a ? normalizeVersion(a) : null, p = i.status ?? "ok", m = i.skipReason, h = !1, g = !1;
@@ -216,4 +226,7 @@ function isSha(e) {
216
226
  let t = e.replace(/^v/u, "");
217
227
  return /^[0-9a-f]{7,40}$/iu.test(t);
218
228
  }
229
+ function isRateLimitError(e) {
230
+ return e instanceof Error && e.name === "GitHubRateLimitError";
231
+ }
219
232
  export { checkUpdates };
@@ -4,7 +4,8 @@ import { ReleaseInfo } from '../../types/release-info';
4
4
  * Fetch releases for a repository.
5
5
  *
6
6
  * Resolves SHA only for the first returned release via target_commitish when it
7
- * looks like a SHA; further enrichment happens at higher levels when needed.
7
+ * looks like a SHA; callers can resolve the tag via git refs later when
8
+ * pinning.
8
9
  *
9
10
  * @param context - Client context.
10
11
  * @param parameters - Request parameters.
@@ -2,15 +2,25 @@ import { GitHubClient } from '../../types/github-client';
2
2
  import { UpdateMode } from '../../types/update-mode';
3
3
  import { TagInfo } from '../../types/tag-info';
4
4
  interface GetCompatibleUpdateParameters {
5
- /** Optional in-memory cache for resolved tag SHAs. */
5
+ /**
6
+ * Optional in-memory cache for resolved tag SHAs.
7
+ */
6
8
  shaCache?: Map<string, string | null>;
7
- /** Update mode that limits which tag can be selected. */
9
+ /**
10
+ * Update mode that limits which tag can be selected.
11
+ */
8
12
  mode: Exclude<UpdateMode, 'major'>;
9
- /** Optional in-memory cache for action tags. */
13
+ /**
14
+ * Optional in-memory cache for action tags.
15
+ */
10
16
  tagsCache?: Map<string, TagInfo[]>;
11
- /** Current action version used as compatibility baseline. */
17
+ /**
18
+ * Current action version used as compatibility baseline.
19
+ */
12
20
  currentVersion: string | null;
13
- /** Action name in `owner/repo` format (path suffix is allowed). */
21
+ /**
22
+ * Action name in `owner/repo` format (path suffix is allowed).
23
+ */
14
24
  actionName: string;
15
25
  }
16
26
  /**
@@ -3,9 +3,9 @@ import { ReleaseInfo } from '../../types/release-info';
3
3
  /**
4
4
  * Fetch the latest release for a repository.
5
5
  *
6
- * If the latest release does not exist (404), returns null. The commit SHA is
7
- * taken from target_commitish only when it looks like a SHA; otherwise SHA is
8
- * left null and may be resolved later via tag lookups.
6
+ * If the latest release does not exist (404), returns null. The commit SHA may
7
+ * be taken from target_commitish when it looks like a SHA; callers can resolve
8
+ * the tag via git refs later when pinning.
9
9
  *
10
10
  * @param context - Client context.
11
11
  * @param owner - Repository owner.
@@ -1,12 +1,20 @@
1
1
  import { GitHubAction } from '../../../types/github-action';
2
2
  interface ExtractUsesOptions {
3
- /** YAML sequence node containing workflow/action steps. */
3
+ /**
4
+ * YAML sequence node containing workflow/action steps.
5
+ */
4
6
  stepsNode: unknown;
5
- /** Path of the file being scanned (for metadata). */
7
+ /**
8
+ * Path of the file being scanned (for metadata).
9
+ */
6
10
  filePath: string;
7
- /** Name of the job containing these steps (for workflows). */
11
+ /**
12
+ * Name of the job containing these steps (for workflows).
13
+ */
8
14
  jobName?: string;
9
- /** Original YAML file content (for line number calculation). */
15
+ /**
16
+ * Original YAML file content (for line number calculation).
17
+ */
10
18
  content: string;
11
19
  }
12
20
  /**
@@ -1,4 +1,6 @@
1
- /** Constants for directory names used in the project. */
1
+ /**
2
+ * Constants for directory names used in the project.
3
+ */
2
4
  export declare const GITHUB_DIRECTORY: ".github";
3
5
  export declare const WORKFLOWS_DIRECTORY: "workflows";
4
6
  export declare const ACTIONS_DIRECTORY: "actions";
@@ -1,6 +1,8 @@
1
1
  import { ActionUpdate } from '../../types/action-update';
2
2
  interface PromptUpdateSelectionOptions {
3
- /** Whether to show the Age column. */
3
+ /**
4
+ * Whether to show the Age column.
5
+ */
4
6
  showAge?: boolean;
5
7
  }
6
8
  export declare function promptUpdateSelection(updates: ActionUpdate[], options?: PromptUpdateSelectionOptions): Promise<ActionUpdate[] | null>;
@@ -4,18 +4,22 @@ import { GitHubAction } from '../../types/github-action';
4
4
  * object.
5
5
  *
6
6
  * @example
7
- * const action = parseActionReference(
8
- * 'actions/checkout@v3',
9
- * 'workflow.yml',
10
- * 10,
11
- * )
12
- * // Returns: {
13
- * // type: 'external',
14
- * // name: 'actions/checkout',
15
- * // version: 'v3',
16
- * // file: 'workflow.yml',
17
- * // line: 10,
18
- * // }
7
+ *
8
+ * ```ts
9
+ * const action = parseActionReference(
10
+ * 'actions/checkout@v3',
11
+ * 'workflow.yml',
12
+ * 10,
13
+ * )
14
+ * // Returns:
15
+ * // {
16
+ * // type: 'external',
17
+ * // name: 'actions/checkout',
18
+ * // version: 'v3',
19
+ * // file: 'workflow.yml',
20
+ * // line: 10,
21
+ * // }
22
+ * ```
19
23
  *
20
24
  * @param reference - The action reference string to parse. Can be:
21
25
  *
@@ -4,7 +4,10 @@ import { ScanResult } from '../types/scan-result';
4
4
  * actions.
5
5
  *
6
6
  * @example
7
- * const result = await scanGitHubActions('/path/to/repo')
7
+ *
8
+ * ```ts
9
+ * const result = await scanGitHubActions('/path/to/repo')
10
+ * ```
8
11
  *
9
12
  * @param rootPath - The root path of the repository to scan. Defaults to
10
13
  * current working directory.
@@ -1,4 +1,6 @@
1
- /** Update level for a version change. */
1
+ /**
2
+ * Update level for a version change.
3
+ */
2
4
  type UpdateLevel = 'unknown' | 'major' | 'minor' | 'patch' | 'none';
3
5
  /**
4
6
  * Determine the update level between two version strings.
package/dist/package.js CHANGED
@@ -1,2 +1,2 @@
1
- const version = "1.12.0";
1
+ const version = "1.12.1";
2
2
  export { version };
@@ -1,30 +1,50 @@
1
1
  import { GitHubAction } from './github-action';
2
- /** Update information for a GitHub Action. */
2
+ /**
3
+ * Update information for a GitHub Action.
4
+ */
3
5
  export interface ActionUpdate {
4
- /** Reason for skipping the update check. */
6
+ /**
7
+ * Reason for skipping the update check.
8
+ */
5
9
  skipReason?: 'unknown' | 'branch'
6
10
 
7
- /** Current version string. */
11
+ /**
12
+ * Current version string.
13
+ */
8
14
  currentVersion: string | null
9
15
 
10
- /** Latest available version. */
16
+ /**
17
+ * Latest available version.
18
+ */
11
19
  latestVersion: string | null
12
20
 
13
- /** Status of the check for this action. */
21
+ /**
22
+ * Status of the check for this action.
23
+ */
14
24
  status?: 'skipped' | 'ok'
15
25
 
16
- /** SHA hash of the latest version. */
26
+ /**
27
+ * SHA hash of the latest version.
28
+ */
17
29
  latestSha: string | null
18
30
 
19
- /** Publication date of the latest version (null if unknown). */
31
+ /**
32
+ * Publication date of the latest version (null if unknown).
33
+ */
20
34
  publishedAt: Date | null
21
35
 
22
- /** The original action from scanning. */
36
+ /**
37
+ * The original action from scanning.
38
+ */
23
39
  action: GitHubAction
24
40
 
25
- /** Whether this is a major version change. */
41
+ /**
42
+ * Whether this is a major version change.
43
+ */
26
44
  isBreaking: boolean
27
45
 
28
- /** Whether an update is available. */
46
+ /**
47
+ * Whether an update is available.
48
+ */
29
49
  hasUpdate: boolean
30
50
  }
@@ -1,12 +1,20 @@
1
1
  import { CompositeActionStep } from './composite-action-step';
2
- /** Represents the runs configuration for a composite action. */
2
+ /**
3
+ * Represents the runs configuration for a composite action.
4
+ */
3
5
  export interface CompositeActionRuns {
4
- /** Array of steps to execute. */
6
+ /**
7
+ * Array of steps to execute.
8
+ */
5
9
  steps?: CompositeActionStep[]
6
10
 
7
- /** Allow additional properties. */
11
+ /**
12
+ * Allow additional properties.
13
+ */
8
14
  [key: string]: unknown
9
15
 
10
- /** Must be 'composite' for composite actions. */
16
+ /**
17
+ * Must be 'composite' for composite actions.
18
+ */
11
19
  using?: string
12
20
  }
@@ -1,23 +1,39 @@
1
- /** Represents a step in a composite GitHub Action. */
1
+ /**
2
+ * Represents a step in a composite GitHub Action.
3
+ */
2
4
  export interface CompositeActionStep {
3
- /** Environment variables for this step. */
5
+ /**
6
+ * Environment variables for this step.
7
+ */
4
8
  env?: Record<string, unknown>
5
9
 
6
- /** Working directory for the step. */
10
+ /**
11
+ * Working directory for the step.
12
+ */
7
13
  'working-directory'?: string
8
14
 
9
- /** Allow additional properties. */
15
+ /**
16
+ * Allow additional properties.
17
+ */
10
18
  [key: string]: unknown
11
19
 
12
- /** Shell to use for the run command. */
20
+ /**
21
+ * Shell to use for the run command.
22
+ */
13
23
  shell?: string
14
24
 
15
- /** Action to use for this step. */
25
+ /**
26
+ * Action to use for this step.
27
+ */
16
28
  uses?: string
17
29
 
18
- /** Display name for this step. */
30
+ /**
31
+ * Display name for this step.
32
+ */
19
33
  name?: string
20
34
 
21
- /** Shell command to run for this step. */
35
+ /**
36
+ * Shell command to run for this step.
37
+ */
22
38
  run?: string
23
39
  }
@@ -1,21 +1,35 @@
1
1
  import { CompositeActionRuns } from './composite-action-runs';
2
- /** Represents the structure of a composite GitHub Action file. */
2
+ /**
3
+ * Represents the structure of a composite GitHub Action file.
4
+ */
3
5
  export interface CompositeActionStructure {
4
- /** Output values from the action. */
6
+ /**
7
+ * Output values from the action.
8
+ */
5
9
  outputs?: Record<string, unknown>
6
10
 
7
- /** Input parameters for the action. */
11
+ /**
12
+ * Input parameters for the action.
13
+ */
8
14
  inputs?: Record<string, unknown>
9
15
 
10
- /** Runs configuration for composite actions. */
16
+ /**
17
+ * Runs configuration for composite actions.
18
+ */
11
19
  runs?: CompositeActionRuns
12
20
 
13
- /** Allow additional properties. */
21
+ /**
22
+ * Allow additional properties.
23
+ */
14
24
  [key: string]: unknown
15
25
 
16
- /** Description of what the action does. */
26
+ /**
27
+ * Description of what the action does.
28
+ */
17
29
  description?: string
18
30
 
19
- /** Display name of the action. */
31
+ /**
32
+ * Display name of the action.
33
+ */
20
34
  name?: string
21
35
  }
@@ -1,26 +1,44 @@
1
- /** Represents a GitHub Action used in workflows or composite actions. */
1
+ /**
2
+ * Represents a GitHub Action used in workflows or composite actions.
3
+ */
2
4
  export interface GitHubAction {
3
- /** Type of the GitHub Action. */
5
+ /**
6
+ * Type of the GitHub Action.
7
+ */
4
8
  type: 'reusable-workflow' | 'composite' | 'external' | 'docker' | 'local'
5
9
 
6
- /** Version or tag of the action (e.g., 'v1', 'main', commit SHA). */
10
+ /**
11
+ * Version or tag of the action (e.g., 'v1', 'main', commit SHA).
12
+ */
7
13
  version?: string | null
8
14
 
9
- /** Line number where the action is used in the file. */
15
+ /**
16
+ * Line number where the action is used in the file.
17
+ */
10
18
  line?: number
11
19
 
12
- /** Path to the file where this action is used. */
20
+ /**
21
+ * Path to the file where this action is used.
22
+ */
13
23
  file?: string
14
24
 
15
- /** Original `uses` string from workflow, if available. */
25
+ /**
26
+ * Original `uses` string from workflow, if available.
27
+ */
16
28
  uses?: string
17
29
 
18
- /** Name of the job where this action is used (for workflows). */
30
+ /**
31
+ * Name of the job where this action is used (for workflows).
32
+ */
19
33
  job?: string
20
34
 
21
- /** Full name of the action (e.g., 'actions/checkout'). */
35
+ /**
36
+ * Full name of the action (e.g., 'actions/checkout').
37
+ */
22
38
  name: string
23
39
 
24
- /** Original `ref` string from workflow, if available. */
40
+ /**
41
+ * Original `ref` string from workflow, if available.
42
+ */
25
43
  ref?: string
26
44
  }
@@ -6,27 +6,43 @@ import { TagInfo } from './tag-info';
6
6
  * number of API requests during a single run.
7
7
  */
8
8
  export interface GitHubClientContext {
9
- /** Lightweight caches keyed by owner/repo (+ extra payload). */
9
+ /**
10
+ * Lightweight caches keyed by owner/repo (+ extra payload).
11
+ */
10
12
  caches: {
11
- /** Cache of reference type detections (branch/tag/null). */
13
+ /**
14
+ * Cache of reference type detections (branch/tag/null).
15
+ */
12
16
  refType: Map<string, 'branch' | 'tag' | null>
13
17
 
14
- /** Cache of resolved tag metadata (message/date/SHA). */
18
+ /**
19
+ * Cache of resolved tag metadata (message/date/SHA).
20
+ */
15
21
  tagInfo: Map<string, TagInfo | null>
16
22
 
17
- /** Cache of resolved tag commit SHAs. */
23
+ /**
24
+ * Cache of resolved tag commit SHAs.
25
+ */
18
26
  tagSha: Map<string, string | null>
19
27
  }
20
28
 
21
- /** Remaining requests available per current rate-limit window. */
29
+ /**
30
+ * Remaining requests available per current rate-limit window.
31
+ */
22
32
  rateLimitRemaining: number
23
33
 
24
- /** GitHub token, if available. */
34
+ /**
35
+ * GitHub token, if available.
36
+ */
25
37
  token: undefined | string
26
38
 
27
- /** Scheduled time when rate limit resets. */
39
+ /**
40
+ * Scheduled time when rate limit resets.
41
+ */
28
42
  rateLimitReset: Date
29
43
 
30
- /** GitHub REST API base URL. */
44
+ /**
45
+ * GitHub REST API base URL.
46
+ */
31
47
  baseUrl: string
32
48
  }
@@ -8,35 +8,51 @@ import { TagInfo } from './tag-info';
8
8
  * normalized, serializable data structures.
9
9
  */
10
10
  export interface GitHubClient {
11
- /** Detect whether a reference is a tag or a branch (or unknown). */
11
+ /**
12
+ * Detect whether a reference is a tag or a branch (or unknown).
13
+ */
12
14
  getRefType(
13
15
  owner: string,
14
16
  repo: string,
15
17
  reference: string,
16
18
  ): Promise<'branch' | 'tag' | null>
17
19
 
18
- /** List releases with minimal enrichment. */
20
+ /**
21
+ * List releases with minimal enrichment.
22
+ */
19
23
  getAllReleases(
20
24
  owner: string,
21
25
  repo: string,
22
26
  limit?: number,
23
27
  ): Promise<ReleaseInfo[]>
24
28
 
25
- /** Fetch tag metadata (message/date) and the resolved commit SHA. */
29
+ /**
30
+ * Fetch tag metadata (message/date) and the resolved commit SHA.
31
+ */
26
32
  getTagInfo(owner: string, repo: string, tag: string): Promise<TagInfo | null>
27
33
 
28
- /** Resolve commit SHA for a tag without fetching commit data. */
34
+ /**
35
+ * Resolve commit SHA for a tag without fetching commit data.
36
+ */
29
37
  getTagSha(owner: string, repo: string, tag: string): Promise<string | null>
30
38
 
31
- /** List repository tags (name + commit SHA). */
39
+ /**
40
+ * List repository tags (name + commit SHA).
41
+ */
32
42
  getAllTags(owner: string, repo: string, limit?: number): Promise<TagInfo[]>
33
43
 
34
- /** Fetch the latest release or null when no latest release exists. */
44
+ /**
45
+ * Fetch the latest release or null when no latest release exists.
46
+ */
35
47
  getLatestRelease(owner: string, repo: string): Promise<ReleaseInfo | null>
36
48
 
37
- /** Current rate limit snapshot. */
49
+ /**
50
+ * Current rate limit snapshot.
51
+ */
38
52
  getRateLimitStatus(): { remaining: number; resetAt: Date }
39
53
 
40
- /** True when remaining requests are below a threshold. */
54
+ /**
55
+ * True when remaining requests are below a threshold.
56
+ */
41
57
  shouldWaitForRateLimit(threshold?: number): boolean
42
58
  }
@@ -1,23 +1,39 @@
1
- /** Normalized release information used across the tool. */
1
+ /**
2
+ * Normalized release information used across the tool.
3
+ */
2
4
  export interface ReleaseInfo {
3
- /** Release description (body) or null when absent. */
5
+ /**
6
+ * Release description (body) or null when absent.
7
+ */
4
8
  description: string | null
5
9
 
6
- /** True when the release is marked as prerelease. */
10
+ /**
11
+ * True when the release is marked as prerelease.
12
+ */
7
13
  isPrerelease: boolean
8
14
 
9
- /** Commit SHA associated with the release tag (may be null). */
15
+ /**
16
+ * Commit SHA associated with the release tag when known (may be provisional).
17
+ */
10
18
  sha: string | null
11
19
 
12
- /** Publication date of the release. */
20
+ /**
21
+ * Publication date of the release.
22
+ */
13
23
  publishedAt: Date
14
24
 
15
- /** Tag name (e.g. V1.2.3). */
25
+ /**
26
+ * Tag name (e.g. V1.2.3).
27
+ */
16
28
  version: string
17
29
 
18
- /** Release name or tag name when name is not provided. */
30
+ /**
31
+ * Release name or tag name when name is not provided.
32
+ */
19
33
  name: string
20
34
 
21
- /** HTML URL of the release page. */
35
+ /**
36
+ * HTML URL of the release page.
37
+ */
22
38
  url: string
23
39
  }
@@ -1,12 +1,20 @@
1
1
  import { GitHubAction } from './github-action';
2
- /** Result of scanning a repository for GitHub Actions usage. */
2
+ /**
3
+ * Result of scanning a repository for GitHub Actions usage.
4
+ */
3
5
  export interface ScanResult {
4
- /** Map of workflow files to their used GitHub Actions. */
6
+ /**
7
+ * Map of workflow files to their used GitHub Actions.
8
+ */
5
9
  workflows: Map<string, GitHubAction[]>
6
10
 
7
- /** Map of composite action names to their file paths. */
11
+ /**
12
+ * Map of composite action names to their file paths.
13
+ */
8
14
  compositeActions: Map<string, string>
9
15
 
10
- /** List of all unique GitHub Actions found in the repository. */
16
+ /**
17
+ * List of all unique GitHub Actions found in the repository.
18
+ */
11
19
  actions: GitHubAction[]
12
20
  }
@@ -1,14 +1,24 @@
1
- /** Normalized tag information (message/date) and the resolved commit SHA. */
1
+ /**
2
+ * Normalized tag information (message/date) and the resolved commit SHA.
3
+ */
2
4
  export interface TagInfo {
3
- /** Tag or commit message, null when absent. */
5
+ /**
6
+ * Tag or commit message, null when absent.
7
+ */
4
8
  message: string | null
5
9
 
6
- /** Commit SHA the tag ultimately points to (may be null). */
10
+ /**
11
+ * Commit SHA the tag ultimately points to (may be null).
12
+ */
7
13
  sha: string | null
8
14
 
9
- /** Date associated with the tag (from release, tagger or commit). */
15
+ /**
16
+ * Date associated with the tag (from release, tagger or commit).
17
+ */
10
18
  date: Date | null
11
19
 
12
- /** Tag name (e.g. V1.2.3). */
20
+ /**
21
+ * Tag name (e.g. V1.2.3).
22
+ */
13
23
  tag: string
14
24
  }
@@ -1,2 +1,4 @@
1
- /** Allowed update modes for filtering actions. */
1
+ /**
2
+ * Allowed update modes for filtering actions.
3
+ */
2
4
  export type UpdateMode = 'major' | 'minor' | 'patch'
@@ -1,27 +1,45 @@
1
1
  import { WorkflowStep } from './workflow-step';
2
- /** Represents a job in a GitHub Actions workflow. */
2
+ /**
3
+ * Represents a job in a GitHub Actions workflow.
4
+ */
3
5
  export interface WorkflowJob {
4
- /** Secrets passed to the reusable workflow ('inherit' or specific secrets). */
6
+ /**
7
+ * Secrets passed to the reusable workflow ('inherit' or specific secrets).
8
+ */
5
9
  secrets?: Record<string, unknown> | 'inherit'
6
10
 
7
- /** Input parameters passed to the reusable workflow. */
11
+ /**
12
+ * Input parameters passed to the reusable workflow.
13
+ */
8
14
  with?: Record<string, unknown>
9
15
 
10
- /** Runner environment(s) to execute this job on (e.g., 'ubuntu-latest'). */
16
+ /**
17
+ * Runner environment(s) to execute this job on (e.g., 'ubuntu-latest').
18
+ */
11
19
  'runs-on'?: string[] | string
12
20
 
13
- /** Job IDs that must complete successfully before this job runs. */
21
+ /**
22
+ * Job IDs that must complete successfully before this job runs.
23
+ */
14
24
  needs?: string[] | string
15
25
 
16
- /** Array of steps to execute in this job. */
26
+ /**
27
+ * Array of steps to execute in this job.
28
+ */
17
29
  steps?: WorkflowStep[]
18
30
 
19
- /** Allow additional properties for job configuration. */
31
+ /**
32
+ * Allow additional properties for job configuration.
33
+ */
20
34
  [key: string]: unknown
21
35
 
22
- /** Reusable workflow reference (mutually exclusive with 'steps'). */
36
+ /**
37
+ * Reusable workflow reference (mutually exclusive with 'steps').
38
+ */
23
39
  uses?: string
24
40
 
25
- /** Conditional expression to determine if the job should run. */
41
+ /**
42
+ * Conditional expression to determine if the job should run.
43
+ */
26
44
  if?: string
27
45
  }
@@ -1,20 +1,34 @@
1
- /** Represents a single step in a GitHub Actions workflow job. */
1
+ /**
2
+ * Represents a single step in a GitHub Actions workflow job.
3
+ */
2
4
  export interface WorkflowStep {
3
- /** Input parameters to pass to the action. */
5
+ /**
6
+ * Input parameters to pass to the action.
7
+ */
4
8
  with?: Record<string, unknown>
5
9
 
6
- /** Environment variables to set for this step. */
10
+ /**
11
+ * Environment variables to set for this step.
12
+ */
7
13
  env?: Record<string, unknown>
8
14
 
9
- /** Allow additional properties for step configuration. */
15
+ /**
16
+ * Allow additional properties for step configuration.
17
+ */
10
18
  [key: string]: unknown
11
19
 
12
- /** Action to use for this step (e.g., 'actions/checkout@v4'). */
20
+ /**
21
+ * Action to use for this step (e.g., 'actions/checkout@v4').
22
+ */
13
23
  uses?: string
14
24
 
15
- /** Display name for this step. */
25
+ /**
26
+ * Display name for this step.
27
+ */
16
28
  name?: string
17
29
 
18
- /** Shell command to run for this step. */
30
+ /**
31
+ * Shell command to run for this step.
32
+ */
19
33
  run?: string
20
34
  }
@@ -1,15 +1,25 @@
1
1
  import { WorkflowJob } from './workflow-job';
2
- /** Represents the root structure of a GitHub Actions workflow file. */
2
+ /**
3
+ * Represents the root structure of a GitHub Actions workflow file.
4
+ */
3
5
  export interface WorkflowStructure {
4
- /** Map of job IDs to job configurations. */
6
+ /**
7
+ * Map of job IDs to job configurations.
8
+ */
5
9
  jobs?: Record<string, WorkflowJob>
6
10
 
7
- /** Allow additional properties for workflow configuration. */
11
+ /**
12
+ * Allow additional properties for workflow configuration.
13
+ */
8
14
  [key: string]: unknown
9
15
 
10
- /** Display name for the workflow. */
16
+ /**
17
+ * Display name for the workflow.
18
+ */
11
19
  name?: string
12
20
 
13
- /** Events that trigger the workflow (push, pull_request, etc.). */
21
+ /**
22
+ * Events that trigger the workflow (push, pull_request, etc.).
23
+ */
14
24
  on?: unknown
15
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "actions-up",
3
- "version": "1.12.0",
3
+ "version": "1.12.1",
4
4
  "description": "Interactive CLI tool to update GitHub Actions to latest versions with SHA pinning",
5
5
  "keywords": [
6
6
  "github-actions",
@@ -36,19 +36,14 @@
36
36
  "./dist"
37
37
  ],
38
38
  "dependencies": {
39
- "cac": "^6.7.14",
39
+ "cac": "^7.0.0",
40
40
  "enquirer": "^2.4.1",
41
41
  "nanospinner": "^1.2.2",
42
42
  "picocolors": "^1.1.1",
43
43
  "semver": "^7.7.4",
44
- "yaml": "^2.8.2"
44
+ "yaml": "^2.8.3"
45
45
  },
46
46
  "engines": {
47
47
  "node": "^18.0.0 || >=20.0.0"
48
- },
49
- "pnpm": {
50
- "overrides": {
51
- "vite": "npm:rolldown-vite@latest"
52
- }
53
48
  }
54
49
  }
package/readme.md CHANGED
@@ -12,15 +12,21 @@
12
12
  [![Code Coverage](https://img.shields.io/codecov/c/github/azat-io/actions-up.svg?color=fff&labelColor=4493f8)](https://codecov.io/gh/azat-io/actions-up)
13
13
  [![GitHub License](https://img.shields.io/badge/license-MIT-232428.svg?color=fff&labelColor=4493f8)](https://github.com/azat-io/actions-up/blob/main/license.md)
14
14
 
15
- Actions Up scans your workflows and composite actions to discover every referenced GitHub Action, then checks for newer releases.
15
+ Actions Up scans your workflows and composite actions to discover every
16
+ referenced GitHub Action, then checks for newer releases.
16
17
 
17
- Interactively upgrade and pin actions to exact commit SHAs for secure, reproducible CI and low-friction maintenance.
18
+ Interactively upgrade and pin actions to exact commit SHAs for secure,
19
+ reproducible CI and low-friction maintenance.
18
20
 
19
21
  ## Features
20
22
 
21
- - **Auto-discovery**: Scans all workflows (`.github/workflows/*.yml`) and composite actions (`.github/actions/*/action.yml` and root `action.yml`/`action.yaml`)
22
- - **Reusable Workflows**: Detects and updates reusable workflow calls at the job level
23
- - **SHA pinning**: Updates actions to use commit SHA instead of tags for better security
23
+ - **Auto-discovery**: Scans all workflows (`.github/workflows/*.yml`) and
24
+ composite actions (`.github/actions/*/action.yml` and root
25
+ `action.yml`/`action.yaml`)
26
+ - **Reusable Workflows**: Detects and updates reusable workflow calls at the job
27
+ level
28
+ - **SHA pinning**: Updates actions to use commit SHA instead of tags for better
29
+ security
24
30
  - **Batch Updates**: Update multiple actions at once
25
31
  - **Interactive Selection**: Choose which actions to update
26
32
  - **Breaking Changes Detection**: Warns about major version updates
@@ -49,7 +55,9 @@ Interactively upgrade and pin actions to exact commit SHAs for secure, reproduci
49
55
 
50
56
  ## Why
51
57
 
52
- Keeping GitHub Actions updated is critical and time-consuming. Actions Up scans all workflows, highlights available updates, and can pin actions to SHAs for reproducibility.
58
+ Keeping GitHub Actions updated is critical and time-consuming. Actions Up scans
59
+ all workflows, highlights available updates, and can pin actions to SHAs for
60
+ reproducibility.
53
61
 
54
62
  | Without Actions Up | With Actions Up |
55
63
  | :----------------------------- | :------------------------------- |
@@ -59,7 +67,10 @@ Keeping GitHub Actions updated is critical and time-consuming. Actions Up scans
59
67
 
60
68
  ### Security Motivation
61
69
 
62
- GitHub Actions run arbitrary code in your CI. If a job has secrets available, any action used in that job can read the environment and exfiltrate those secrets. A compromised action or a mutable version tag is a direct path to leakage.
70
+ GitHub Actions run arbitrary code in your CI. If a job has secrets available,
71
+ any action used in that job can read the environment and exfiltrate those
72
+ secrets. A compromised action or a mutable version tag is a direct path to
73
+ leakage.
63
74
 
64
75
  Actions Up reduces risk by:
65
76
 
@@ -67,7 +78,9 @@ Actions Up reduces risk by:
67
78
  - Making outdated actions visible and showing exactly what runs in CI
68
79
  - Warning about major updates so you can review changes before applying them
69
80
 
70
- Note: secrets are available on `push`, `workflow_dispatch`, `schedule`, and `pull_request_target` triggers (and on fork PRs if explicitly enabled). Always scope workflow permissions to the minimum required.
81
+ Note: secrets are available on `push`, `workflow_dispatch`, `schedule`, and
82
+ `pull_request_target` triggers (and on fork PRs if explicitly enabled). Always
83
+ scope workflow permissions to the minimum required.
71
84
 
72
85
  ## Installation
73
86
 
@@ -107,7 +120,8 @@ npx actions-up
107
120
 
108
121
  This will:
109
122
 
110
- 1. Scan all `.github/workflows/*.yml` and `.github/actions/*/action.yml` files, plus root `action.yml`/`action.yaml`
123
+ 1. Scan all `.github/workflows/*.yml` and `.github/actions/*/action.yml` files,
124
+ plus root `action.yml`/`action.yaml`
111
125
  2. Check for available updates
112
126
  3. Show an interactive list to select updates
113
127
  4. Apply selected updates with SHA pinning
@@ -134,7 +148,8 @@ npx actions-up --dry-run
134
148
 
135
149
  By default, Actions Up scans `.github`.
136
150
 
137
- Use `--dir` to choose another directory, and pass it multiple times to scan several directories:
151
+ Use `--dir` to choose another directory, and pass it multiple times to scan
152
+ several directories:
138
153
 
139
154
  ```bash
140
155
  npx actions-up --dir .gitea
@@ -143,18 +158,23 @@ npx actions-up --dir .github --dir ./other/.github
143
158
 
144
159
  ### Recursive Scanning
145
160
 
146
- Use `--recursive` (`-r`) to scan YAML workflow/composite-action files recursively in the selected directories:
161
+ Use `--recursive` (`-r`) to scan YAML workflow/composite-action files
162
+ recursively in the selected directories:
147
163
 
148
164
  ```bash
149
165
  npx actions-up -r
150
166
  npx actions-up --dir ./gh-repo-defaults -r
151
167
  ```
152
168
 
153
- When `--recursive` is used without `--dir`, Actions Up scans from the current directory (`.`).
169
+ When `--recursive` is used without `--dir`, Actions Up scans from the current
170
+ directory (`.`).
154
171
 
155
172
  ### Branch References
156
173
 
157
- By default, actions pinned to branch refs (e.g., `@main`, `@release/v1`) are skipped to avoid changing intentionally floating references. Skipped entries are listed in the output. To include them in update checks, pass `--include-branches`.
174
+ By default, actions pinned to branch refs (e.g., `@main`, `@release/v1`) are
175
+ skipped to avoid changing intentionally floating references. Skipped entries are
176
+ listed in the output. To include them in update checks, pass
177
+ `--include-branches`.
158
178
 
159
179
  ### Update Mode
160
180
 
@@ -165,15 +185,17 @@ npx actions-up --mode minor
165
185
  npx actions-up --mode patch
166
186
  ```
167
187
 
168
- In `minor` and `patch` modes, Actions Up tries to find the newest compatible
169
- tag first (for example, from `@v4` in `minor` mode it will choose the latest
188
+ In `minor` and `patch` modes, Actions Up tries to find the newest compatible tag
189
+ first (for example, from `@v4` in `minor` mode it will choose the latest
170
190
  `v4.x.y`). If no compatible version exists, that action is skipped.
171
191
 
172
192
  ## GitHub Actions Integration
173
193
 
174
194
  ### Automated PR Checks
175
195
 
176
- You can integrate Actions Up into your CI/CD pipeline to automatically check for outdated actions on every pull request. This helps maintain security and ensures your team stays aware of available updates.
196
+ You can integrate Actions Up into your CI/CD pipeline to automatically check for
197
+ outdated actions on every pull request. This helps maintain security and ensures
198
+ your team stays aware of available updates.
177
199
 
178
200
  <details>
179
201
  <summary>Create <code>.github/workflows/check-actions-updates.yml</code>.</summary>
@@ -295,7 +317,9 @@ jobs:
295
317
  fi
296
318
 
297
319
  - name: Comment PR with updates
298
- if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
320
+ if:
321
+ github.event_name == 'pull_request' &&
322
+ github.event.pull_request.head.repo.full_name == github.repository
299
323
  uses: actions/github-script@v7
300
324
  with:
301
325
  script: |
@@ -433,7 +457,8 @@ jobs:
433
457
 
434
458
  ### GitHub Token
435
459
 
436
- Use `GITHUB_TOKEN` (or a PAT) to raise API rate limits from 60 to 5000 requests/hour.
460
+ Use `GITHUB_TOKEN` (or a PAT) to raise API rate limits from 60 to 5000
461
+ requests/hour.
437
462
 
438
463
  ```bash
439
464
  GITHUB_TOKEN=your_token_here npx actions-up
@@ -479,14 +504,17 @@ Ignore comments (file/block/next-line/inline):
479
504
 
480
505
  Interactive CLI for developers who want control over GitHub Actions updates.
481
506
 
482
- - **vs. Dependabot/Renovate:** Dependabot and Renovate update via pull requests; Actions Up is an interactive CLI with explicit SHA pinning.
483
- - **vs. pinact:** pinact is a CLI to pin and update Actions and reusable workflows; Actions Up adds interactive selection and major update warnings.
507
+ - **vs. Dependabot/Renovate:** Dependabot and Renovate update via pull requests;
508
+ Actions Up is an interactive CLI with explicit SHA pinning.
509
+ - **vs. pinact:** pinact is a CLI to pin and update Actions and reusable
510
+ workflows; Actions Up adds interactive selection and major update warnings.
484
511
  - **Zero-config:** `npx actions-up` runs immediately.
485
512
  - **Breaking change warnings:** Major updates are flagged before applying.
486
513
 
487
514
  ## Contributing
488
515
 
489
- See [Contributing Guide](https://github.com/azat-io/actions-up/blob/main/contributing.md).
516
+ See
517
+ [Contributing Guide](https://github.com/azat-io/actions-up/blob/main/contributing.md).
490
518
 
491
519
  ## License
492
520