diff --git a/README.md b/README.md index 9dd3357..4e2f3c1 100644 --- a/README.md +++ b/README.md @@ -1 +1,58 @@ -# docker-repo-scan-action +# Scan Docker Tags Action + +Scan a Docker image repository for recently-updated tags. This is helpful e.g. when your project relies on a certain Docker image and you want to rebuild it every time the base image is updated. + + +## Example + +This example workflow scans an image every 15 minutes and prints all tags that were updated since the last run. + +```yml +name: Scan Docker Repo +on: + schedule: + - cron: '*/15 * * * *' + +jobs: + scan: + name: List Recent Updates + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Scan Docker Repository + uses: dhet/docker-repo-scan-action@v1 + with: + image: mhart/alpine-node + max-age-minutes: 15 + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_PASSWORD }} + id: scan + - name: Print + run: "echo 'Recent updates: ${{ steps.scan.outputs.tags }}'" +``` +**Output:** +``` +Recent updates: slim-14.4,slim-14,slim,latest +``` + +## Required Inputs + +|Parameter|Description +|---|--- +|`image`|The Docker image to scan (sans tag), e.g. "mhart/alpine-node" +|`max-age-minutes`|The maximum age of tags to consider. Older tags are discarded. E.g. `30` for 30 minutes +|`username`|The username used to authenticate against the Docker repository +|`password`|The password used to authenticate against the Docker repository + + +## Optional Inputs +|Parameter|Description|Default +|---|---|--- +|`tag-regex`|A regular expression for filtering tags. Backslashes need to be escaped. E.g. `\\d+\\.\\d+$` matches semver, `latest` matches only the "latest" tag.|`.*` +|`repo-url`|The URL of the Docker registry. Defaults to Dockerhub.|`https://hub.docker.com` + + +## Outputs +The only output this action exposes is the `tags` output. `tags` is a comma-separated list of all image tags that have +changed in the specified time frame. The list is sorted by date in ascending order. E.g. `v1.0.7,v1.0.8,latest`. diff --git a/action.yml b/action.yml index c09a8c2..f53bfe5 100644 --- a/action.yml +++ b/action.yml @@ -4,6 +4,9 @@ inputs: image: description: The Docker image to scan (sans tag), e.g. "mhart/alpine-node" required: true + max-age-minutes: + description: The maximum age of tags in minutes. Older tags are discarded + required: true username: description: The username used to authenticate against the Docker repository required: true @@ -16,24 +19,18 @@ inputs: semver, `latest` matches only the "latest" tag required: false default: '.*' - max-age-minutes: - description: The maximum age of tags in minutes. Older tags are discarded. Defaults to 30 minutes - required: false - default: '30' repo-url: description: The URL of the Docker registry. Defaults to Dockerhub (https://hub.docker.com) required: false default: https://hub.docker.com - output-delimiter: - description: The delimiter to use for the output. Defaults to "," - required: false - default: ',' outputs: tags: - description: A list of all image tags that have changed in the specified time frame + description: > + A comma-separated list of all image tags that have changed in the specified time frame, sorted by date in + ascending order (oldest first) runs: using: node12 main: dist/index.js branding: - icon: rotate-cw - color: yellow + icon: refresh-cw + color: blue diff --git a/index.js b/index.js index c032fc1..fd8ba9a 100644 --- a/index.js +++ b/index.js @@ -2,15 +2,14 @@ const fetch = require("node-fetch") const core = require('@actions/core'); -let repoUrl, image, regex, maxAgeMinutes, outputDelimiter, username, password +let repoUrl, image, regex, maxAgeMinutes, username, password try { - repoUrl = core.getInput("repo-url") - image = core.getInput("image") - regex = new RegExp(core.getInput("tag-regex")) + repoUrl = core.getInput("repo-url") + image = core.getInput("image") + regex = new RegExp(core.getInput("tag-regex")) maxAgeMinutes = parseInt(core.getInput("max-age-minutes")) - outputDelimiter = core.getInput("output-delimiter") - username = core.getInput("username") - password = core.getInput("password") + username = core.getInput("username") + password = core.getInput("password") } catch (err) { const msg = "Failed to initialize action: " + err.message core.setFailed(msg) @@ -41,7 +40,7 @@ fetch(`${repoUrl}/v2/users/login/`, { .filter(filterOldEntry) .filter(el => regex.test(el.name)) .map(el => el.name) - .join(outputDelimiter) + .join(",") core.setOutput("tags", tags) }) @@ -68,7 +67,7 @@ function byDateAsc(a, b) { } function filterOldEntry(entry) { - const now = new Date() + const now = new Date() const entryDate = new Date(entry.last_updated) return (now - entryDate) < maxAgeMinutes * 60 * 1000 } \ No newline at end of file