1name: Formatting your code
2on:
3  # We are interested only in master and PRs, but GitHub explicitly forbids
4  # pushing to the fork when an event is triggered on the base repo.
5  # We therefore need to intercept all calls and filter out the ones we are
6  # interested in.
7  # For master, and branches with an open PR, we run utils/fix_formatting.py.
8  # We then commit and push the changes to the branch.
9  # If someone pushes to the branch while we're still formatting,
10  # we exit 1 instead of pushing.
11  # For other branches without an open PR, we also run fix_formatting.py, but
12  # we do not push anything, only signal the code quality by exiting 0 or 1.
13  push:
14jobs:
15  run_formatting:
16    name: Run fix_formatting.py
17    # clang-format has broken dependencies on ubuntu-latest
18    runs-on: ubuntu-16.04
19    steps:
20    - name: Checkout
21      uses: actions/checkout@v2
22    - name: Fetching branch info
23      run: |
24        echo "::set-env name=branch::${GITHUB_REF##*/}"
25        git config --global user.name "The Widelands Code Formatting Bot"
26        git config --global user.email "actions@github.com"
27        # copied from https://github.com/stefanzweifel/git-auto-commit-action/blob/master/entrypoint.sh
28        cat <<- EOF > $HOME/.netrc
29        machine github.com
30        login $GITHUB_ACTOR
31        password ${{ secrets.GITHUB_TOKEN }}
32        machine api.github.com
33        login $GITHUB_ACTOR
34        password ${{ secrets.GITHUB_TOKEN }}
35        EOF
36        chmod 600 $HOME/.netrc
37    - name: Installing python
38      uses: actions/setup-python@v1
39      with:
40        python-version: 3.x
41    - name: Installing formatting tools
42      run: |
43        sudo apt-get update
44        sudo apt-get install clang-format
45        pip install pyformat
46    - name: Invoking fix_formatting.py
47      run: python3 ./utils/fix_formatting.py
48    - name: Gathering changes
49      run: |
50        nrfiles=$(git status -s | wc -l)
51        if [ $nrfiles == 0 ]
52        then
53          echo "Nothing to do"
54          files=""
55        else
56          if [ $nrfiles == 1 ]
57          then
58            echo "1 file formatted"
59            files=$(git status -s)
60            files="'${files#???}' was automatically formatted."
61          else
62            echo "$nrfiles files formatted"
63            files="$nrfiles files were automatically formatted."
64          fi
65          if [ "$branch" == "master" ]
66          then
67            echo "Always push master branch ($GITHUB_REF)"
68          else
69            forkname=${{ github.repository }}
70            # grep returns 1 if the branch is not found
71            set +e
72            output=$(curl -i "https://api.github.com/repos/widelands/widelands/pulls?state=open&head=${forkname%%/*}:$branch" | grep "$branch")
73            set -e
74            if [ -z "$output" ]
75            then
76              echo "Branch $branch in repository $forkname does not have an open pull request, so no changes will be pushed. Please note however that your code is not properly formatted:"
77              git status -s
78              git --no-pager diff --cached
79              exit 1
80            else
81              echo "Branch $branch in repository $forkname has an open pull request. Changes will be pushed."
82            fi
83          fi
84        fi
85        echo "::set-env name=COMMIT_MESSAGE::$files"
86    - name: Pushing changes
87      run: |
88        if [ -z "$COMMIT_MESSAGE" ]
89        # skip if there's nothing to do
90        then
91          echo "Code was already correctly formatted"
92          exit 0
93        fi
94        # curl exits 23 because grep will kill it after the first match
95        set +e
96        latest=$(curl -i "https://api.github.com/repos/${{ github.repository }}/commits/$branch" | grep -m 1 "\"sha\": ")
97        set -e
98        latest=${latest#*: \"}
99        latest=${latest%\",}
100        if [ "$latest" == "${{ github.sha }}" ]
101        then
102          echo "No remote changes"
103          git commit -m "$COMMIT_MESSAGE"
104          git push origin "$branch"
105          echo "Changes were successfully pushed to $branch at ${{ github.repository }}. Don't forget to run 'git pull' before pushing to the branch again."
106        else
107          echo "The remote branch '$branch' ($GITHUB_REF) from '${{ github.repository }}' was updated from '${{ github.sha }}' to '$latest', cancel"
108          exit 1
109        fi
110