diff --git a/knowledge-base/actions/homebrew/actions/remove-disabled-packages/action-security.yml b/knowledge-base/actions/homebrew/actions/remove-disabled-packages/action-security.yml new file mode 100644 index 000000000..5255e85ce --- /dev/null +++ b/knowledge-base/actions/homebrew/actions/remove-disabled-packages/action-security.yml @@ -0,0 +1,2 @@ +name: Remove disabled packages # Homebrew/actions/remove-disabled-packages +# GITHUB_TOKEN not used \ No newline at end of file diff --git a/remediation/workflow/metadata/actionmetadata_test.go b/remediation/workflow/metadata/actionmetadata_test.go index d3967e411..2696baa7c 100644 --- a/remediation/workflow/metadata/actionmetadata_test.go +++ b/remediation/workflow/metadata/actionmetadata_test.go @@ -181,6 +181,7 @@ func TestKnowledgeBase(t *testing.T) { func doesActionRepoExist(filePath string) bool { splitOnSlash := strings.Split(filePath, "/") + owner := splitOnSlash[5] repo := splitOnSlash[6] diff --git a/remediation/workflow/pin/action_image_manifest.go b/remediation/workflow/pin/action_image_manifest.go new file mode 100644 index 000000000..16e3a1ad8 --- /dev/null +++ b/remediation/workflow/pin/action_image_manifest.go @@ -0,0 +1,120 @@ +package pin + +import ( + "encoding/json" + "fmt" + "regexp" + "strings" + + "net/http" + + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/sirupsen/logrus" +) + +var ( + githubImmutableActionArtifactType = "application/vnd.github.actions.package.v1+json" + semanticTagRegex = regexp.MustCompile(`v[0-9]+\.[0-9]+\.[0-9]+$`) +) + +type ociManifest struct { + ArtifactType string `json:"artifactType"` +} + +// isImmutableAction checks if the action is an immutable action or not +// It queries the OCI manifest for the action and checks if the artifact type is "application/vnd.github.actions.package.v1+json" +// +// Example usage: +// +// # Immutable action (returns true) +// isImmutableAction("actions/checkout@v4.2.2") +// +// # Non-Immutable action (returns false) +// isImmutableAction("actions/checkout@v4.2.3") +// +// REF - https://github.com/actions/publish-immutable-action/issues/216#issuecomment-2549914784 +func IsImmutableAction(action string) bool { + + artifactType, err := getOCIImageArtifactTypeForGhAction(action) + if err != nil { + // log the error + logrus.WithFields(logrus.Fields{"action": action}).WithError(err).Error("error in getting OCI manifest for image") + return false + } + + if artifactType == githubImmutableActionArtifactType { + return true + } + return false + +} + +// getOCIImageArtifactTypeForGhAction retrieves the artifact type from a GitHub Action's OCI manifest. +// This function is used to determine if an action is immutable by checking its artifact type. +// +// Example usage: +// +// # Immutable action (returns "application/vnd.github.actions.package.v1+json", nil) +// artifactType, err := getOCIImageArtifactTypeForGhAction("actions/checkout@v4.2.2") +// +// Returns: +// - artifactType: The artifact type string from the OCI manifest +// - error: An error if the action format is invalid or if there's a problem retrieving the manifest +func getOCIImageArtifactTypeForGhAction(action string) (string, error) { + + // Split the action into parts (e.g., "actions/checkout@v2" -> ["actions/checkout", "v2"]) + parts := strings.Split(action, "@") + if len(parts) != 2 { + return "", fmt.Errorf("invalid action format") + } + + // For bundled actions like github/codeql-action/analyze@v3, + // we only need the repository part (github/codeql-action) to check for immutability + actionPath := parts[0] + if strings.Count(parts[0], "/") > 1 { + pathParts := strings.Split(parts[0], "/") + actionPath = strings.Join(pathParts[:2], "/") + } + + // convert v1.x.x to 1.x.x which is + // use regexp to match tag version format and replace v in prefix + // as immutable actions image tag is in format 1.x.x (without v prefix) + // REF - https://github.com/actions/publish-immutable-action/issues/216#issuecomment-2549914784 + if semanticTagRegex.MatchString(parts[1]) { + // v1.x.x -> 1.x.x + parts[1] = strings.TrimPrefix(parts[1], "v") + } + + // Convert GitHub action to GHCR image reference using proper OCI reference format + image := fmt.Sprintf("ghcr.io/%s:%s", actionPath, parts[1]) + imageManifest, err := getOCIManifestForImage(image) + if err != nil { + return "", err + } + + var ociManifest ociManifest + err = json.Unmarshal([]byte(imageManifest), &ociManifest) + if err != nil { + return "", err + } + return ociManifest.ArtifactType, nil +} + +// getOCIManifestForImage retrieves the artifact type from the OCI image manifest +func getOCIManifestForImage(imageRef string) (string, error) { + + // Parse the image reference + ref, err := name.ParseReference(imageRef) + if err != nil { + return "", fmt.Errorf("error parsing reference: %v", err) + } + + // Get the image manifest + desc, err := remote.Get(ref, remote.WithTransport(http.DefaultTransport)) + if err != nil { + return "", fmt.Errorf("error getting manifest: %v", err) + } + + return string(desc.Manifest), nil +} diff --git a/remediation/workflow/pin/action_image_manifest_test.go b/remediation/workflow/pin/action_image_manifest_test.go new file mode 100644 index 000000000..d16af7de3 --- /dev/null +++ b/remediation/workflow/pin/action_image_manifest_test.go @@ -0,0 +1,163 @@ +package pin + +import ( + "crypto/tls" + "io/ioutil" + "net/http" + "net/http/httptest" + "path/filepath" + "strings" + "testing" +) + +type customTransport struct { + base http.RoundTripper + baseURL string +} + +func (t *customTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if strings.Contains(req.URL.Host, "ghcr.io") { + req2 := req.Clone(req.Context()) + req2.URL.Scheme = "https" + req2.URL.Host = strings.TrimPrefix(t.baseURL, "https://") + return t.base.RoundTrip(req2) + } + return t.base.RoundTrip(req) +} + +func createGhesTestServer(t *testing.T) *httptest.Server { + return httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Content-Type", "application/json") + + if !strings.Contains(r.Host, "ghcr.io") { + w.WriteHeader(http.StatusNotFound) + return + } + // Mock manifest endpoints + switch r.URL.Path { + + case "/v2/": // simulate ping request + w.WriteHeader(http.StatusOK) + + case "/token": + // for immutable actions, since image will be present in registry...it returns 200 OK with token + // otherwise it returns 403 Forbidden + scope := r.URL.Query().Get("scope") + switch scope { + case "repository:actions/checkout:pull": + fallthrough + case "repository:step-security/wait-for-secrets:pull": + + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"token": "test-token", "access_token": "test-token"}`)) + default: + w.WriteHeader(http.StatusForbidden) + w.Write([]byte(`{"errors": [{"code": "DENIED", "message": "requested access to the resource is denied"}]}`)) + } + + case "/v2/actions/checkout/manifests/4.2.2": + fallthrough + case "/v2/actions/checkout/manifests/1.2.0": + fallthrough + case "/v2/step-security/wait-for-secrets/manifests/1.2.0": + w.Write(readHttpResponseForAction(t, r.URL.Path)) + case "/v2/actions/checkout/manifests/1.2.3": // since this version doesn't exist + fallthrough + default: + w.WriteHeader(http.StatusNotFound) + w.Write(readHttpResponseForAction(t, "default")) + } + })) +} + +func Test_isImmutableAction(t *testing.T) { + // Create test server that mocks GitHub Container Registry + server := createGhesTestServer(t) + defer server.Close() + + // Create a custom client that redirects ghcr.io to our test server + originalClient := http.DefaultClient + http.DefaultClient = &http.Client{ + Transport: &customTransport{ + base: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + baseURL: server.URL, + }, + } + + // update default transport + OriginalTransport := http.DefaultTransport + http.DefaultTransport = http.DefaultClient.Transport + + defer func() { + http.DefaultClient = originalClient + http.DefaultTransport = OriginalTransport + }() + + tests := []struct { + name string + action string + want bool + }{ + { + name: "immutable action - 1", + action: "actions/checkout@v4.2.2", + want: true, + }, + { + name: "immutable action - 2", + action: "step-security/wait-for-secrets@v1.2.0", + want: true, + }, + { + name: "non immutable action(valid action)", + action: "sailikhith-stepsecurity/hello-action@v1.0.2", + want: false, + }, + { + name: "non immutable action(invalid action)", + action: "sailikhith-stepsecurity/no-such-action@v1.0.2", + want: false, + }, + { + name: " action with release tag doesn't exist", + action: "actions/checkout@1.2.3", + want: false, + }, + { + name: "invalid action format", + action: "invalid-format", + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + got := IsImmutableAction(tt.action) + if got != tt.want { + t.Errorf("isImmutableAction() = %v, want %v", got, tt.want) + } + }) + } +} + +func readHttpResponseForAction(t *testing.T, actionPath string) []byte { + // remove v2 prefix from action path + actionPath = strings.TrimPrefix(actionPath, "/v2/") + + fileName := strings.ReplaceAll(actionPath, "/", "-") + ".json" + testFilesDir := "../../../testfiles/pinactions/immutableActionResponses/" + respFilePath := filepath.Join(testFilesDir, fileName) + + resp, err := ioutil.ReadFile(respFilePath) + if err != nil { + t.Fatalf("error reading test file:%v", err) + } + + return resp +} diff --git a/remediation/workflow/pin/pinactions.go b/remediation/workflow/pin/pinactions.go index b8aef31c5..8f3837555 100644 --- a/remediation/workflow/pin/pinactions.go +++ b/remediation/workflow/pin/pinactions.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "regexp" "strings" "github.com/google/go-github/v40/github" @@ -43,7 +44,7 @@ func PinAction(action, inputYaml string) (string, bool) { return inputYaml, updated // Cannot pin local actions and docker actions } - if isAbsolute(action) { + if isAbsolute(action) || IsImmutableAction(action) { return inputYaml, updated } leftOfAt := strings.Split(action, "@") @@ -74,8 +75,32 @@ func PinAction(action, inputYaml string) (string, bool) { } pinnedAction := fmt.Sprintf("%s@%s # %s", leftOfAt[0], commitSHA, tagOrBranch) + + // if the action with version is immutable, then pin the action with version instead of sha + pinnedActionWithVersion := fmt.Sprintf("%s@%s", leftOfAt[0], tagOrBranch) + if semanticTagRegex.MatchString(tagOrBranch) && IsImmutableAction(pinnedActionWithVersion) { + pinnedAction = pinnedActionWithVersion + } + updated = !strings.EqualFold(action, pinnedAction) - inputYaml = strings.ReplaceAll(inputYaml, action, pinnedAction) + + // strings.ReplaceAll is not suitable here because it would incorrectly replace substrings + // For example, if we want to replace "actions/checkout@v1" to "actions/checkout@v1.2.3", it would also incorrectly match and replace in "actions/checkout@v1.2.3" + // making new string to "actions/checkout@v1.2.3.2.3" + // + // Instead, we use a regex pattern that ensures we only replace complete action references: + // Pattern: (@)($|\s|"|') + // - Group 1 (@): Captures the exact action reference + // - Group 2 ($|\s|"|'): Captures the delimiter that follows (end of line, whitespace, or quotes) + // + // Examples: + // - "actions/checkout@v1.2.3" - No match (no delimiter after v1) + // - "actions/checkout@v1 " - Matches (space delimiter) + // - "actions/checkout@v1"" - Matches (quote delimiter) + // - "actions/checkout@v1" - Matches (quote delimiter) + // - "actions/checkout@v1\n" - Matches (newline is considered whitespace \s) + actionRegex := regexp.MustCompile(`(` + regexp.QuoteMeta(action) + `)($|\s|"|')`) + inputYaml = actionRegex.ReplaceAllString(inputYaml, pinnedAction+"$2") yamlWithPreviousActionCommentsRemoved, wasModified := removePreviousActionComments(pinnedAction, inputYaml) if wasModified { return yamlWithPreviousActionCommentsRemoved, updated diff --git a/remediation/workflow/pin/pinactions_test.go b/remediation/workflow/pin/pinactions_test.go index a4872be77..3e7c0ef8b 100644 --- a/remediation/workflow/pin/pinactions_test.go +++ b/remediation/workflow/pin/pinactions_test.go @@ -3,7 +3,9 @@ package pin import ( "io/ioutil" "log" + "net/http" "path" + "strings" "testing" "github.com/jarcoal/httpmock" @@ -171,6 +173,95 @@ func TestPinActions(t *testing.T) { } ]`)) + httpmock.RegisterResponder("GET", "https://api.github.com/repos/github/codeql-action/commits/v3", + httpmock.NewStringResponder(200, `d68b2d4edb4189fd2a5366ac14e72027bd4b37dd`)) + + httpmock.RegisterResponder("GET", "https://api.github.com/repos/github/codeql-action/git/matching-refs/tags/v3.", + httpmock.NewStringResponder(200, + `[ + { + "ref": "refs/tags/v3.28.2", + "object": { + "sha": "d68b2d4edb4189fd2a5366ac14e72027bd4b37dd", + "type": "commit" + } + } + ]`)) + + // mock ping response + httpmock.RegisterResponder("GET", "https://ghcr.io/v2/", + httpmock.NewStringResponder(200, ``)) + + // Mock token endpoints + httpmock.RegisterResponder("GET", "https://ghcr.io/token", + func(req *http.Request) (*http.Response, error) { + scope := req.URL.Query().Get("scope") + switch scope { + // Following are the ones which simulate the image existance in ghcr + case "repository:actions/checkout:pull", + "repository:step-security/wait-for-secrets:pull", + "repository:actions/setup-node:pull", + "repository:peter-evans/close-issue:pull", + "repository:borales/actions-yarn:pull", + "repository:JS-DevTools/npm-publish:pull", + "repository:elgohr/Publish-Docker-Github-Action:pull", + "repository:brandedoutcast/publish-nuget:pull", + "repository:rohith/publish-nuget:pull", + "repository:github/codeql-action:pull": + return httpmock.NewJsonResponse(http.StatusOK, map[string]string{ + "token": "test-token", + "access_token": "test-token", + }) + default: + return httpmock.NewJsonResponse(http.StatusForbidden, map[string]interface{}{ + "errors": []map[string]string{ + { + "code": "DENIED", + "message": "requested access to the resource is denied", + }, + }, + }) + } + }) + + // Mock manifest endpoints for specific versions and commit hashes + manifestResponders := []string{ + // the following list will contain the list of actions with versions + // which are mocked to be immutable + "actions/checkout@v1.2.0", + "github/codeql-action@v3.28.2", + } + + for _, action := range manifestResponders { + actionPath := strings.Split(action, "@")[0] + version := strings.TrimPrefix(strings.Split(action, "@")[1], "v") + // Mock manifest response so that we can treat action as immutable + httpmock.RegisterResponder("GET", "https://ghcr.io/v2/"+actionPath+"/manifests/"+version, + func(req *http.Request) (*http.Response, error) { + return httpmock.NewJsonResponse(http.StatusOK, map[string]interface{}{ + "schemaVersion": 2, + "mediaType": "application/vnd.github.actions.package.v1+json", + "artifactType": "application/vnd.github.actions.package.v1+json", + "config": map[string]interface{}{ + "mediaType": "application/vnd.github.actions.package.v1+json", + }, + }) + }) + } + + // Default manifest response for non-existent tags + httpmock.RegisterResponder("GET", `=~^https://ghcr\.io/v2/.*/manifests/.*`, + func(req *http.Request) (*http.Response, error) { + return httpmock.NewJsonResponse(http.StatusNotFound, map[string]interface{}{ + "errors": []map[string]string{ + { + "code": "MANIFEST_UNKNOWN", + "message": "manifest unknown", + }, + }, + }) + }) + tests := []struct { fileName string wantUpdated bool @@ -184,6 +275,7 @@ func TestPinActions(t *testing.T) { {fileName: "multipleactions.yml", wantUpdated: true}, {fileName: "actionwithcomment.yml", wantUpdated: true}, {fileName: "repeatedactionwithcomment.yml", wantUpdated: true}, + {fileName: "immutableaction-1.yml", wantUpdated: true}, } for _, tt := range tests { input, err := ioutil.ReadFile(path.Join(inputDirectory, tt.fileName)) diff --git a/testfiles/pinactions/immutableActionResponses/actions-checkout-manifests-4.2.2.json b/testfiles/pinactions/immutableActionResponses/actions-checkout-manifests-4.2.2.json new file mode 100644 index 000000000..d93e66789 --- /dev/null +++ b/testfiles/pinactions/immutableActionResponses/actions-checkout-manifests-4.2.2.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.github.actions.package.v1+json", + "config": { + "mediaType": "application/vnd.oci.empty.v1+json", + "size": 2, + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" + }, + "layers": [ + { + "mediaType": "application/vnd.github.actions.package.layer.v1.tar+gzip", + "size": 424913, + "digest": "sha256:309d5e1a7604a5e688e2b55a6763e4109eb07349dca6d3c44e85c57ab2bb4f3f", + "annotations": { + "org.opencontainers.image.title": "actions-checkout_4.2.2.tar.gz" + } + }, + { + "mediaType": "application/vnd.github.actions.package.layer.v1.zip", + "size": 546845, + "digest": "sha256:e9808fe811a75b46234757f9566987635166bca838090fcbc8021a0d45c737b3", + "annotations": { + "org.opencontainers.image.title": "actions-checkout_4.2.2.zip" + } + } + ], + "annotations": { + "org.opencontainers.image.created": "2024-10-23T14:46:13.071Z", + "action.tar.gz.digest": "sha256:309d5e1a7604a5e688e2b55a6763e4109eb07349dca6d3c44e85c57ab2bb4f3f", + "action.zip.digest": "sha256:e9808fe811a75b46234757f9566987635166bca838090fcbc8021a0d45c737b3", + "com.github.package.type": "actions_oci_pkg", + "com.github.package.version": "4.2.2", + "com.github.source.repo.id": "197814629", + "com.github.source.repo.owner.id": "44036562", + "com.github.source.commit": "11bd71901bbe5b1630ceea73d27597364c9af683" + } +} \ No newline at end of file diff --git a/testfiles/pinactions/immutableActionResponses/default.json b/testfiles/pinactions/immutableActionResponses/default.json new file mode 100644 index 000000000..d8e11ba40 --- /dev/null +++ b/testfiles/pinactions/immutableActionResponses/default.json @@ -0,0 +1,8 @@ +{ + "errors":[ + { + "code":"MANIFEST_UNKNOWN", + "message":"manifest unknown" + } + ] +} \ No newline at end of file diff --git a/testfiles/pinactions/immutableActionResponses/step-security-wait-for-secrets-manifests-1.2.0.json b/testfiles/pinactions/immutableActionResponses/step-security-wait-for-secrets-manifests-1.2.0.json new file mode 100644 index 000000000..d85d31251 --- /dev/null +++ b/testfiles/pinactions/immutableActionResponses/step-security-wait-for-secrets-manifests-1.2.0.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "artifactType": "application/vnd.github.actions.package.v1+json", + "config": { + "mediaType": "application/vnd.oci.empty.v1+json", + "size": 2, + "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a" + }, + "layers": [ + { + "mediaType": "application/vnd.github.actions.package.layer.v1.tar+gzip", + "size": 689381, + "digest": "sha256:6390cea2d46095ef08dd2746d4323b11b7d1190d7e9ad9ef4a23b8ee5481d295", + "annotations": { + "org.opencontainers.image.title": "step-security-wait-for-secrets_1.2.0.tar.gz" + } + }, + { + "mediaType": "application/vnd.github.actions.package.layer.v1.zip", + "size": 723541, + "digest": "sha256:56f5004c2b1bff0f148c3998aa0f5bd47a315a602428031b8ba72d881edfb429", + "annotations": { + "org.opencontainers.image.title": "step-security-wait-for-secrets_1.2.0.zip" + } + } + ], + "annotations": { + "org.opencontainers.image.created": "2024-10-24T05:13:19.501Z", + "action.tar.gz.digest": "sha256:6390cea2d46095ef08dd2746d4323b11b7d1190d7e9ad9ef4a23b8ee5481d295", + "action.zip.digest": "sha256:56f5004c2b1bff0f148c3998aa0f5bd47a315a602428031b8ba72d881edfb429", + "com.github.package.type": "actions_oci_pkg", + "com.github.package.version": "1.2.0", + "com.github.source.repo.id": "498456330", + "com.github.source.repo.owner.id": "88700172", + "com.github.source.commit": "5809f7d044804a5a1d43217fa8f3e855939fc9ef" + } +} \ No newline at end of file diff --git a/testfiles/pinactions/input/immutableaction-1.yml b/testfiles/pinactions/input/immutableaction-1.yml new file mode 100644 index 000000000..3740d1637 --- /dev/null +++ b/testfiles/pinactions/input/immutableaction-1.yml @@ -0,0 +1,12 @@ +name: Integration Test Github +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: github/codeql-action/analyze@v3 + - uses: borales/actions-yarn@v2.3.0 + with: + auth-token: ${{ secrets.GITHUB_TOKEN }} + registry-url: npm.pkg.github.com diff --git a/testfiles/pinactions/output/actionwithcomment.yml b/testfiles/pinactions/output/actionwithcomment.yml index a1131c832..89388bb10 100644 --- a/testfiles/pinactions/output/actionwithcomment.yml +++ b/testfiles/pinactions/output/actionwithcomment.yml @@ -16,7 +16,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 - uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6 with: node-version: 10 diff --git a/testfiles/pinactions/output/dockeraction.yml b/testfiles/pinactions/output/dockeraction.yml index 6e3948640..1413f1e52 100644 --- a/testfiles/pinactions/output/dockeraction.yml +++ b/testfiles/pinactions/output/dockeraction.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + uses: actions/checkout@v1.2.0 - name: Integration test uses: docker://ghcr.io/step-security/integration-test/int:latest env: diff --git a/testfiles/pinactions/output/immutableaction-1.yml b/testfiles/pinactions/output/immutableaction-1.yml new file mode 100644 index 000000000..b007a0e7d --- /dev/null +++ b/testfiles/pinactions/output/immutableaction-1.yml @@ -0,0 +1,12 @@ +name: Integration Test Github +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1.2.0 + - uses: github/codeql-action/analyze@v3.28.2 + - uses: borales/actions-yarn@4965e1a0f0ae9c422a9a5748ebd1fb5e097d22b9 # v2.3.0 + with: + auth-token: ${{ secrets.GITHUB_TOKEN }} + registry-url: npm.pkg.github.com diff --git a/testfiles/pinactions/output/localaction.yml b/testfiles/pinactions/output/localaction.yml index c6d98688b..f79109707 100644 --- a/testfiles/pinactions/output/localaction.yml +++ b/testfiles/pinactions/output/localaction.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6 with: node-version: 12.x - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 - run: npm ci - run: npm run build - run: npm run format-check @@ -32,7 +32,7 @@ jobs: steps: # Clone this repo - name: Checkout - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + uses: actions/checkout@v1.2.0 # Basic checkout - name: Checkout basic @@ -150,7 +150,7 @@ jobs: steps: # Clone this repo - name: Checkout - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + uses: actions/checkout@v1.2.0 # Basic checkout using git - name: Checkout basic @@ -182,7 +182,7 @@ jobs: steps: # Clone this repo - name: Checkout - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + uses: actions/checkout@v1.2.0 # Basic checkout using git - name: Checkout basic diff --git a/testfiles/pinactions/output/multipleactions.yml b/testfiles/pinactions/output/multipleactions.yml index 9b9abf9c9..1e4a76422 100644 --- a/testfiles/pinactions/output/multipleactions.yml +++ b/testfiles/pinactions/output/multipleactions.yml @@ -4,7 +4,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 - uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6 with: node-version: 10 diff --git a/testfiles/pinactions/output/multiplejobs.yml b/testfiles/pinactions/output/multiplejobs.yml index 6d2d47211..435f8b621 100644 --- a/testfiles/pinactions/output/multiplejobs.yml +++ b/testfiles/pinactions/output/multiplejobs.yml @@ -8,7 +8,7 @@ jobs: name: build, pack & publish runs-on: ubuntu-latest steps: - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 # - name: Setup dotnet # uses: actions/setup-dotnet@v1 @@ -27,7 +27,7 @@ jobs: name: build, pack & publish runs-on: ubuntu-latest steps: - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 # - name: Setup dotnet # uses: actions/setup-dotnet@v1 diff --git a/testfiles/pinactions/output/repeatedactionwithcomment.yml b/testfiles/pinactions/output/repeatedactionwithcomment.yml index dbd50839e..0cfd8a115 100644 --- a/testfiles/pinactions/output/repeatedactionwithcomment.yml +++ b/testfiles/pinactions/output/repeatedactionwithcomment.yml @@ -16,7 +16,7 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@544eadc6bf3d226fd7a7a9f0dc5b5bf7ca0675b9 # v1.2.0 + - uses: actions/checkout@v1.2.0 - uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1.4.6 with: node-version: 10