diff --git a/.github/merge_rules.yaml b/.github/merge_rules.yaml new file mode 100644 index 0000000..0882cc8 --- /dev/null +++ b/.github/merge_rules.yaml @@ -0,0 +1,48 @@ +# Merge rules for ghstack land +# +# Rules are matched in order - first matching rule wins. +# Each rule specifies: +# - name: A descriptive name for the rule +# - patterns: File glob patterns to match (fnmatch syntax) +# - approved_by: Required approvers (usernames or org/team refs) +# Use "any" to accept any approved review +# - mandatory_checks_name: CI checks that must pass +# - ignore_flaky_failures: (optional) If true, ignore check failures + +- name: core-library + patterns: + - "src/ghstack/**" + approved_by: + - ezyang + - pytorch/ghstack-maintainers # Team reference example + mandatory_checks_name: + - "Test" + - "Lint" + +- name: documentation + patterns: + - "docs/**" + - "*.md" + approved_by: + - any # Any approved review is sufficient + mandatory_checks_name: + - "Lint" + +- name: ci-config + patterns: + - ".github/**" + approved_by: + - ezyang + mandatory_checks_name: + - "Test" + - "Lint" + +- name: default + patterns: + - "*" + - "**/*" + approved_by: + - ezyang + mandatory_checks_name: + - "Test" + - "Lint" diff --git a/.github/workflows/ghstack-merge-on-comment.yml b/.github/workflows/ghstack-merge-on-comment.yml new file mode 100644 index 0000000..d7f614f --- /dev/null +++ b/.github/workflows/ghstack-merge-on-comment.yml @@ -0,0 +1,38 @@ +# Example workflow that calls the reusable ghstack-merge workflow +# when someone comments "@ghstack merge" on a PR. +# +# To use in your repository: +# 1. Copy this file to .github/workflows/ +# 2. Optionally create .github/merge_rules.yaml for merge rules +# 3. Comment "@ghstack merge" on any ghstack PR to trigger landing + +name: ghstack merge on comment + +on: + issue_comment: + types: [created] + +jobs: + check-comment: + # Only run on PR comments containing '@ghstack merge' + if: | + github.event.issue.pull_request && + contains(github.event.comment.body, '@ghstack merge') + runs-on: ubuntu-latest + outputs: + should_merge: ${{ steps.check.outputs.should_merge }} + steps: + - name: Check if comment triggers merge + id: check + run: echo "should_merge=true" >> $GITHUB_OUTPUT + + merge: + needs: check-comment + if: needs.check-comment.outputs.should_merge == 'true' + uses: ezyang/ghstack/.github/workflows/ghstack-merge.yml@master + with: + pull_request_number: ${{ github.event.issue.number }} + validate_rules: true + comment_on_failure: true + secrets: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ghstack-merge.yml b/.github/workflows/ghstack-merge.yml new file mode 100644 index 0000000..6b1791c --- /dev/null +++ b/.github/workflows/ghstack-merge.yml @@ -0,0 +1,89 @@ +name: ghstack merge + +on: + workflow_call: + inputs: + pull_request_number: + description: 'The pull request number to land' + required: true + type: number + python_version: + description: 'Python version to use' + required: false + type: string + default: '3.11' + ghstack_version: + description: 'ghstack version to install (e.g., "ghstack", "ghstack==0.14.0", "git+https://github.com/ezyang/ghstack.git")' + required: false + type: string + default: 'ghstack' + validate_rules: + description: 'Whether to validate against merge rules' + required: false + type: boolean + default: true + dry_run: + description: 'Validate only, do not actually merge' + required: false + type: boolean + default: false + comment_on_failure: + description: 'Post validation errors as PR comment' + required: false + type: boolean + default: true + runs_on: + description: 'Runner to use' + required: false + type: string + default: 'ubuntu-latest' + secrets: + github_token: + description: 'GitHub token with contents:write and pull-requests:write permissions' + required: true + +jobs: + merge: + runs-on: ${{ inputs.runs_on }} + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.github_token }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python_version }} + + - name: Install ghstack + run: pip install '${{ inputs.ghstack_version }}' + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Build ghstack land command + id: build-command + run: | + CMD="ghstack land" + if [ "${{ inputs.validate_rules }}" = "true" ]; then + CMD="$CMD --validate-rules" + fi + if [ "${{ inputs.dry_run }}" = "true" ]; then + CMD="$CMD --dry-run" + fi + if [ "${{ inputs.comment_on_failure }}" = "true" ]; then + CMD="$CMD --comment-on-failure" + fi + CMD="$CMD ${{ inputs.pull_request_number }}" + echo "command=$CMD" >> $GITHUB_OUTPUT + + - name: Run ghstack land + env: + GITHUB_TOKEN: ${{ secrets.github_token }} + run: ${{ steps.build-command.outputs.command }}