Skip to content

Commit 878c98f

Browse files
committed
build: add slash command to autofix lint errors
1 parent 78142dd commit 878c98f

3 files changed

Lines changed: 247 additions & 0 deletions

File tree

.github/workflows/lint_autofix.yml

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#/
2+
# @license Apache-2.0
3+
#
4+
# Copyright (c) 2024 The Stdlib Authors.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
#/
18+
19+
# Workflow name:
20+
name: lint_autofix
21+
22+
# Workflow triggers:
23+
on:
24+
25+
# Allow the workflow to be triggered by other workflows
26+
workflow_call:
27+
# Define the input parameters for the workflow:
28+
inputs:
29+
pull_request_number:
30+
description: 'PR number'
31+
required: true
32+
type: number
33+
# Define the secrets accessible by the workflow:
34+
secrets:
35+
STDLIB_BOT_GITHUB_TOKEN:
36+
description: 'GitHub token for stdlb-bot'
37+
required: true
38+
REPO_GITHUB_TOKEN:
39+
description: 'GitHub token for accessing the repository'
40+
required: true
41+
STDLIB_BOT_GPG_PRIVATE_KEY:
42+
description: 'GPG private key for stdlb-bot'
43+
required: true
44+
STDLIB_BOT_GPG_PASSPHRASE:
45+
description: 'GPG passphrase for stdlb-bot'
46+
required: true
47+
48+
# Workflow jobs:
49+
jobs:
50+
51+
# Define a job for automatically fixing lint errors:
52+
autofix:
53+
54+
# Define a display name:
55+
name: 'Fix lint errors'
56+
57+
# Define the type of virtual host machine:
58+
runs-on: ubuntu-latest
59+
60+
# Define the sequence of job steps...
61+
steps:
62+
63+
# Get PR details:
64+
- name: 'Get PR details'
65+
id: pr-details
66+
run: |
67+
pr_response=$(curl -s \
68+
-H "Accept: application/vnd.github.v3+json" \
69+
-H "Authorization: Bearer ${{ secrets.STDLIB_BOT_GITHUB_TOKEN }}" \
70+
"https://api.github.com/repos/stdlib-js/stdlib/pulls/${{ inputs.pull_request_number }}")
71+
72+
# Escape control characters:
73+
pr_response=$(echo "$pr_response" | tr -d '\000-\031')
74+
75+
# Extract the needed details:
76+
pr_branch=$(echo "$pr_response" | jq -r '.head.ref') # PR's branch
77+
pr_repo_full_name=$(echo "$pr_response" | jq -r '.head.repo.full_name') # PR's repo full name
78+
79+
# Set outputs for the branch and repository:
80+
echo "branch=$pr_branch" >> $GITHUB_OUTPUT
81+
echo "repository=$pr_repo_full_name" >> $GITHUB_OUTPUT
82+
83+
# Checkout the repository:
84+
- name: 'Checkout repository'
85+
# Pin action to full length commit SHA
86+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
87+
with:
88+
# Refers to the branch name of the branch being pushed:
89+
ref: ${{ steps.pr-details.outputs.branch }}
90+
91+
# Refers to the repository name:
92+
repository: ${{ steps.pr-details.outputs.repository }}
93+
94+
# Token for accessing the repository:
95+
token: ${{ secrets.REPO_GITHUB_TOKEN }}
96+
97+
# File path to checkout to:
98+
path: './'
99+
100+
# Get list of changed files:
101+
- name: 'Get list of changed files'
102+
id: changed-files
103+
run: |
104+
page=1
105+
files=""
106+
while true; do
107+
changed_files=$(curl -s -H "Accept: application/vnd.github.v3+json" -H "Authorization: Bearer ${{ secrets.STDLIB_BOT_GITHUB_TOKEN
108+
}}" "https://api.github.com/repos/stdlib-js/stdlib/pulls/${{ inputs.pull_request_number }}/files?page=$page&per_page=100" | jq -r '.[] | .filename')
109+
if [ -z "$changed_files" ]; then
110+
break
111+
fi
112+
files="$files $changed_files"
113+
page=$((page+1))
114+
done
115+
files=$(echo "$files" | tr '\n' ' ' | sed 's/^ //;s/ $//')
116+
echo "files=${files}" >> $GITHUB_OUTPUT
117+
118+
# Fix JavaScript lint errors:
119+
- name: 'Fix JavaScript lint errors'
120+
id: fix-lint-errors
121+
run: |
122+
files="${{ steps.changed-files.outputs.files }}"
123+
FIX=1 . "$GITHUB_WORKSPACE/.github/workflows/scripts/lint_javascript_files" "$files"
124+
125+
# Disable Git hooks:
126+
- name: 'Disable Git hooks'
127+
run: |
128+
rm -rf .git/hooks
129+
130+
# Import GPG key to sign commits:
131+
- name: 'Import GPG key to sign commits'
132+
# Pin action to full length commit SHA
133+
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
134+
with:
135+
gpg_private_key: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }}
136+
passphrase: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }}
137+
git_user_signingkey: true
138+
git_commit_gpgsign: true
139+
140+
# Commit and push changes:
141+
- name: 'Commit and push changes'
142+
env:
143+
REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
144+
USER_NAME: stdlb-bot
145+
BRANCH_NAME: ${{ steps.pr-details.outputs.branch }}
146+
REPO_NAME: ${{ steps.pr-details.outputs.repository }}
147+
run: |
148+
git config --local user.email "82920195+stdlib-bot@users.noreply.github.com"
149+
git config --local user.name "stdlib-bot"
150+
git add .
151+
git commit -m "fix: resolve lint errors"
152+
git push "https://$USER_NAME:$REPO_GITHUB_TOKEN@github.com/$REPO_NAME.git" $BRANCH_NAME
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env bash
2+
#
3+
# @license Apache-2.0
4+
#
5+
# Copyright (c) 2024 The Stdlib Authors.
6+
#
7+
# Licensed under the Apache License, Version 2.0 (the "License");
8+
# you may not use this file except in compliance with the License.
9+
# You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
# Script to update years for stdlib copyright notices to the current year.
20+
#
21+
# Usage: update_copyright_years file1 [file2 file3 ...]
22+
#
23+
# Arguments:
24+
#
25+
# file1 File path.
26+
# file2 File path.
27+
# file3 File path.
28+
#
29+
# Environment variables:
30+
#
31+
# FIX 0 or 1 indicating whether to automatically fix errors.
32+
33+
# Determine root directory:
34+
root=$(git rev-parse --show-toplevel)
35+
36+
# Flag indicating whether to automatically fix errors:
37+
fix="${FIX:-0}"
38+
39+
# Files to lint:
40+
files_to_lint=${@}
41+
42+
# Define the path to ESLint configuration file for linting examples:
43+
eslint_examples_conf="${root}/etc/eslint/.eslintrc.examples.js"
44+
45+
# Define the path to ESLint configuration file for linting tests:
46+
eslint_tests_conf="${root}/etc/eslint/.eslintrc.tests.js"
47+
48+
# Define the path to ESLint configuration file for linting benchmarks:
49+
eslint_benchmarks_conf="${root}/etc/eslint/.eslintrc.benchmarks.js"
50+
51+
# Lint JavaScript source files:
52+
files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '\.js$' | grep -v -e '/examples' -e '/test' -e '/benchmark' -e '^dist/' | tr '\n' ' ' | sed 's/ $//')
53+
if [[ -n "${files}" ]]; then
54+
make lint-javascript-files FIX="${fix}" FILES="${files}"
55+
fi
56+
57+
# Lint JavaScript command-line interfaces...
58+
file=$(echo ${files_to_lint} | tr ' ' '\n' | grep '\.js$' | grep -E '/bin/cli$' | tr '\n' ' ' | sed 's/ $//')
59+
if [[ -n "${file}" ]]; then
60+
make lint-javascript-files FIX="${fix}" FILES="${file}"
61+
fi
62+
63+
# Lint JavaScript example files:
64+
files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/examples/.*\.js$' | tr '\n' ' ' | sed 's/ $//')
65+
if [[ -n "${files}" ]]; then
66+
make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_examples_conf}"
67+
fi
68+
69+
# Lint JavaScript test files:
70+
files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/test/.*\.js$' | tr '\n' ' ' | sed 's/ $//')
71+
if [[ -n "${files}" ]]; then
72+
make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_tests_conf}"
73+
fi
74+
75+
# Lint JavaScript benchmark files:
76+
files=$(echo "${files_to_lint}" | tr ' ' '\n' | grep '/benchmark/.*\.js$' | tr '\n' ' ' | sed 's/ $//')
77+
if [[ -n "${files}" ]]; then
78+
make lint-javascript-files FIX="${fix}" FILES="${files}" ESLINT_CONF="${eslint_benchmarks_conf}"
79+
fi

.github/workflows/slash_commands.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,19 @@ jobs:
5656
STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_GITHUB_TOKEN }}
5757
STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }}
5858
STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }}
59+
60+
# Define a job for auto-fixing lint errors:
61+
fix_lint_errors:
62+
63+
# Define the conditions under which the job should run:
64+
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib lint-autofix')
65+
66+
# Run reusable workflow:
67+
uses: ./.github/workflows/lint_autofix.yml
68+
with:
69+
pull_request_number: ${{ github.event.issue.number }}
70+
secrets:
71+
REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
72+
STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_GITHUB_TOKEN }}
73+
STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }}
74+
STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }}

0 commit comments

Comments
 (0)