TestUpdateActions_SafeOutputsInputsPreserved verifies that cached inputs and descriptions for safe-outputs.actions entries are preserved in actions-lock.json when other (unrelated) actions are updated. Previously, actionsLockEntry lacked Inputs/ActionDescription fields, causing them to be silently d
(t *testing.T)
| 116 | // actions are updated. Previously, actionsLockEntry lacked Inputs/ActionDescription fields, |
| 117 | // causing them to be silently dropped whenever the file was rewritten. |
| 118 | func TestUpdateActions_SafeOutputsInputsPreserved(t *testing.T) { |
| 119 | tmpDir := testutil.TempDir(t, "test-*") |
| 120 | |
| 121 | // Stub the release-fetch function so no network calls are made. |
| 122 | // actions/checkout gets a bump; owner/my-safe-action is already at latest. |
| 123 | deps := newActionUpdateDepsWithLatestRelease(func(_ context.Context, repo, currentVersion string, allowMajor, verbose bool) (string, string, error) { |
| 124 | switch repo { |
| 125 | case "actions/checkout": |
| 126 | return "v5", "newcheckoutsha1234567890123456789012345", nil |
| 127 | case "owner/my-safe-action": |
| 128 | // Same version/SHA → no update needed |
| 129 | return "v1", "mysafesha12345678901234567890123456789012", nil |
| 130 | default: |
| 131 | return currentVersion, "", nil |
| 132 | } |
| 133 | }) |
| 134 | |
| 135 | // Build actions-lock.json with a regular action and a safe-outputs action (with cached inputs). |
| 136 | cache := workflow.NewActionCache(tmpDir) |
| 137 | cache.Set("actions/checkout", "v4", "oldcheckoutsha234567890123456789012345678") |
| 138 | cache.Set("owner/my-safe-action", "v1", "mysafesha12345678901234567890123456789012") |
| 139 | cache.SetInputs("owner/my-safe-action", "v1", map[string]*workflow.ActionYAMLInput{ |
| 140 | "foo": {Description: "Foo input", Required: true}, |
| 141 | }) |
| 142 | if err := cache.Save(); err != nil { |
| 143 | t.Fatalf("failed to save initial cache: %v", err) |
| 144 | } |
| 145 | |
| 146 | // Run UpdateActions from tmpDir |
| 147 | wd, err := os.Getwd() |
| 148 | if err != nil { |
| 149 | t.Fatalf("failed to get working directory: %v", err) |
| 150 | } |
| 151 | t.Cleanup(func() { |
| 152 | if err := os.Chdir(wd); err != nil { |
| 153 | t.Errorf("failed to restore working directory: %v", err) |
| 154 | } |
| 155 | }) |
| 156 | if err := os.Chdir(tmpDir); err != nil { |
| 157 | t.Fatalf("failed to chdir: %v", err) |
| 158 | } |
| 159 | |
| 160 | if err := updateActions(context.Background(), deps, false, false, false, 0); err != nil { |
| 161 | t.Fatalf("UpdateActions() error = %v", err) |
| 162 | } |
| 163 | |
| 164 | // Reload the saved cache and verify safe-outputs inputs were preserved. |
| 165 | saved := workflow.NewActionCache(tmpDir) |
| 166 | if err := saved.Load(); err != nil { |
| 167 | t.Fatalf("failed to reload cache: %v", err) |
| 168 | } |
| 169 | |
| 170 | // actions/checkout should have been updated to v5 |
| 171 | checkoutEntry, ok := saved.Entries["actions/checkout@v5"] |
| 172 | if !ok { |
| 173 | t.Error("expected actions/checkout@v5 entry after update") |
| 174 | } else if checkoutEntry.SHA != "newcheckoutsha1234567890123456789012345" { |
| 175 | t.Errorf("actions/checkout SHA = %q, want newcheckoutsha...", checkoutEntry.SHA) |
nothing calls this directly
no test coverage detected