From 17191dc379b3ede512aef7994d8cc2bef062caeb Mon Sep 17 00:00:00 2001 From: Barry Date: Sat, 9 May 2020 21:52:58 +0100 Subject: [PATCH 1/6] Add compressOnly mode and also update README to discuss handle pull requests from forks --- README.md | 69 +++++++++++++++++++++++++++++++++++++++-- entrypoint.js | 42 +++++++++++++------------ src/config.js | 6 ++-- src/constants.js | 4 ++- src/image-processing.js | 5 +-- src/index.js | 15 ++++++++- 6 files changed, 112 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index ddf366b8..1bb3db9d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Image Actions -Image Actions automatically compress JPEG, PNG and WebP images in GitHub Pull Requests. +Image Actions automatically compress JPEG, PNG and WebP images in GitHub Pull Requests within the same repository. + +It can also run in "Compress Only" mode to allow this to be used for non-Pull Requests, and also for Pull Requests from forks. - **Fast, efficient and near-lossless compression** - Uses the best image compression algorithms available: [mozjpeg](https://github.com/mozilla/mozjpeg) and [libvips](https://github.com/libvips/libvips) @@ -20,6 +22,8 @@ name: Compress images on: pull_request jobs: build: + # Only run on Pull Requests within the same repository, and not from forks + if: github.event.pull_request.head.repo.full_name == github.repository name: calibreapp/image-actions runs-on: ubuntu-latest steps: @@ -32,7 +36,7 @@ jobs: githubToken: ${{ secrets.GITHUB_TOKEN }} ``` -_The `GITHUB_TOKEN` secret is [automatically generated by GitHub](https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret). This automatic token is [scoped only to the repository that is currently running the action.](https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions)_ +_The `GITHUB_TOKEN` secret is [automatically generated by GitHub](https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret). This automatic token is [scoped only to the repository that is currently running the action.](https://help.github.com/en/articles/virtual-environments-for-github-actions#token-permissions). What this means is that by default the Action cannot update pull requests initiated from forked repositories._ ## Configuration @@ -49,6 +53,7 @@ _The `GITHUB_TOKEN` secret is [automatically generated by GitHub](https://help.g webpQuality: "80" ignorePaths: "node_modules/**,build" # No spaces allowed + compressOnly: false ``` If you would like to modify the defaults, update the `.github/workflows/calibreapp-image-actions.yml` file by adding arguments to the action: @@ -57,9 +62,12 @@ If you would like to modify the defaults, update the `.github/workflows/calibrea - [pngQuality](http://sharp.pixelplumbing.com/en/stable/api-output/#png): Number, integer 1-100, default 80 stored in a string - [webpQuality](http://sharp.pixelplumbing.com/en/stable/api-output/#webp): Number, integer 1-100, default 80 stored in a string - `ignorePaths`: a comma separated string with [globbing](https://www.npmjs.com/package/glob) support of paths to ignore when looking for images to compress +- `compressOnly`: Boolean, true or false, default false _The `jpegQuality`, `pngQuality` and `webpQuality` config keys will be delivered directly into [sharp’s](http://sharp.pixelplumbing.com) `toFormat` method._ +The markdown added to a pull request is outputted to `markdown` output parameter. In that case it is advised to add an `id` attribute to reference this (see [Handling pull requests from forked repos](./#handling-pull-requests-from-forked-repos) example below). + Previous versions of image-actions used `.github/calibre/image-actions.yml` for configuration. We suggest that you migrate to the newest configuration format by reading the [migration steps](#migration-legacy-configuration) below. ### Running the action only when images are changed @@ -78,6 +86,63 @@ on: The above workflow will only run on a pull request when `jpg`, `png` or `webp` files are changed. +## Running just the compression + +By default this Action will add the updated image to the current pull request. It is also possible to set the `compressOnly` option to `true` to skip the commit, if you want to handle this separately - including for forks - see below. + +```yml + - name: Compress Images + uses: calibreapp/image-actions@master + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} + compressOnly: true +``` + +## Handling pull requests from forked repos + +GitHub actions, by default, do not have permission to alter forked repositories. This means this action, by default, only works for pull requests from branches in the same repository as the destination branch. + +You can replace the default `GITHUB_TOKEN` with a [personal access token (PAT)](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token#permissions-for-the-github_token) which does have permission for forked repositaries, but this introduces other security considerations (which is why it not available by default). + +Alternatively you can run this action only for Pull Requests for the current repo, which is advised when not using PATs to avoid wasting time and compute for compressions that will not be committed using the following syntax (as shown in the example yml files in this README): + +``` + if: github.event.pull_request.head.repo.full_name == github.repository +``` + +It is also possible to run an addition instance of this action in `compressOnly` mode on pushes to master, and then raise a new pull request for any images commited from a forked repositary pull request as shown in the below example which uses the [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub Action to open this new Pull Request (note this only raises a Pull Request if any fules are changed). + + +```yml +name: Compress images on Push to Master +on: + push: + branches: + - master +jobs: + build: + name: calibreapp/image-actions + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@master + + - name: Compress Images + id: calibre + uses: calibreapp/image-actions@master + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} + compressOnly: true + + - name: Create New Pull Request + uses: peter-evans/create-pull-request@master + with: + title: Compressed Images + branch-suffix: timestamp + commit-message: Compressed Images + body: ${{ steps.calibre.outputs.markdown }} +``` + ## Migrate legacy configuration - uses: docker://calibreapp/github-image-actions diff --git a/entrypoint.js b/entrypoint.js index 0db758f4..e2b2b1ca 100755 --- a/entrypoint.js +++ b/entrypoint.js @@ -1,6 +1,6 @@ #!/usr/bin/env node -const { GITHUB_TOKEN, GITHUB_EVENT_NAME } = require("./src/constants"); +const { GITHUB_TOKEN, GITHUB_EVENT_NAME, COMPRESS_ONLY } = require("./src/constants"); const githubEvent = require("./src/github-event"); const run = require("./src/index.js"); @@ -11,24 +11,28 @@ if (!GITHUB_TOKEN) { } const main = async () => { - // Bail out if the event that executed the action wasn’t a pull_request - if (GITHUB_EVENT_NAME !== "pull_request") { - console.log("::error:: This action only runs for pushes to PRs"); - process.exit(78); - } - - // Bail out if the pull_request event wasn't synchronize or opened - const event = await githubEvent(); - if (event.action !== "synchronize" && event.action !== "opened") { - console.log( - "::error:: Check run has action", - event.action, - ". Wants: synchronize or opened" - ); - process.exit(78); - } - - await run(); + + if (!COMPRESS_ONLY) { + + // Bail out if the event that executed the action wasn’t a pull_request + if (GITHUB_EVENT_NAME !== "pull_request") { + console.log("::error:: This action only runs for pushes to PRs"); + process.exit(78); + } + + // Bail out if the pull_request event wasn't synchronize or opened + const event = await githubEvent(); + if (event.action !== "synchronize" && event.action !== "opened") { + console.log( + "::error:: Check run has action", + event.action, + ". Wants: synchronize or opened" + ); + process.exit(78); + } + + await run(); + }; }; main(); diff --git a/src/config.js b/src/config.js index 1cb292bb..92fa451c 100644 --- a/src/config.js +++ b/src/config.js @@ -6,7 +6,8 @@ const { CONFIG_PATH, JPEG_QUALITY, PNG_QUALITY, WEBP_QUALITY, - IGNORE_PATHS + IGNORE_PATHS, + COMPRESS_ONLY } = require("./constants"); const getYamlConfig = async () => { @@ -23,7 +24,8 @@ const getConfig = async () => { jpeg: { quality: JPEG_QUALITY }, png: { quality: PNG_QUALITY }, webp: { quality: WEBP_QUALITY }, - ignorePaths: IGNORE_PATHS + ignorePaths: IGNORE_PATHS, + compressOnly: COMPRESS_ONLY }; const ymlConfig = await getYamlConfig(); diff --git a/src/constants.js b/src/constants.js index 763e1033..f2bf90af 100644 --- a/src/constants.js +++ b/src/constants.js @@ -16,6 +16,7 @@ const WEBP_QUALITY = parseInt(process.env["INPUT_WEBPQUALITY"]) || 80; const IGNORE_PATHS = process.env["INPUT_IGNOREPATHS"] ? process.env["INPUT_IGNOREPATHS"].split(",") : ["node_modules/**"]; +const COMPRESS_ONLY = process.env["INPUT_COMPRESSONLY"] || false; const COMMITTER = { name: "Calibre", @@ -53,5 +54,6 @@ module.exports = { JPEG_QUALITY, PNG_QUALITY, WEBP_QUALITY, - IGNORE_PATHS + IGNORE_PATHS, + COMPRESS_ONLY }; diff --git a/src/image-processing.js b/src/image-processing.js index 998522e2..67ba8ccf 100644 --- a/src/image-processing.js +++ b/src/image-processing.js @@ -4,15 +4,12 @@ const path = require("path"); const glob = util.promisify(require("glob")); const sharp = require("sharp"); -const getConfig = require("./config"); - const { REPO_DIRECTORY, EXTENSION_TO_SHARP_FORMAT_MAPPING } = require("./constants"); -const processImages = async () => { - const config = await getConfig(); +const processImages = async config => { const imagePaths = await glob(`${REPO_DIRECTORY}/**/*.{jpg,png,webp}`, { ignore: config.ignorePaths.map(p => path.resolve(REPO_DIRECTORY, p)), nodir: true diff --git a/src/index.js b/src/index.js index 2deffdac..2dc72d54 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,14 @@ const generateMarkdownReport = require("./github-markdown"); const processImages = require("./image-processing"); const createComment = require("./github-pr-comment"); const createCommit = require("./github-commit"); +const getConfig = require("./config"); const run = async () => { + const config = await getConfig(); + console.log("->> Locating images…"); - const results = await processImages(); + const results = await processImages(config); const optimisedImages = results.images.filter( img => img.compressionWasSignificant @@ -21,6 +24,16 @@ const run = async () => { console.log("->> Generating markdown…"); const markdown = await generateMarkdownReport(results); + // Expose the markdown to an Action output + const escaped_markdown = markdown.replace(/\%/g,'%25').replace(/\n/g,'%0A').replace(/\r/g,'%0D') + console.log("::set-output name=markdown::" + escaped_markdown) + + // If compress only mode, then we're done + if (config.compressOnly) { + console.log("->> compressOnly was set. Stopping."); + return results; + } + console.log("->> Committing files…"); await createCommit(optimisedImages); From 95e3ba3c1f381ac54e8ddfd08cbb1c07bbe2aac2 Mon Sep 17 00:00:00 2001 From: Barry Date: Sat, 9 May 2020 21:56:46 +0100 Subject: [PATCH 2/6] Update YML file --- action.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/action.yml b/action.yml index 0ce0ed25..81d285a3 100644 --- a/action.yml +++ b/action.yml @@ -27,6 +27,15 @@ inputs: required: false default: "node_modules/**" + compressOnly: + description: "Only runs the compression, without adding to Pull Request" + required: false + default: false + +outputs: + markdown: + description: "Output param used to store the Markdown summary for subsequent actions to use" + runs: using: "docker" image: "docker://calibreapp/github-image-actions" From 438de273b7467ff00cdff566b20cfae33aadf20b Mon Sep 17 00:00:00 2001 From: Barry Date: Sat, 9 May 2020 21:59:29 +0100 Subject: [PATCH 3/6] Fix nesting --- entrypoint.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/entrypoint.js b/entrypoint.js index e2b2b1ca..1b8988da 100755 --- a/entrypoint.js +++ b/entrypoint.js @@ -30,9 +30,9 @@ const main = async () => { ); process.exit(78); } + } - await run(); - }; + await run(); }; main(); From 49ebaacef308468e5c04a661a0952a30026a4a57 Mon Sep 17 00:00:00 2001 From: Barry Date: Fri, 22 May 2020 11:36:34 +0100 Subject: [PATCH 4/6] Better Bool handling --- README.md | 6 +++--- action.yml | 2 +- src/constants.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1bb3db9d..4ef72c41 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ _The `GITHUB_TOKEN` secret is [automatically generated by GitHub](https://help.g webpQuality: "80" ignorePaths: "node_modules/**,build" # No spaces allowed - compressOnly: false + compressOnly: "false" ``` If you would like to modify the defaults, update the `.github/workflows/calibreapp-image-actions.yml` file by adding arguments to the action: @@ -95,7 +95,7 @@ By default this Action will add the updated image to the current pull request. I uses: calibreapp/image-actions@master with: githubToken: ${{ secrets.GITHUB_TOKEN }} - compressOnly: true + compressOnly: "true" ``` ## Handling pull requests from forked repos @@ -132,7 +132,7 @@ jobs: uses: calibreapp/image-actions@master with: githubToken: ${{ secrets.GITHUB_TOKEN }} - compressOnly: true + compressOnly: "true" - name: Create New Pull Request uses: peter-evans/create-pull-request@master diff --git a/action.yml b/action.yml index 81d285a3..c24ea091 100644 --- a/action.yml +++ b/action.yml @@ -30,7 +30,7 @@ inputs: compressOnly: description: "Only runs the compression, without adding to Pull Request" required: false - default: false + default: "false" outputs: markdown: diff --git a/src/constants.js b/src/constants.js index f2bf90af..da2b550c 100644 --- a/src/constants.js +++ b/src/constants.js @@ -16,7 +16,7 @@ const WEBP_QUALITY = parseInt(process.env["INPUT_WEBPQUALITY"]) || 80; const IGNORE_PATHS = process.env["INPUT_IGNOREPATHS"] ? process.env["INPUT_IGNOREPATHS"].split(",") : ["node_modules/**"]; -const COMPRESS_ONLY = process.env["INPUT_COMPRESSONLY"] || false; +const COMPRESS_ONLY = process.env["INPUT_COMPRESSONLY"] === "true"; const COMMITTER = { name: "Calibre", From f5ec0126b6c5869eb98ebd0a4d876e3c76c89762 Mon Sep 17 00:00:00 2001 From: Barry Date: Fri, 21 Aug 2020 07:57:36 +0100 Subject: [PATCH 5/6] Add reference for escaping newlines --- src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.js b/src/index.js index 2dc72d54..f1515257 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,7 @@ const run = async () => { const markdown = await generateMarkdownReport(results); // Expose the markdown to an Action output + // https://github.community/t/set-output-truncates-multiline-strings/16852 const escaped_markdown = markdown.replace(/\%/g,'%25').replace(/\n/g,'%0A').replace(/\r/g,'%0D') console.log("::set-output name=markdown::" + escaped_markdown) From 0dc03d27b5290b80bea1401950418fa6872c5db4 Mon Sep 17 00:00:00 2001 From: Barry Date: Mon, 14 Sep 2020 07:27:41 +0100 Subject: [PATCH 6/6] Review feedback --- README.md | 6 ------ action.yml | 2 +- src/index.js | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index acbb1034..f7bf8589 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,6 @@ # Image Actions -<<<<<<< HEAD -Image Actions automatically compress JPEG, PNG and WebP images in GitHub Pull Requests within the same repository. - -It can also run in "Compress Only" mode to allow this to be used for non-Pull Requests, and also for Pull Requests from forks. -======= Image Actions automatically compresses JPEG, PNG and WebP images in GitHub Pull Requests. ->>>>>>> upstream/master - **Fast, efficient and near-lossless compression** - Uses the best image compression algorithms available: [mozjpeg](https://github.com/mozilla/mozjpeg) and [libvips](https://github.com/libvips/libvips) diff --git a/action.yml b/action.yml index ab97174c..89da30a4 100644 --- a/action.yml +++ b/action.yml @@ -33,7 +33,7 @@ inputs: default: "node_modules/**" compressOnly: - description: "Only runs the compression, without adding to Pull Request" + description: "Images will be compressed. No commit, or comments will be added to your Pull Request" required: false default: "false" diff --git a/src/index.js b/src/index.js index f1515257..d60d3840 100644 --- a/src/index.js +++ b/src/index.js @@ -26,8 +26,8 @@ const run = async () => { // Expose the markdown to an Action output // https://github.community/t/set-output-truncates-multiline-strings/16852 - const escaped_markdown = markdown.replace(/\%/g,'%25').replace(/\n/g,'%0A').replace(/\r/g,'%0D') - console.log("::set-output name=markdown::" + escaped_markdown) + const escapedMarkdown = markdown.replace(/\%/g,'%25').replace(/\n/g,'%0A').replace(/\r/g,'%0D') + console.log("::set-output name=markdown::" + escapedMarkdown) // If compress only mode, then we're done if (config.compressOnly) {