diff --git a/docs/install-forgejo-gitea.md b/docs/install-forgejo-gitea.md new file mode 100644 index 00000000000..ce478290441 --- /dev/null +++ b/docs/install-forgejo-gitea.md @@ -0,0 +1,159 @@ +--- +title: Install MegaLinter on Forgejo/Gitea Actions +description: Manual instructions to setup MegaLinter as an Forgejo/Gitea Workflow +--- + + + + +# Forgejo / Gitea + +Use the following Forgejo Actions [YAML template](https://forgejo.org/docs/latest/user/actions/reference) + +This CI is heavily based on Github Actions, and due to that will mostly use the same functionality. + +## Single Repository + +Add the following to an `azure-pipelines.yaml` file within your code repository: + +```yaml +# MegaLinter GitHub Action configuration file +# More info at https://megalinter.io +--- +name: MegaLinter + +on: + # Trigger mega-linter at every push. Action will also be visible from Pull Requests to main + push: # Comment this line to trigger action only on pull-requests (not recommended if you don't pay for GH Actions) + pull_request: + branches: [master, main] + +env: # Comment env block if you don't want to apply fixes + # Apply linter fixes configuration + APPLY_FIXES: all # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool) + APPLY_FIXES_EVENT: pull_request # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all) + APPLY_FIXES_MODE: commit # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request) + # NODE_EXTRA_CA_CERTS: /etc/ssl/certs/ca-certificates.crt # this line is only required for internal systems with a corporate CA certificate + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: {} + +jobs: + megalinter: + name: MegaLinter + runs-on: ubuntu-latest + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push, comment issues & post new PR + # Remove the ones you do not need + contents: write + issues: write + pull-requests: write + + steps: + # Git Checkout + - name: Checkout Code + uses: actions/checkout@v6 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances + + - name: MegaLinter + uses: https://github.com/oxsecurity/megalinter@v9 + id: ml + # You can override MegaLinter flavor used to have faster performances + # More info at https://megalinter.io/flavors/ + # MAJOR-RELEASE-IMPACTED + continue-on-error: true + env: + # All available variables are described in documentation + # https://megalinter.io/configuration/ + # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources + VALIDATE_ALL_CODEBASE: >- + ${{ + github.event_name == 'push' && + contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref) + }} + GIT_AUTHORIZATION_BEARER: ${{ secrets.GITHUB_TOKEN }} + # GITHUB_COMMENT_REPORTER: false # Gets automatically triggered as it's detected as GHES could theoretically work + # ADD YOUR CUSTOM ENV VARIABLES HERE OR DEFINE THEM IN A FILE .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY + # DISABLE: COPYPASTE,SPELL # Uncomment to disable copy-paste and spell checks + + # Upload MegaLinter artifacts + - name: Archive production artifacts + if: success() || failure() + uses: actions/upload-artifact@v3 + with: + name: MegaLinter reports + include-hidden-files: "true" + path: | + megalinter-reports + mega-linter.log + + - name: Set APPLY_FIXES_IF var + run: | + printf 'APPLY_FIXES_IF=%s\n' "${{ + steps.ml.outputs.has_updated_sources == 1 && + ( + env.APPLY_FIXES_EVENT == 'all' || + env.APPLY_FIXES_EVENT == github.event_name + ) && + ( + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository + ) + }}" >> "${GITHUB_ENV}" + + - name: Set APPLY_FIXES_IF_* vars + run: | + printf 'APPLY_FIXES_IF_PR=%s\n' "${{ + env.APPLY_FIXES_IF == 'true' && + env.APPLY_FIXES_MODE == 'pull_request' + }}" >> "${GITHUB_ENV}" + printf 'APPLY_FIXES_IF_COMMIT=%s\n' "${{ + env.APPLY_FIXES_IF == 'true' && + env.APPLY_FIXES_MODE == 'commit' && + (!contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref)) + }}" >> "${GITHUB_ENV}" + + # Create pull request if applicable (for now works only on PR from same repository, not from forks) + - name: Create Pull Request with applied fixes + uses: https://github.com/peter-evans/create-pull-request@v7 + id: cpr + if: env.APPLY_FIXES_IF_PR == 'true' + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + commit-message: "[MegaLinter] Apply linters automatic fixes" + title: "[MegaLinter] Apply linters automatic fixes" + labels: bot + + - name: Create PR output + if: env.APPLY_FIXES_IF_PR == 'true' + run: | + echo "PR Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "PR URL - ${{ steps.cpr.outputs.pull-request-url }}" + + # Push new commit if applicable (for now works only on PR from same repository, not from forks) + - name: Prepare commit + if: env.APPLY_FIXES_IF_COMMIT == 'true' + run: chown -Rc $UID .git/ + + - name: Commit and push applied linter fixes + uses: https://github.com/stefanzweifel/git-auto-commit-action@v7 + if: env.APPLY_FIXES_IF_COMMIT == 'true' + with: + branch: >- + ${{ + github.event.pull_request.head.ref || + github.head_ref || + github.ref + }} + commit_message: "[MegaLinter] Apply linters fixes" + commit_user_name: megalinter-bot + commit_user_email: 129584137+megalinter-bot@users.noreply.github.com + +``` + + diff --git a/megalinter/reporters/GithubCommentReporter.py b/megalinter/reporters/GithubCommentReporter.py index 1180f20eafe..71b65b9ceb8 100644 --- a/megalinter/reporters/GithubCommentReporter.py +++ b/megalinter/reporters/GithubCommentReporter.py @@ -72,10 +72,20 @@ def produce_report(self): run_id = config.get(self.master.request_id, "GITHUB_RUN_ID") sha = config.get(self.master.request_id, "GITHUB_SHA") + forgejo_actions = config.get(self.master.request_id, "FORGEJO_ACTIONS", "false") + gitea_actions = config.get(self.master.request_id, "GITEA_ACTIONS", "false") + if config.get(self.master.request_id, "CI_ACTION_RUN_URL", "") != "": action_run_url = config.get( self.master.request_id, "CI_ACTION_RUN_URL", "" ) + elif forgejo_actions == "true": + # Forgejo issue https://codeberg.org/forgejo/forgejo/issues/611 + forgejo_run_number = config.get(self.master.request_id, "FORGEJO_RUN_NUMBER", "") + forgejo_run_attempt = config.get(self.master.request_id, "FORGEJO_RUN_ATTEMPT", "") + action_run_url = ( + f"{github_server_url}/{github_repo}/actions/runs/{forgejo_run_number}/jobs/0/attempt/{forgejo_run_attempt}" + ) elif run_id is not None: action_run_url = ( f"{github_server_url}/{github_repo}/actions/runs/{run_id}" @@ -107,7 +117,11 @@ def produce_report(self): # Try to get PR from GITHUB_REF pr_list = [] ref = config.get(self.master.request_id, "GITHUB_REF", "") - m = re.compile("refs/pull/(\\d+)/merge").match(ref) + # Forgejo Gitea issue https://github.com/go-gitea/gitea/issues/27039 + if forgejo_actions == "true" or gitea_actions == "true": + m = re.compile("refs/pull/(\\d+)/head").match(ref) + else: + m = re.compile("refs/pull/(\\d+)/merge").match(ref) if m is not None: pr_id = m.group(1) logging.debug(f"Identified PR#{pr_id} from environment") @@ -115,7 +129,10 @@ def produce_report(self): pr_list = [repo.get_pull(int(pr_id))] except Exception as e: logging.warning(f"Could not fetch PR#{pr_id}: {e}") - if pr_list is None or len(pr_list) == 0: + # Forgejo Gitea issue: + # Is not /repos/{owner}/{repo}/commits/{ref} but /repos/{owner}/{repo}/git/commits/{sha} + # Will fail with a 404 + if (pr_list is None or len(pr_list) == 0) and forgejo_actions != "true" and gitea_actions != "true": # If not found with GITHUB_REF, try to find PR from commit try: commit = repo.get_commit(sha=sha) @@ -137,6 +154,8 @@ def produce_report(self): # Check if there is already a comment from MegaLinter # start searching from the most recent comment, backwards. existing_comment = None + # Forgejo Gitea issue: + # Wrong ref in PR object for comment in pr.get_issue_comments().reversed: if marker in comment.body: existing_comment = comment