You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/01/27 00:51:13 UTC

[GitHub] [tvm] areusch commented on a change in pull request #10056: [ci] Add auto-updating `last-successful` tag

areusch commented on a change in pull request #10056:
URL: https://github.com/apache/tvm/pull/10056#discussion_r793168872



##########
File path: tests/scripts/update_tag.py
##########
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import os
+import json
+import argparse
+import tempfile
+from typing import Any, Dict
+
+from git_utils import git, GitHubRepo, parse_remote
+
+
+_commit_query_fields = """
+    messageHeadline
+    oid
+    statusCheckRollup {
+        contexts(last:100) {
+            nodes {
+                ... on CheckRun {
+                    conclusion
+                    status
+                    name
+                    checkSuite {
+                        workflowRun {
+                            workflow {
+                                name
+                            }
+                        }
+                    }
+                }
+                ... on StatusContext {
+                    context
+                    state
+                }
+            }
+        }
+    }
+"""
+
+
+def commits_query(user: str, repo: str, cursor: str = None):
+    """
+    Create a GraphQL query to find the last N commits along with their statuses
+    and some metadata (paginated after 'cursor')
+    """
+    after = ""
+    if cursor is not None:
+        after = f', after:"{cursor}"'
+
+    return f"""
+    {{
+    repository(name: "{repo}", owner: "{user}") {{
+        defaultBranchRef {{
+        target {{
+            ... on Commit {{
+            history(first: 15{after}) {{
+                edges {{ cursor }}
+                nodes {{
+                    {_commit_query_fields}
+                }}
+            }}
+            }}
+        }}
+        }}
+    }}
+    }}
+    """
+
+
+def commit_passed_ci(commit: Dict[str, Any]) -> bool:
+    """
+    Returns true if all of a commit's statuses are SUCCESS
+    """
+    statuses = commit["statusCheckRollup"]["contexts"]["nodes"]
+
+    # GitHub Actions statuses are different from external GitHub statuses, so
+    # unify them into 1 representation
+    unified_statuses = []
+    for status in statuses:
+        if "context" in status:
+            # Parse non-GHA status
+            unified_statuses.append((status["context"], status["state"] == "SUCCESS"))
+        else:
+            # Parse GitHub Actions item

Review comment:
       want to include a link to schema or docs?

##########
File path: .github/workflows/update_tag.yml
##########
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# GH actions.
+# We use it to cover windows and mac builds
+# Jenkins is still the primary CI
+
+name: Update last-successful tag
+
+on:
+  workflow_dispatch:
+  schedule:
+    cron: 15/* * * * *
+
+concurrency:
+  group: update-last-successful-tag
+  cancel-in-progress: true
+
+jobs:
+  update-last-successful-tag:
+    runs-on: ubuntu-latest

Review comment:
       just wondering if we should be pinning these to avoid python version being bumped unexpectedly?

##########
File path: tests/scripts/update_tag.py
##########
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import os
+import json
+import argparse
+import tempfile
+from typing import Any, Dict
+
+from git_utils import git, GitHubRepo, parse_remote
+
+
+_commit_query_fields = """
+    messageHeadline
+    oid
+    statusCheckRollup {
+        contexts(last:100) {
+            nodes {
+                ... on CheckRun {
+                    conclusion
+                    status
+                    name
+                    checkSuite {
+                        workflowRun {
+                            workflow {
+                                name
+                            }
+                        }
+                    }
+                }
+                ... on StatusContext {
+                    context
+                    state
+                }
+            }
+        }
+    }
+"""
+
+
+def commits_query(user: str, repo: str, cursor: str = None):
+    """
+    Create a GraphQL query to find the last N commits along with their statuses
+    and some metadata (paginated after 'cursor')
+    """
+    after = ""
+    if cursor is not None:
+        after = f', after:"{cursor}"'
+
+    return f"""
+    {{
+    repository(name: "{repo}", owner: "{user}") {{
+        defaultBranchRef {{
+        target {{
+            ... on Commit {{
+            history(first: 15{after}) {{
+                edges {{ cursor }}
+                nodes {{
+                    {_commit_query_fields}
+                }}
+            }}
+            }}
+        }}
+        }}
+    }}
+    }}
+    """
+
+
+def commit_passed_ci(commit: Dict[str, Any]) -> bool:
+    """
+    Returns true if all of a commit's statuses are SUCCESS
+    """
+    statuses = commit["statusCheckRollup"]["contexts"]["nodes"]
+
+    # GitHub Actions statuses are different from external GitHub statuses, so
+    # unify them into 1 representation
+    unified_statuses = []
+    for status in statuses:
+        if "context" in status:
+            # Parse non-GHA status
+            unified_statuses.append((status["context"], status["state"] == "SUCCESS"))
+        else:
+            # Parse GitHub Actions item
+            workflow = status["checkSuite"]["workflowRun"]["workflow"]["name"]
+            name = f"{workflow} / {status['name']}"
+            unified_statuses.append((name, status["conclusion"] == "SUCCESS"))
+
+    print(f"Statuses on {commit['oid']}:", json.dumps(unified_statuses, indent=2))
+
+    # Assert that specific jobs are present in the commit statuses (i.e. don't
+    # approve if CI was broken and didn't schedule a job)
+    expected_jobs = {"tvm-ci/branch"}
+    job_names = {name for name, status in unified_statuses}
+    for job in expected_jobs:
+        if job not in job_names:
+            # Did not find expected job name
+            return False
+
+    passed_ci = all(status for name, status in unified_statuses)
+    return passed_ci
+
+
+def update_tag(user: str, repo: str, sha: str, tag_name: str, message: str) -> None:
+    with tempfile.TemporaryDirectory() as f:
+        # Clone only a specific commit: https://stackoverflow.com/a/3489576
+        git(["init"], cwd=f)
+        git(["remote", "add", "origin", f"git@github.com:{user}/{repo}.git"], cwd=f)
+        git(["fetch", "origin", sha], cwd=f)
+        git(["reset", "--hard", "FETCH_HEAD"], cwd=f)
+
+        # Create a push the tag
+        git(["tag", "--annotate", tag_name, f"--message={message}"], cwd=f)
+        git(["push", "origin", "--force", tag_name], cwd=f)
+        print(f"Pushed tag {tag_name} with commit {sha}")
+
+
+if __name__ == "__main__":
+    help = "Push the a tag to the last commit that passed all CI runs"
+    parser = argparse.ArgumentParser(description=help)
+    parser.add_argument("--remote", default="origin", help="ssh remote to parse")
+    parser.add_argument("--dry-run", action="store_true", help="don't submit to GitHub")
+    parser.add_argument("--tag", default="last-successful", help="tag name")
+    parser.add_argument(
+        "--message", default="last 'main' commit that passed CI", help="label to add"
+    )
+    parser.add_argument("--json", help="(testing) data to use instead of fetching from GitHub")

Review comment:
       maybe prefer `--testonly-github-reply-json`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org