# yaml-language-server: $schema=https://json.schemastore.org/github-action.json # permissions: # - contents: write # Required for creating commits # - pull-requests: write # Required for creating pull requests --- # # Compress images on demand (workflow_dispatch), and at 11pm every Sunday (schedule). # Open a Pull Request if any images can be compressed. name: Compress Images description: Compress images on demand (workflow_dispatch), and at 11pm every Sunday (schedule). author: Ismo Vuorinen branding: icon: image color: blue inputs: token: description: 'GitHub token for authentication' required: false default: ${{ github.token }} username: description: 'GitHub username for commits' required: false default: 'github-actions' email: description: 'GitHub email for commits' required: false default: 'github-actions@github.com' working-directory: description: 'Directory containing images to compress' required: false default: '.' image-quality: description: 'JPEG compression quality (0-100)' required: false default: '85' png-quality: description: 'PNG compression quality (0-100)' required: false default: '95' ignore-paths: description: 'Paths to ignore during compression (glob patterns)' required: false default: 'node_modules/**,dist/**,build/**' outputs: images_compressed: description: 'Whether any images were compressed (boolean)' value: ${{ steps.calibre.outputs.markdown != '' && 'true' || 'false' }} compression_report: description: 'Markdown report of compression results' value: ${{ steps.calibre.outputs.markdown }} runs: using: composite steps: - name: Validate Inputs id: validate shell: sh env: WORKING_DIRECTORY: ${{ inputs.working-directory }} IMAGE_QUALITY: ${{ inputs.image-quality }} PNG_QUALITY: ${{ inputs.png-quality }} IGNORE_PATHS: ${{ inputs.ignore-paths }} EMAIL: ${{ inputs.email }} USERNAME: ${{ inputs.username }} GITHUB_TOKEN: ${{ inputs.token }} run: | set -eu # Validate working directory if [ ! -d "$WORKING_DIRECTORY" ]; then echo "::error::Invalid working-directory: '$WORKING_DIRECTORY'. Directory does not exist" exit 1 fi # Validate path security (prevent absolute paths and path traversal) case "$WORKING_DIRECTORY" in /*|~*|[A-Za-z]:*|*..*) echo "::error::Invalid working-directory: '$WORKING_DIRECTORY'. Absolute paths and path traversal not allowed" exit 1 ;; esac # Validate image quality (0-100) - must be numeric case "$IMAGE_QUALITY" in ''|*[!0-9]*) echo "::error::Invalid image-quality: '$IMAGE_QUALITY'. Must be a number between 0 and 100" exit 1 ;; esac if [ "$IMAGE_QUALITY" -lt 0 ] || [ "$IMAGE_QUALITY" -gt 100 ]; then echo "::error::Invalid image-quality: '$IMAGE_QUALITY'. Must be between 0 and 100" exit 1 fi # Validate PNG quality (0-100) - must be numeric case "$PNG_QUALITY" in ''|*[!0-9]*) echo "::error::Invalid png-quality: '$PNG_QUALITY'. Must be a number between 0 and 100" exit 1 ;; esac if [ "$PNG_QUALITY" -lt 0 ] || [ "$PNG_QUALITY" -gt 100 ]; then echo "::error::Invalid png-quality: '$PNG_QUALITY'. Must be between 0 and 100" exit 1 fi # Validate ignore paths format (prevent command injection and path traversal) case "$IGNORE_PATHS" in *\;*|*\&\&*|*\|*|*\`*|*\$\(*|*\$\{*|*\<*|*\>*|*..\*) echo "::error::Invalid ignore-paths: '$IGNORE_PATHS'. Command injection patterns and path traversal not allowed" exit 1 ;; esac # Validate email format (basic check) case "$EMAIL" in *@*.*) ;; *) echo "::error::Invalid email format: '$EMAIL'. Expected valid email address" exit 1 ;; esac # Validate username format (prevent command injection) case "$USERNAME" in *\;*|*\&\&*|*\|*) echo "::error::Invalid username: '$USERNAME'. Command injection patterns not allowed" exit 1 ;; esac # Validate token format if provided (basic GitHub token pattern) if [ -n "$GITHUB_TOKEN" ]; then case "$GITHUB_TOKEN" in gh[efpousr]_?????????????????????????????????????) ;; *) echo "::warning::GitHub token format may be invalid. Expected format: gh*_36characters" ;; esac fi - name: Checkout Repository uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta with: token: ${{ inputs.token }} - name: Compress Images id: calibre uses: calibreapp/image-actions@f32575787d333b0579f0b7d506ff03be63a669d1 # 1.4.1 with: compressOnly: true githubToken: ${{ inputs.token }} jpegQuality: ${{ inputs.image-quality }} pngQuality: ${{ inputs.png-quality }} ignorePaths: ${{ inputs.ignore-paths }} workingDirectory: ${{ inputs.working-directory }} - name: Create New Pull Request If Needed if: steps.calibre.outputs.markdown != '' uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 with: token: ${{ inputs.token }} title: 'chore: compress images' branch-suffix: timestamp commit-message: 'chore: compress images' body: ${{ steps.calibre.outputs.markdown }}