Skip to content

Commit

Permalink
Merge pull request #694 from conda-forge/linting
Browse files Browse the repository at this point in the history
feat: add linter plus tests
  • Loading branch information
beckermr authored Sep 30, 2024
2 parents 479d85e + a3eafa8 commit 589a098
Show file tree
Hide file tree
Showing 7 changed files with 621 additions and 12 deletions.
111 changes: 106 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ jobs:
git config --global pull.rebase false
mkdir -p ~/.conda-smithy/ && echo $GH_TOKEN > ~/.conda-smithy/github.token
pip install --no-deps -e .
version=$(python -c "import conda_forge_webservices; print(conda_forge_webservices.__version__.replace('+', '.'))")
echo "version=${version}" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}

Expand Down Expand Up @@ -83,6 +80,40 @@ jobs:
CF_WEBSERVICES_FEEDSTOCK_PRIVATE_KEY: ${{ secrets.CF_CURATOR_PRIVATE_KEY }}
ACTION_URL: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}"

docker-build:
name: docker-build
runs-on: "ubuntu-latest"
concurrency:
group: ${{ github.workflow }}-docker-build-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
with:
fetch-depth: 0

- name: setup conda
uses: mamba-org/setup-micromamba@f8b8a1e23a26f60a44c853292711bacfd3eac822 # v1
with:
environment-file: conda-lock.yml
environment-name: webservices
condarc: |
show_channel_urls: true
channel_priority: strict
channels:
- conda-forge
- name: install code
id: install-code
shell: bash -l {0}
run: |
git config --global user.email "79913779+conda-forge-curator[bot]@users.noreply.github.com"
git config --global user.name "conda-forge-curator[bot]"
git config --global pull.rebase false
pip install --no-deps --no-build-isolation -e .
version=$(python -c "import conda_forge_webservices; print(conda_forge_webservices.__version__.replace('+', '.'))")
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: set up docker buildx
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'conda-forge/conda-forge-webservices'
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3
Expand All @@ -106,7 +137,9 @@ jobs:
live-tests-upload:
name: live-tests-upload
runs-on: "ubuntu-latest"
needs: tests
needs:
- tests
- docker-build
concurrency:
group: ${{ github.event.pull_request.head.repo.fork != 'true' && 'live-tests-upload' || format('{0}-{1}', github.workflow, github.ref) }}
steps:
Expand Down Expand Up @@ -166,7 +199,9 @@ jobs:
live-tests-rerender:
name: live-tests-rerender
runs-on: "ubuntu-latest"
needs: tests
needs:
- tests
- docker-build
concurrency:
group: ${{ github.event.pull_request.head.repo.fork != 'true' && 'live-tests-rerender' || format('{0}-{1}', github.workflow, github.ref) }}
steps:
Expand Down Expand Up @@ -226,3 +261,69 @@ jobs:
pytest -vvs --branch=${branch} test_live_rerender.py
env:
GH_TOKEN: ${{ secrets.CF_ADMIN_GITHUB_TOKEN }}

live-tests-linter:
name: live-tests-linter
runs-on: "ubuntu-latest"
needs:
- tests
- docker-build
concurrency:
group: ${{ github.event.pull_request.head.repo.fork != 'true' && 'live-tests-linter' || format('{0}-{1}', github.workflow, github.ref) }}
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
if: ${{ !github.event.pull_request.head.repo.fork }}
with:
fetch-depth: 0

