From b62e68200ea24603c696d76f87a41a01a818ca86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matou=C5=A1=20Dzivjak?= <matousdzivjak@gmail.com>
Date: Thu, 5 Sep 2019 09:10:46 +0200
Subject: [PATCH] fix(github-actions): handle updates of yaml file defined
 actions (#4420)

---
 lib/config/definitions.ts                     |  5 ++-
 lib/manager/github-actions/extract.ts         |  6 +++-
 lib/manager/github-actions/update.ts          |  2 +-
 renovate-schema.json                          |  5 ++-
 .../__snapshots__/extract.spec.ts.snap        | 26 +++++++++++++++
 .../github-actions/_fixtures/workflow.yml.1   | 32 +++++++++++++++++++
 test/manager/github-actions/extract.spec.ts   | 10 ++++++
 test/manager/github-actions/update.spec.ts    | 31 ++++++++++++++++++
 8 files changed, 113 insertions(+), 4 deletions(-)
 create mode 100644 test/manager/github-actions/_fixtures/workflow.yml.1

diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts
index a617a1563a..d5fe5adb66 100644
--- a/lib/config/definitions.ts
+++ b/lib/config/definitions.ts
@@ -1600,7 +1600,10 @@ const options: RenovateOptions[] = [
     stage: 'package',
     type: 'object',
     default: {
-      fileMatch: ['^\\.github/main.workflow$'],
+      fileMatch: [
+        '^\\.github/main.workflow$',
+        '^\\.github/workflows/[^/]+\\.ya?ml$',
+      ],
       pinDigests: true,
     },
     mergeable: true,
diff --git a/lib/manager/github-actions/extract.ts b/lib/manager/github-actions/extract.ts
index 68ef79f86a..96eac846ed 100644
--- a/lib/manager/github-actions/extract.ts
+++ b/lib/manager/github-actions/extract.ts
@@ -7,7 +7,11 @@ export function extractPackageFile(content: string): PackageFile | null {
   const deps: PackageDependency[] = [];
   let lineNumber = 0;
   for (const line of content.split('\n')) {
-    const match = line.match(/^\s+uses = "docker:\/\/([^"]+)"\s*$/);
+    // old github actions syntax will be deprecated on September 30, 2019
+    // after that, the first line can be removed
+    const match =
+      line.match(/^\s+uses = "docker:\/\/([^"]+)"\s*$/) ||
+      line.match(/^\s+uses: docker:\/\/([^"]+)\s*$/);
     if (match) {
       const currentFrom = match[1];
       const dep = getDep(currentFrom);
diff --git a/lib/manager/github-actions/update.ts b/lib/manager/github-actions/update.ts
index 806c53a3ac..3e66ffc091 100644
--- a/lib/manager/github-actions/update.ts
+++ b/lib/manager/github-actions/update.ts
@@ -11,7 +11,7 @@ export function updateDependency(
     logger.debug(`github-actions.updateDependency(): ${newFrom}`);
     const lines = fileContent.split('\n');
     const lineToChange = lines[upgrade.managerData.lineNumber];
-    const imageLine = new RegExp(/^(\s+uses = "docker:\/\/)[^"]+("\s*)$/);
+    const imageLine = new RegExp(/^(.+docker:\/\/)[^"]+("\s*)?$/);
     if (!lineToChange.match(imageLine)) {
       logger.debug('No image line found');
       return null;
diff --git a/renovate-schema.json b/renovate-schema.json
index cea32222b8..3a739846cd 100644
--- a/renovate-schema.json
+++ b/renovate-schema.json
@@ -1053,7 +1053,10 @@
       "description": "Configuration object for GitHub Actions workflow renovation. Also inherits settings from `docker` object.",
       "type": "object",
       "default": {
-        "fileMatch": ["^\\.github/main.workflow$"],
+        "fileMatch": [
+          "^\\.github/main.workflow$",
+          "^\\.github/workflows/[^/]+\\.ya?ml$"
+        ],
         "pinDigests": true
       },
       "$ref": "#"
diff --git a/test/manager/github-actions/__snapshots__/extract.spec.ts.snap b/test/manager/github-actions/__snapshots__/extract.spec.ts.snap
index 350f74b4f3..11c3c4551e 100644
--- a/test/manager/github-actions/__snapshots__/extract.spec.ts.snap
+++ b/test/manager/github-actions/__snapshots__/extract.spec.ts.snap
@@ -25,3 +25,29 @@ Array [
   },
 ]
 `;
+
+exports[`lib/manager/github-actions/extract extractPackageFile() extracts multiple image lines from yaml configuration file 1`] = `
+Array [
+  Object {
+    "currentDigest": undefined,
+    "currentValue": undefined,
+    "datasource": "docker",
+    "depName": "replicated/dockerfilelint",
+    "managerData": Object {
+      "lineNumber": 17,
+    },
+    "versionScheme": "docker",
+  },
+  Object {
+    "commitMessageTopic": "Node.js",
+    "currentDigest": "sha256:7b65413af120ec5328077775022c78101f103258a1876ec2f83890bce416e896",
+    "currentValue": "6",
+    "datasource": "docker",
+    "depName": "node",
+    "managerData": Object {
+      "lineNumber": 31,
+    },
+    "versionScheme": "docker",
+  },
+]
+`;
diff --git a/test/manager/github-actions/_fixtures/workflow.yml.1 b/test/manager/github-actions/_fixtures/workflow.yml.1
new file mode 100644
index 0000000000..1513408eee
--- /dev/null
+++ b/test/manager/github-actions/_fixtures/workflow.yml.1
@@ -0,0 +1,32 @@
+name: Run linters
+
+on: [push]
+
+jobs:
+  shell_lint:
+    name: Shell lint
+    runs-on: ubuntu-latest
+    steps:
+      - name: Shell lint
+        uses: actions/bin/shellcheck@master
+        run: ./entrypoint.sh
+  docker_lint:
+    name: Docker lint
+    runs-on: ubuntu-latest
+    steps:
+      - name: Docker lint
+        uses: docker://replicated/dockerfilelint
+        run: Dockerfile
+  build:
+    name: Build
+    runs-on: ubuntu-latest
+    steps:
+      - name: Build
+        uses: actions/docker/cli@master
+        run: build -t conventional-commits .
+  node_6_test:
+    name: Node 6 Test
+    runs-on: ubuntu-latest
+    steps:
+      - name: Node 6 test
+        uses: docker://node:6@sha256:7b65413af120ec5328077775022c78101f103258a1876ec2f83890bce416e896
diff --git a/test/manager/github-actions/extract.spec.ts b/test/manager/github-actions/extract.spec.ts
index 73b920be4d..a6cffc6dcc 100644
--- a/test/manager/github-actions/extract.spec.ts
+++ b/test/manager/github-actions/extract.spec.ts
@@ -6,6 +6,11 @@ const workflow1 = readFileSync(
   'utf8'
 );
 
+const workflow2 = readFileSync(
+  'test/manager/github-actions/_fixtures/workflow.yml.1',
+  'utf8'
+);
+
 describe('lib/manager/github-actions/extract', () => {
   describe('extractPackageFile()', () => {
     it('returns null for empty', () => {
@@ -16,5 +21,10 @@ describe('lib/manager/github-actions/extract', () => {
       expect(res.deps).toMatchSnapshot();
       expect(res.deps).toHaveLength(2);
     });
+    it('extracts multiple image lines from yaml configuration file', () => {
+      const res = extractPackageFile(workflow2);
+      expect(res.deps).toMatchSnapshot();
+      expect(res.deps).toHaveLength(2);
+    });
   });
 });
diff --git a/test/manager/github-actions/update.spec.ts b/test/manager/github-actions/update.spec.ts
index b260273f3e..ba9067b483 100644
--- a/test/manager/github-actions/update.spec.ts
+++ b/test/manager/github-actions/update.spec.ts
@@ -6,6 +6,11 @@ const workflow1 = readFileSync(
   'utf8'
 );
 
+const workflow2 = readFileSync(
+  'test/manager/github-actions/_fixtures/workflow.yml.1',
+  'utf8'
+);
+
 describe('manager/github-actions/update', () => {
   describe('updateDependency', () => {
     it('replaces existing uses value', () => {
@@ -38,5 +43,31 @@ describe('manager/github-actions/update', () => {
       const res = updateDependency(null, null);
       expect(res).toBeNull();
     });
+    it('replaces existing uses value in yaml file', () => {
+      const upgrade = {
+        managerData: { lineNumber: 17 },
+        depName: 'replicated/dockerfilelint',
+        newDigest: 'sha256:abcdefghijklmnop',
+      };
+      const res = updateDependency(workflow2, upgrade);
+      expect(res).not.toEqual(workflow2);
+      expect(res.includes(upgrade.newDigest)).toBe(true);
+    });
+    it('returns same in yaml file', () => {
+      const upgrade = {
+        managerData: { lineNumber: 17 },
+        depName: 'replicated/dockerfilelint',
+      };
+      const res = updateDependency(workflow2, upgrade);
+      expect(res).toEqual(workflow2);
+    });
+    it('returns null if mismatch in yaml file', () => {
+      const upgrade = {
+        managerData: { lineNumber: 12 },
+        newFrom: 'registry:2.6.2@sha256:abcdefghijklmnop',
+      };
+      const res = updateDependency(workflow2, upgrade);
+      expect(res).toBeNull();
+    });
   });
 });
-- 
GitLab