Screenshot Web Elements Across Browsers in Issue Comments.
Tags: actionshackathon21, opensource, github
Published: 2021-12-01 04:54:18

### My Workflow
[Note]: # (Please make sure the project links to the appropriate GitHub Actions repository, and includes [an open source license](https://choosealicense.com/) and README.)

{% github https://github.com/DryCreations/screenshot-workflow %}

This workflow will run a local server in a Github action, take screenshots using Playwright, upload those screenshots to Imgur, and post them as a comment on an issue or pull request.

### Submission Category:

Maintainer Must-Haves

### Yaml File or Link to Code

Demo Repository: [https://github.com/DryCreations/screenshot-workflow](https://github.com/DryCreations/screenshot-workflow)

Workflow:

```yaml
name: Screenshot
on: 
  issue_comment:
    types: 
      - created

jobs:
  screenshot:
    runs-on: ubuntu-latest
    container: mcr.microsoft.com/playwright:focal
    if: contains(github.event.comment.body, '/screenshot')
    steps:
    - name: Checkout Main
      if: ${{ !github.event.issue.pull_request }}
      uses: actions/checkout@v2
    - name: Get Branch for Pull Request
      if: ${{ github.event.issue.pull_request }}
      uses: xt0rted/pull-request-comment-branch@v1
      id: comment-branch
    - name: Checkout Branch
      if: ${{ github.event.issue.pull_request }}
      uses: actions/checkout@v2
      with:
        ref: ${{ steps.comment-branch.outputs.head_ref }}
    - name: Cache NPM Dependencies
      uses: actions/cache@v2
      with:
        path: ~/.npm
        key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.OS }}-npm-cache-
    - name: Install Playwright
      run: |
        npm install playwright
    - name: Run Server
      run: |
        npm run start & 
        npx wait-on http://127.0.0.1:3000/
    - name: Screenshot Images
      id: sc_step
      uses: actions/github-script@v5
      with:
        github-token: ${{secrets.GITHUB_TOKEN}}
        script: |
          const { webkit, firefox, chromium } = require('playwright');

          let browsers = {
            "webkit": webkit,
            "firefox": firefox,
            "chromium": chromium
          }
          let comment_body = context.payload.comment.body;

          let matches = comment_body.matchAll(/\/screenshot (?<browser>.+?) (?<path>.+?)(\s{(?<selector>.+)})?/gm);
          let img_ctr = 0;

          for (const { groups: { browser, path, selector } } of matches) {
            console.log(browser, path, selector);
            let img_id = img_ctr++;
            (async () => {
              const b = await browsers[browser].launch();
              const page = await b.newPage();
              await page.goto(`http://127.0.0.1:3000${path}`, { waitUntil: 'domcontentloaded' });
              const element = selector ? await page.$(selector) : page;
              await element.screenshot({ path: `image-uploads/${img_id}.png` });
              await b.close();
            })()
          }
    - name: Upload to Imgur
      id: imgur_step
      uses: devicons/public-upload-to-imgur@v2.2.1
      with:
        path: image-uploads/ # or path/to/images
        client_id: ${{secrets.IMGUR_CLIENT_ID}}
    - name: Comment Images
      uses: actions/github-script@v5
      env:
        IMG_URLS: ${{ steps.imgur_step.outputs.imgur_urls }}
      with:
        github-token: ${{secrets.GITHUB_TOKEN}}
        script: |
          const { IMG_URLS } = process.env
          let img_urls = JSON.parse(IMG_URLS)
          console.log(img_urls)
          console.log(img_urls[0])

          let comment_body = context.payload.comment.body;
          let matches = comment_body.matchAll(/\/screenshot (?<params>.+? .+?(\s{.+})?)/gm);
          let params = Array.from(matches, m => m.groups.params);

          let body = img_urls.map((url, idx) => `# ${params[idx]}\n![Image](${url})`).join('\n\n')

          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: body
          })
```

### Additional Resources / Info

Relies on the following actions:

[https://github.com/marketplace/actions/checkout](https://github.com/marketplace/actions/checkout)

[https://github.com/marketplace/actions/cache](https://github.com/marketplace/actions/cache)

[https://github.com/marketplace/actions/github-script](https://github.com/marketplace/actions/github-script)

[https://github.com/marketplace/actions/publish-on-imgur](https://github.com/marketplace/actions/publish-on-imgur)

Important Notes:

If you plan on using this in your own project, you may want to play attention to line 37. Currently the project runs the following command:

```sh
npm run start
```

And expects a server to start at `http://127.0.0.1:3000/`

If your project acts differently, or has another run command, update the command on line 37 as needed.