- name: setup conda
if: ${{ !github.event.pull_request.head.repo.fork }}
uses: mamba-org/setup-micromamba@f8b8a1e23a26f60a44c853292711bacfd3eac822 # v1
with:
environment-file: conda-lock.yml
environment-name: webservices
condarc: |
show_channel_urls: true
channel_priority: strict
channels:
- conda-forge
- name: generate token
if: ${{ !github.event.pull_request.head.repo.fork }}
id: generate_token
uses: actions/create-github-app-token@31c86eb3b33c9b601a1f60f98dcbfd1d70f379b4 # v1
with:
app-id: ${{ secrets.CF_CURATOR_APP_ID }}
private-key: ${{ secrets.CF_CURATOR_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}

- name: install code
shell: bash -l {0}
if: ${{ !github.event.pull_request.head.repo.fork }}
run: |
git config --global user.email "79913779+conda-forge-curator[bot]@users.noreply.github.com"
git config --global user.name "conda-forge-curator[bot]"
git config --global pull.rebase false
mkdir -p ~/.conda-smithy/ && echo $GH_TOKEN > ~/.conda-smithy/github.token
pip install --no-deps -e .
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}

- name: run linter tests
shell: bash -l {0}
if: ${{ !github.event.pull_request.head.repo.fork }}
run: |
if [[ "${GITHUB_HEAD_REF}" != "" ]]; then
branch="${GITHUB_HEAD_REF}"
else
branch="${GITHUB_REF_NAME}"
fi
version=$(python -c "import conda_forge_webservices; print(conda_forge_webservices.__version__.replace('+', '.'))")
export CF_FEEDSTOCK_OPS_CONTAINER_NAME=condaforge/webservices-dispatch-action
export CF_FEEDSTOCK_OPS_CONTAINER_TAG="${version}"
cd tests
pytest -vvs --branch=${branch} test_live_linter.py
env:
GH_TOKEN: ${{ secrets.CF_ADMIN_GITHUB_TOKEN }}
42 changes: 42 additions & 0 deletions .github/workflows/webservices-workflow-dispatch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,51 @@ defaults:
permissions: {}

jobs:
init-task:
name: init-task
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
with:
fetch-depth: 0
ref: ${{ github.ref }}

- name: setup conda
uses: mamba-org/setup-micromamba@f8b8a1e23a26f60a44c853292711bacfd3eac822
with:
environment-file: conda-lock.yml
environment-name: webservices
condarc: |
show_channel_urls: true
channel_priority: strict
channels:
- conda-forge
- name: install code
run: |
pip install --no-deps --no-build-isolation -e .
- name: init task
run: |
git config --global user.name "conda-forge-webservices[bot]"
git config --global user.email "91080706+conda-forge-webservices[bot]@users.noreply.github.com"
export CF_FEEDSTOCK_OPS_CONTAINER_NAME=condaforge/webservices-dispatch-action
export CF_FEEDSTOCK_OPS_CONTAINER_TAG="${{ inputs.container_tag }}"
conda-forge-webservices-init-task \
--task=${{ inputs.task }} \
--repo=${{ inputs.repo }} \
--pr-number=${{ inputs.pr_number }}
env:
GH_TOKEN: ${{ secrets.CF_ADMIN_GITHUB_TOKEN }}

run-task:
name: run-task
runs-on: ubuntu-latest
needs:
- init-task
steps:
- name: checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
Expand Down
87 changes: 83 additions & 4 deletions conda_forge_webservices/github_actions_integration/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
import subprocess
import sys
import tempfile
import traceback

import click
from conda_forge_feedstock_ops.lint import lint as lint_feedstock
from conda_forge_feedstock_ops.os_utils import sync_dirs
from git import Repo

from .utils import (
comment_and_push_if_changed,
dedent_with_escaped_continue,
flush_logger,
get_gha_run_link,
mark_pr_as_ready_for_review,
)
from .api_sessions import create_api_sessions
from .rerendering import rerender
from .linting import make_lint_comment, build_and_make_lint_comment, set_pr_status


LOGGER = logging.getLogger(__name__)
Expand All @@ -39,6 +43,26 @@ def _pull_docker_image():
print("::endgroup::", flush=True)


@click.command(name="conda-forge-webservices-init-task")
@click.option("--task", required=True, type=str)
@click.option("--repo", required=True, type=str)
@click.option("--pr-number", required=True, type=str)
def main_init_task(task, repo, pr_number):
logging.basicConfig(level=logging.INFO)

LOGGER.info("initializing task %s for conda-forge/%s#%s", task, repo, pr_number)

