diff --git a/.github/workflows/cleanup.yaml b/.github/workflows/cleanup.yaml new file mode 100644 index 0000000..14a5d49 --- /dev/null +++ b/.github/workflows/cleanup.yaml @@ -0,0 +1,37 @@ +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - id: createGithubAppToken + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.OPERATOR_APP_ID }} + private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ steps.createGithubAppToken.outputs.token }} + - env: + BASE_REF: ${{ github.base_ref }} + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + HEAD_REF: ${{ github.head_ref }} + REPO: ${{ github.repository }} + if: "!contains(github.event.pull_request.labels.*.name, 'ghstack')" + run: git push origin --delete "$HEAD_REF" + - env: + BASE_REF: ${{ github.base_ref }} + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + HEAD_REF: ${{ github.head_ref }} + REPO: ${{ github.repository }} + if: contains(github.event.pull_request.labels.*.name, 'ghstack') + run: + "for role in base head orig; do\n git push origin --delete \"${HEAD_REF%/head}/$role\"\ + \ || true\ndone\n" +name: Cleanup +"on": + check_suite: + types: + - completed + pull_request: + types: + - closed diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml new file mode 100644 index 0000000..5fc47a0 --- /dev/null +++ b/.github/workflows/integration.yaml @@ -0,0 +1,88 @@ +jobs: + check: + needs: + - triage + runs-on: ubuntu-latest + steps: + - id: createGithubAppToken + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.OPERATOR_APP_ID }} + private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ steps.createGithubAppToken.outputs.token }} + - uses: shikanime-studio/setup-nix-action@v1 + with: + github-token: ${{ steps.createGithubAppToken.outputs.token }} + - uses: shikanime-studio/direnv-action@v2 + - run: nix flake check --accept-flake-config --all-systems --no-pure-eval + merge: + needs: + - check + runs-on: ubuntu-latest + steps: + - id: createGithubAppToken + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.OPERATOR_APP_ID }} + private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ steps.createGithubAppToken.outputs.token }} + - uses: shikanime-studio/setup-nix-action@v1 + with: + github-token: ${{ steps.createGithubAppToken.outputs.token }} + - env: + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + PR_HTML_URL: ${{ github.event.issue.pull_request.html_url }} + if: + contains(github.event.pull_request.labels.*.name, 'dependencies') && contains(github.event.issue.labels.*.name, + 'ghstack') + run: nix run nixpkgs#sapling -- ghstack land "$PR_HTML_URL" + - env: + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + PR_HTML_URL: ${{ github.event.issue.pull_request.html_url }} + if: + contains(github.event.pull_request.labels.*.name, 'dependencies') && !contains(github.event.issue.labels.*.name, + 'ghstack') + run: gh pr merge --auto "$PR_HTML_URL" + triage: + runs-on: ubuntu-latest + steps: + - id: createGithubAppToken + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ vars.OPERATOR_APP_ID }} + private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + token: ${{ steps.createGithubAppToken.outputs.token }} + - env: + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + if: + github.event.pull_request.user.login == 'yorha-operator-6o[bot]' || github.event.pull_request.user.login + == 'dependabot[bot]' + run: gh pr edit "$PR_NUMBER" --assignee @yorha-operator-6o + - env: + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + if: + github.event.pull_request.user.login == 'yorha-operator-6o[bot]' || github.event.pull_request.user.login + == 'dependabot[bot]' + run: gh pr edit "$PR_NUMBER" --add-label dependencies + - env: + GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + if: startsWith(github.head_ref, 'gh/') && endsWith(github.head_ref, '/head') + run: gh pr edit "$PR_NUMBER" --add-label ghstack +name: Integration +"on": + pull_request: + branches: + - main + - gh/*/*/base diff --git a/.github/workflows/main.yaml b/.github/workflows/push.yaml similarity index 90% rename from .github/workflows/main.yaml rename to .github/workflows/push.yaml index d2b557b..b883f73 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/push.yaml @@ -16,12 +16,8 @@ jobs: github-token: ${{ steps.createGithubAppToken.outputs.token }} - uses: shikanime-studio/direnv-action@v2 - run: nix flake check --accept-flake-config --all-systems --no-pure-eval -name: Main +name: Push "on": - pull_request: - branches: - - main - - gh/*/*/base push: branches: - main diff --git a/.github/workflows/triage.yaml b/.github/workflows/triage.yaml deleted file mode 100644 index d60a7b9..0000000 --- a/.github/workflows/triage.yaml +++ /dev/null @@ -1,54 +0,0 @@ -jobs: - cleanup: - if: github.event.action == 'closed' - runs-on: ubuntu-latest - steps: - - id: createGithubAppToken - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.OPERATOR_APP_ID }} - private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ steps.createGithubAppToken.outputs.token }} - - env: - GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} - PR_BASE_REF: ${{ github.event.pull_request.base.ref }} - PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} - REPO: ${{ github.repository }} - run: - "if [[ \"$PR_HEAD_REF\" =~ ^gh/[^/]+/[^/]+/head$ && \"$PR_BASE_REF\" =~\ - \ ^gh/[^/]+/[^/]+/base$ && \"${PR_HEAD_REF%/head}\" == \"${PR_BASE_REF%/base}\"\ - \ ]]; then\n for role in base head orig; do\n git push origin --delete\ - \ \"${PR_HEAD_REF%/head}/$role\" || true\n done\nelse\n git push origin\ - \ --delete \"$PR_HEAD_REF\" || true\nfi\n" - labels: - if: github.event.action == 'opened' - runs-on: ubuntu-latest - steps: - - id: createGithubAppToken - uses: actions/create-github-app-token@v2 - with: - app-id: ${{ vars.OPERATOR_APP_ID }} - private-key: ${{ secrets.OPERATOR_PRIVATE_KEY }} - - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ steps.createGithubAppToken.outputs.token }} - - env: - GITHUB_TOKEN: ${{ steps.createGithubAppToken.outputs.token }} - PR_NUMBER: ${{ github.event.pull_request.number }} - if: - github.event.pull_request.user.login == 'yorha-operator-6o[bot]' || github.event.pull_request.user.login - == 'dependabot[bot]' - run: gh pr edit "$PR_NUMBER" --add-label dependencies -name: Triage -"on": - check_suite: - types: - - completed - pull_request: - types: - - closed - - opened diff --git a/modules/devenv/shikanime-studio.nix b/modules/devenv/shikanime-studio.nix index 46e75f6..26eac26 100644 --- a/modules/devenv/shikanime-studio.nix +++ b/modules/devenv/shikanime-studio.nix @@ -89,7 +89,26 @@ with lib; enable = mkDefault true; actions = with config.github.lib; { - add-labels = { + assign-pr = { + env = { + GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; + PR_NUMBER = mkWorkflowRef "github.event.pull_request.number"; + }; + "if" = concatStringsSep " || " [ + "github.event.pull_request.user.login == 'yorha-operator-6o[bot]'" + "github.event.pull_request.user.login == 'dependabot[bot]'" + ]; + run = mkWorkflowRun [ + "gh" + "pr" + "edit" + ''"$PR_NUMBER"'' + "--assignee" + "@yorha-operator-6o" + ]; + }; + + add-dependencies-labels = { env = { GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; PR_NUMBER = mkWorkflowRef "github.event.pull_request.number"; @@ -108,21 +127,54 @@ with lib; ]; }; - cleanup = { + add-ghstack-labels = { + env = { + GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; + PR_NUMBER = mkWorkflowRef "github.event.pull_request.number"; + }; + "if" = concatStringsSep " && " [ + "startsWith(github.head_ref, 'gh/')" + "endsWith(github.head_ref, '/head')" + ]; + run = mkWorkflowRun [ + "gh" + "pr" + "edit" + ''"$PR_NUMBER"'' + "--add-label" + "ghstack" + ]; + }; + + cleanup-pr = { + env = { + GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; + BASE_REF = mkWorkflowRef "github.base_ref"; + HEAD_REF = mkWorkflowRef "github.head_ref"; + REPO = mkWorkflowRef "github.repository"; + }; + "if" = "!contains(github.event.pull_request.labels.*.name, 'ghstack')"; + run = mkWorkflowRun [ + "git" + "push" + "origin" + "--delete" + ''"$HEAD_REF"'' + ]; + }; + + cleanup-ghstack = { env = { GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; - PR_BASE_REF = mkWorkflowRef "github.event.pull_request.base.ref"; - PR_HEAD_REF = mkWorkflowRef "github.event.pull_request.head.ref"; + BASE_REF = mkWorkflowRef "github.base_ref"; + HEAD_REF = mkWorkflowRef "github.head_ref"; REPO = mkWorkflowRef "github.repository"; }; + "if" = "contains(github.event.pull_request.labels.*.name, 'ghstack')"; run = '' - if [[ "$PR_HEAD_REF" =~ ^gh/[^/]+/[^/]+/head$ && "$PR_BASE_REF" =~ ^gh/[^/]+/[^/]+/base$ && "''${PR_HEAD_REF%/head}" == "''${PR_BASE_REF%/base}" ]]; then - for role in base head orig; do - git push origin --delete "''${PR_HEAD_REF%/head}/$role" || true - done - else - git push origin --delete "$PR_HEAD_REF" || true - fi + for role in base head orig; do + git push origin --delete "''${HEAD_REF%/head}/$role" || true + done ''; }; @@ -183,6 +235,44 @@ with lib; }; }; + ghstack-merge = { + env = { + GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; + PR_HTML_URL = mkWorkflowRef "github.event.issue.pull_request.html_url"; + }; + "if" = concatStringsSep " && " [ + "contains(github.event.pull_request.labels.*.name, 'dependencies')" + "contains(github.event.issue.labels.*.name, 'ghstack')" + ]; + run = mkWorkflowRun [ + "nix" + "run" + "nixpkgs#sapling" + "--" + "ghstack" + "land" + ''"$PR_HTML_URL"'' + ]; + }; + + pr-merge = { + env = { + GITHUB_TOKEN = mkWorkflowRef "steps.createGithubAppToken.outputs.token"; + PR_HTML_URL = mkWorkflowRef "github.event.issue.pull_request.html_url"; + }; + "if" = concatStringsSep " && " [ + "contains(github.event.pull_request.labels.*.name, 'dependencies')" + "!contains(github.event.issue.labels.*.name, 'ghstack')" + ]; + run = mkWorkflowRun [ + "gh" + "pr" + "merge" + "--auto" + ''"$PR_HTML_URL"'' + ]; + }; + nix-flake-check.run = mkWorkflowRun [ "nix" "flake" @@ -238,19 +328,15 @@ with lib; }; }; - main = { + push = { enable = mkDefault true; settings = { - name = "Main"; + name = "Push"; on = { push.branches = [ "main" "release-*" ]; - pull_request.branches = [ - "main" - "gh/*/*/base" - ]; }; jobs.check = { runs-on = "ubuntu-latest"; @@ -265,13 +351,27 @@ with lib; }; }; - release = { + integration = { enable = mkDefault true; settings = { - name = "Release"; - on.push.tags = [ "v?[0-9]+.[0-9]+.[0-9]+*" ]; + name = "Integration"; + on.pull_request.branches = [ + "main" + "gh/*/*/base" + ]; jobs = { + triage = { + runs-on = "ubuntu-latest"; + steps = with config.github.actions; [ + create-github-app-token + checkout + assign-pr + add-dependencies-labels + add-ghstack-labels + ]; + }; check = { + needs = [ "triage" ]; runs-on = "ubuntu-latest"; steps = with config.github.actions; [ create-github-app-token @@ -281,55 +381,73 @@ with lib; nix-flake-check ]; }; - - publish = { + merge = { needs = [ "check" ]; runs-on = "ubuntu-latest"; steps = with config.github.actions; [ create-github-app-token checkout - create-release + setup-nix + ghstack-merge + pr-merge ]; }; }; }; }; - triage = { + release = { enable = mkDefault true; settings = { - name = "Triage"; - on = { - pull_request.types = [ - "closed" - "opened" - ]; - check_suite.types = [ "completed" ]; - }; + name = "Release"; + on.push.tags = [ "v?[0-9]+.[0-9]+.[0-9]+*" ]; jobs = { - labels = { - "if" = "github.event.action == 'opened'"; + check = { runs-on = "ubuntu-latest"; steps = with config.github.actions; [ create-github-app-token checkout - add-labels + setup-nix + direnv + nix-flake-check ]; }; - cleanup = { - "if" = "github.event.action == 'closed'"; + publish = { + needs = [ "check" ]; runs-on = "ubuntu-latest"; steps = with config.github.actions; [ create-github-app-token checkout - cleanup + create-release ]; }; }; }; }; + cleanup = { + enable = mkDefault true; + settings = { + name = "Cleanup"; + on = { + pull_request.types = [ + "closed" + ]; + check_suite.types = [ "completed" ]; + }; + jobs.cleanup = { + runs-on = "ubuntu-latest"; + steps = with config.github.actions; [ + create-github-app-token + checkout + cleanup-pr + cleanup-ghstack + ]; + }; + }; + }; + update = { enable = mkDefault true; settings = {