diff --git a/.github/PULL_REQUEST_TEMPLATE/new_icon.md b/.github/PULL_REQUEST_TEMPLATE/new_icon.md
index bcc4f6a72..9e35dc41e 100644
--- a/.github/PULL_REQUEST_TEMPLATE/new_icon.md
+++ b/.github/PULL_REQUEST_TEMPLATE/new_icon.md
@@ -3,7 +3,7 @@
- [ ] PR does not match another non-stale PR currently opened
- [ ] PR name matches the format *new icon: Icon name (versions separated by comma)*. More details [here](https://github.com/devicons/devicon/wiki/Overview-on-Submitting-Icons)
-- [ ] PR's base is the `develop` branch.
+- [ ] PR's base is the `master` branch.
- [ ] Your icons are inside a folder as seen [here](https://github.com/devicons/devicon/wiki/Organizing-SVGs)
- [ ] SVG matches the standards laid out [here](https://github.com/devicons/devicon/wiki/SVG-Standards)
- [ ] A new object is added in the `devicon.json` file at the correct alphabetic position as seen [here](https://github.com/devicons/devicon/wiki/Updating-%60devicon.json%60)
diff --git a/.github/scripts/in_develop_labeler.py b/.github/scripts/in_develop_labeler.py
deleted file mode 100644
index 3d329c994..000000000
--- a/.github/scripts/in_develop_labeler.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import re
-from build_assets import arg_getters, api_handler
-
-def main():
- args = arg_getters.get_in_develop_labeler_args()
- try:
- #get pr body
- pr_body = api_handler.get_pr_by_number(args.token, args.pr_num)["body"]
-
- # find the issue closing line
- print(pr_body.split("\n"))
- issue_line = [line for line in pr_body.split("\n") if line.startswith("**This PR closes")][0]
-
- print("Issue Line is " + issue_line)
- issue_pattern = re.compile(r"\d+")
- issues_numbers = issue_pattern.findall(issue_line)
- print("Labelling issues: " + str(issues_numbers))
- api_handler.label_issues(args.token, issues_numbers, ["in-develop"])
- except IndexError: # if can't find the issue line
- print("The PR body doesn't contain `**This PR closes` keywords. Ending workflow.")
- return
-
-if __name__ == "__main__":
- main()
diff --git a/.github/workflows/auto_build_merge.yml b/.github/workflows/auto_build_merge.yml
new file mode 100644
index 000000000..3788d5821
--- /dev/null
+++ b/.github/workflows/auto_build_merge.yml
@@ -0,0 +1,188 @@
+name: Auto Build and Merge
+on:
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ auto-build-merge:
+ name: Auto Build and Merge
+ runs-on: ubuntu-latest
+ if: github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master'
+
+ steps:
+ - name: Check if PR modifies icon files
+ id: check-files
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { data: files } = await github.rest.pulls.listFiles({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.payload.pull_request.number
+ });
+
+ const hasIconChanges = files.some(file =>
+ file.filename.startsWith('icons/') || file.filename === 'devicon.json'
+ );
+
+ console.log('Has icon changes:', hasIconChanges);
+ core.setOutput('has_icon_changes', hasIconChanges);
+
+ if (!hasIconChanges) {
+ console.log('PR does not modify icon files, skipping build');
+ }
+
+ return hasIconChanges;
+
+ - name: Check approval count
+ if: steps.check-files.outputs.has_icon_changes == 'true'
+ id: check-approvals
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const { data: reviews } = await github.rest.pulls.listReviews({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.payload.pull_request.number
+ });
+
+ // Get unique approvers (latest review per user)
+ const reviewsByUser = {};
+ for (const review of reviews) {
+ if (!reviewsByUser[review.user.login] ||
+ new Date(review.submitted_at) > new Date(reviewsByUser[review.user.login].submitted_at)) {
+ reviewsByUser[review.user.login] = review;
+ }
+ }
+
+ const approvals = Object.values(reviewsByUser).filter(r => r.state === 'APPROVED');
+ const approvalCount = approvals.length;
+
+ console.log('Approval count:', approvalCount);
+ core.setOutput('approval_count', approvalCount);
+ core.setOutput('approvers', JSON.stringify(approvals.map(r => r.user.login)));
+
+ if (approvalCount < 1) {
+ console.log('Less than 1 approval, skipping build');
+ return false;
+ }
+
+ return true;
+
+ - name: Checkout PR branch
+ if: steps.check-approvals.outputs.approval_count >= 1
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.pull_request.head.ref }}
+ repository: ${{ github.event.pull_request.head.repo.full_name }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup Python 3.10
+ if: steps.check-approvals.outputs.approval_count >= 1
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.10'
+
+ - name: Setup Node.js
+ if: steps.check-approvals.outputs.approval_count >= 1
+ uses: actions/setup-node@v4
+ with:
+ node-version: '16'
+
+ - name: Install Python dependencies
+ if: steps.check-approvals.outputs.approval_count >= 1
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r ./.github/scripts/requirements.txt
+
+ - name: Install Node dependencies
+ if: steps.check-approvals.outputs.approval_count >= 1
+ run: npm install
+
+ - name: Run Icomoon build
+ if: steps.check-approvals.outputs.approval_count >= 1
+ id: build
+ continue-on-error: true
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ python ./.github/scripts/icomoon_build.py \
+ ./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver \
+ ./icomoon.json \
+ ./devicon.json \
+ ./icons \
+ ./ \
+ $GITHUB_TOKEN \
+ --headless
+
+ - name: Build CSS
+ if: steps.build.outcome == 'success'
+ id: build-css
+ continue-on-error: true
+ run: npm run build-css
+
+ - name: Handle build failure
+ if: steps.build.outcome == 'failure' || steps.build-css.outcome == 'failure'
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const approvers = JSON.parse('${{ steps.check-approvals.outputs.approvers }}');
+ const prAuthor = context.payload.pull_request.user.login;
+ const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
+
+ const mentions = ['@' + prAuthor, ...approvers.map(a => '@' + a)].join(' ');
+
+ const commentBody = `${mentions}
+
+The Icomoon build has failed for this PR. Please review the errors and fix them.
+
+**Workflow run:** ${runUrl}
+
+The build must pass before this PR can be merged.`;
+
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.payload.pull_request.number,
+ body: commentBody
+ });
+
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.payload.pull_request.number,
+ labels: ['build-failed']
+ });
+
+ core.setFailed('Build failed');
+
+ - name: Commit build artifacts
+ if: steps.build.outcome == 'success' && steps.build-css.outcome == 'success'
+ run: |
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
+ git config --local user.name "github-actions[bot]"
+ git add -A
+ if ! git diff --staged --quiet; then
+ git commit -m "build: generate font files and CSS
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)
+
+Co-Authored-By: Claude /iconsdevicon.json to include the new Icon develop branch for each Icon.master branch for each Icon.new icon: Icon name (versions) update icon: icon-name (versions). Basically, follow the Overview on Submitting Icon but replace the new with update in name of request with the above.
@@ -361,19 +361,19 @@ As an example, let's assume you have created the SVGs for Redhat and Amazon Web
You don't have to be in a team to contribute!
- The branches master and develop are protected branches and only members
- with corresponding permissions (see teams below) are able to push changes to them.
+ The master branch is the protected branch and only members
+ with corresponding permissions (see teams below) are able to push changes to it.
Additional branches must follow the pattern username/feature/description.
The /feature/ indicates that a change is made to existing code (regardless
- if it's a fix, refactor or actual feature). The naming convention is based on the gitflow-workflow.
+ if it's a fix, refactor or actual feature).
For organisational purposes we introduced teams with permissions and responsibilities:
Write access to the repository (allowing them to create own branches)
- and are allowed to push changes to the develop branch (pull request and status checks required).
+ Supporters have Write access to the repository (allowing them to create own branches)
+ and are allowed to push changes to the master branch (pull request and status checks required).
development as draft-release branchnpm version vMAJOR.MINOR.PATCH -m "bump npm version to vMAJOR.MINOR.PATCH" (see #487)master as draft-release branch: git checkout master && git checkout -b draft-releasenpm version vMAJOR.MINOR.PATCH -m "bump npm version to vMAJOR.MINOR.PATCH"draft-releasebuild_icons.yml (which has a workflow_dispatch event trigger) and select the branch draft-release as target branch. This will build a font version of all icons using icomoon and automatically creates a pull request to merge the build result back into draft-releasedevelopment. Mention the release number in the pull request title (like "Build preparation for release vMAJOR.MINOR.PATCH).
- draft-release towards master. Mention the release number in the pull request title (like "Release vMAJOR.MINOR.PATCH").
+ #504 as an example).
+ Add information about all new icons, fixes, features and enhancements in the description of the pull request.
master and HEAD development. Copy the description of the earlier pull request.npm publish leading to a updated npm package (vMAJOR.MINOR.PATCH).npm publish leading to an updated npm package (vMAJOR.MINOR.PATCH).