if task == "rerender":
pass
elif task == "lint":
_, gh = create_api_sessions()
gh_repo = gh.get_repo(f"conda-forge/{repo}")
pr = gh_repo.get_pull(int(pr_number))
set_pr_status(pr.base.repo, pr.head.sha, "pending", target_url=None)
else:
raise ValueError(f"Task `{task}` is not valid!")


@click.command(name="conda-forge-webservices-run-task")
@click.option("--task", required=True, type=str)
@click.option("--repo", required=True, type=str)
Expand Down Expand Up @@ -71,6 +95,21 @@ def main_run_task(task, repo, pr_number, task_data_dir):
task_data["task_results"]["rerender_error"] = rerender_error
task_data["task_results"]["info_message"] = info_message
task_data["task_results"]["commit_message"] = commit_message
elif task == "lint":
_pull_docker_image()
try:
lints, hints = lint_feedstock(feedstock_dir, use_container=True)
lint_error = False
except Exception as err:
LOGGER.warning("LINTING ERROR: %s", repr(err))
LOGGER.warning("LINTING ERROR TRACEBACK: %s", traceback.format_exc())
lint_error = True
lints = None
hints = None

task_data["task_results"]["lint_error"] = lint_error
task_data["task_results"]["lints"] = lints
task_data["task_results"]["hints"] = hints
else:
raise ValueError(f"Task `{task}` is not valid!")

Expand All @@ -82,6 +121,12 @@ def main_run_task(task, repo, pr_number, task_data_dir):
check=True,
capture_output=True,
)
if task == "lint":
subprocess.run(
["rm", "-rf", feedstock_dir],
check=True,
capture_output=True,
)


def _push_rerender_changes(
Expand Down Expand Up @@ -160,11 +205,12 @@ def main_finalize_task(task_data_dir):
flush_logger(LOGGER)

with tempfile.TemporaryDirectory() as tmpdir:
# commit the changes
_, gh = create_api_sessions()
gh_repo = gh.get_repo(f"conda-forge/{repo}")
pr = gh_repo.get_pull(int(pr_number))

# commit the changes if needed
if task in ["rerender"]:
_, gh = create_api_sessions()
gh_repo = gh.get_repo(f"conda-forge/{repo}")
pr = gh_repo.get_pull(int(pr_number))
pr_branch = pr.head.ref
pr_owner = pr.head.repo.owner.login
pr_repo = pr.head.repo.name
Expand Down Expand Up @@ -227,5 +273,38 @@ def main_finalize_task(task_data_dir):
# if the pr was made by the bot, mark it as ready for review
if pr.title == "MNT: rerender" and pr.user.login == "conda-forge-admin":
mark_pr_as_ready_for_review(pr)

elif task == "lint":
if pr.state == "closed":
raise RuntimeError("Closed PRs are not linted!")

if task_results["lint_error"]:
_message = dedent_with_escaped_continue(
"""
Hi! This is the friendly automated conda-forge-linting service.
I Failed to even lint the recipe, probably because of a conda-smithy
bug :cry:. This likely indicates a problem in your `meta.yaml`, \\
though. To get a traceback to help figure out what's going on, \\
install conda-smithy and run \\
`conda smithy recipe-lint --conda-forge .` from the recipe \\
directory.
"""
)
run_link = get_gha_run_link()
_message += (
"\n\n<sub>This message was generated by "
f"GitHub actions workflow run [{run_link}]({run_link}).</sub>\n"
)
msg = make_lint_comment(gh_repo, pr.number, _message)
status = "bad"
else:
msg, status = build_and_make_lint_comment(
gh, gh_repo, pr.number, task_results["lints"], task_results["hints"]
)

set_pr_status(pr.base.repo, pr.head.sha, status, target_url=msg.html_url)
print(f"Linter status: {status}")
print(f"Linter message:\n{msg.body}")
else:
raise ValueError(f"Task `{task}` is not valid!")
Loading

0 comments on commit 589a098

Please sign in to comment.