Home > OS >  Github Actions behave different comparing to a local environment
Github Actions behave different comparing to a local environment

Time:06-20

I have created a GitHub actions pipeline to do linting of the recent committed code. The test script works in my local environment, but not on the GitHub server. What peculiarity I don't notice?

Here is my code for linting:

    #!/usr/bin/env bash
    
    LATEST_COMMIT=$(git rev-parse HEAD);
    echo "Analyzing code changes under the commit hash: $LATEST_COMMIT";
    FILES_UNDER_THE_LATEST_COMMIT=$(git diff-tree --no-commit-id --name-only -r $LATEST_COMMIT);
    echo "Files under the commit:";
    echo $FILES_UNDER_THE_LATEST_COMMIT;
    MATCHES=$(echo $FILES_UNDER_THE_LATEST_COMMIT | grep '.py');
    echo "Files under the commit with Python extension: $MATCHES";
    echo "Starting linting...";
    if echo $MATCHES | grep -q '.py';
    then
      echo $MATCHES | xargs pylint --rcfile .pylintrc;
    else
      echo "Nothing to lint";
    fi

Here is my GitHub Actions config:

name: Pylint

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10"]
    steps:
    - uses: actions/checkout@v3
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v3
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install dependencies
      if: "!contains(github.event.head_commit.message, 'NO_LINT')"
      run: |
        python -m pip install --upgrade pip
        pip install pylint psycopg2 snowflake-connector-python pymssql
        chmod  x .github/workflows/run_linting.sh
    - name: Analysing all Python scripts in the project with Pylint
      if: "contains(github.event.head_commit.message, 'CHECK_ALL')"
      run: pylint --rcfile .pylintrc lib processes tests
    - name: Analysing the latest committed changes Pylint
      if: "!contains(github.event.head_commit.message, 'NO_LINT')"
      run: .github/workflows/run_linting.sh

What I get in GitHub: What I get in GitHub

And what on my computer: And what on my computer

CodePudding user response:

Here's your problem in a nutshell:

    steps:
    - uses: actions/checkout@v3

By default, checkout@v2 and checkout@v3 make a shallow (depth 1), single-branch clone. Such a clone has exactly one commit in it: the most recent one.

As a consequence, this:

git diff-tree --no-commit-id --name-only -r $LATEST_COMMIT

produces no output at all. There's no parent commit available to compare against. (I'd argue that this is a bit of a bug in Git: git diff-tree should notice that the parent is missing due to the .git/shallow grafts file. However, git diff-tree traditionally produces an empty diff for a root commit, and without special handling in git diff-tree, the shallow clone makes git diff-tree think this is a root commit. Oddly, the user-oriented git diff would treat every file as added—still not what you want, but it would have actually worked.)

To fix this, force the depth to be at least 2. Using depth: 0 will force a full (non-shallow) clone, but the reason for using a shallow, single-branch clone is to speed up the action by omitting unnecessary commits. As only the first two "layers" of commit are required here, depth: 2 provides the correct number.

Side note: your bash code has every command terminated with a semicolon. This works fine, but is unnecessary (it reminds me of doing too much C or C programming.1 Also, you can just run git diff-tree <options> HEAD: there's no need for a separate git rev-parse step here (though you might still want that in the echo).


1As I switch from C to C to Go to Python to shell etc., I either put in too many or too few parentheses and semicolons, leading to C compiler errors from:

if x == 0 {

because my brain is in Go mode.

  • Related