From bb933c22b75080b11560b703c50a4bfd6d209851 Mon Sep 17 00:00:00 2001 From: Greg Burd Date: Fri, 15 Sep 2023 13:54:20 -0400 Subject: [PATCH] gha --- .../workflows/cachix-install-nix-action.yml | 32 ++++ .github/workflows/combine-prs.yml | 152 +++++++++++++++++ .github/workflows/dependabot.yml | 7 + .github/workflows/main.yml | 67 ++++++++ .github/workflows/nix-github-actions.yml | 21 +++ .gitignore | 1 + TODO | 38 ++++- flake.lock | 154 +++++++++++++++++- flake.nix | 38 ++++- shell.nix | 4 +- 10 files changed, 498 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/cachix-install-nix-action.yml create mode 100644 .github/workflows/combine-prs.yml create mode 100644 .github/workflows/dependabot.yml create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/nix-github-actions.yml diff --git a/.github/workflows/cachix-install-nix-action.yml b/.github/workflows/cachix-install-nix-action.yml new file mode 100644 index 0000000..8eccd7b --- /dev/null +++ b/.github/workflows/cachix-install-nix-action.yml @@ -0,0 +1,32 @@ +name: Nix Flake actions + +on: + pull_request: + push: + branches: + - master + - main + +jobs: + nix-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + - id: set-matrix + name: Generate Nix Matrix + run: | + set -Eeu + echo "matrix=$(nix eval --json '.#githubActions.matrix')" >> "$GITHUB_OUTPUT" + + nix-build: + needs: nix-matrix + runs-on: ${{ matrix.os }} + strategy: + matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + - run: nix build -L ".#${{ matrix.attr }}" diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml new file mode 100644 index 0000000..28fb480 --- /dev/null +++ b/.github/workflows/combine-prs.yml @@ -0,0 +1,152 @@ +name: 'Combine PRs' + +# Controls when the action will run - in this case triggered manually +on: + workflow_dispatch: + inputs: + branchPrefix: + description: 'Branch prefix to find combinable PRs based on' + required: true + default: 'dependabot' + mustBeGreen: + description: 'Only combine PRs that are green (status is success). Set to false if repo does not run checks' + type: boolean + required: true + default: true + combineBranchName: + description: 'Name of the branch to combine PRs into' + required: true + default: 'combine-prs-branch' + ignoreLabel: + description: 'Exclude PRs with this label' + required: true + default: 'nocombine' + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "combine-prs" + combine-prs: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - uses: actions/github-script@v6 + id: create-combined-pr + name: Create Combined PR + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', { + owner: context.repo.owner, + repo: context.repo.repo + }); + let branchesAndPRStrings = []; + let baseBranch = null; + let baseBranchSHA = null; + for (const pull of pulls) { + const branch = pull['head']['ref']; + console.log('Pull for branch: ' + branch); + if (branch.startsWith('${{ github.event.inputs.branchPrefix }}')) { + console.log('Branch matched prefix: ' + branch); + let statusOK = true; + if(${{ github.event.inputs.mustBeGreen }}) { + console.log('Checking green status: ' + branch); + const stateQuery = `query($owner: String!, $repo: String!, $pull_number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number:$pull_number) { + commits(last: 1) { + nodes { + commit { + statusCheckRollup { + state + } + } + } + } + } + } + }` + const vars = { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pull['number'] + }; + const result = await github.graphql(stateQuery, vars); + const [{ commit }] = result.repository.pullRequest.commits.nodes; + const state = commit.statusCheckRollup.state + console.log('Validating status: ' + state); + if(state != 'SUCCESS') { + console.log('Discarding ' + branch + ' with status ' + state); + statusOK = false; + } + } + console.log('Checking labels: ' + branch); + const labels = pull['labels']; + for(const label of labels) { + const labelName = label['name']; + console.log('Checking label: ' + labelName); + if(labelName == '${{ github.event.inputs.ignoreLabel }}') { + console.log('Discarding ' + branch + ' with label ' + labelName); + statusOK = false; + } + } + if (statusOK) { + console.log('Adding branch to array: ' + branch); + const prString = '#' + pull['number'] + ' ' + pull['title']; + branchesAndPRStrings.push({ branch, prString }); + baseBranch = pull['base']['ref']; + baseBranchSHA = pull['base']['sha']; + } + } + } + if (branchesAndPRStrings.length == 0) { + core.setFailed('No PRs/branches matched criteria'); + return; + } + try { + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/heads/' + '${{ github.event.inputs.combineBranchName }}', + sha: baseBranchSHA + }); + } catch (error) { + console.log(error); + core.setFailed('Failed to create combined branch - maybe a branch by that name already exists?'); + return; + } + + let combinedPRs = []; + let mergeFailedPRs = []; + for(const { branch, prString } of branchesAndPRStrings) { + try { + await github.rest.repos.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + base: '${{ github.event.inputs.combineBranchName }}', + head: branch, + }); + console.log('Merged branch ' + branch); + combinedPRs.push(prString); + } catch (error) { + console.log('Failed to merge branch ' + branch); + mergeFailedPRs.push(prString); + } + } + + console.log('Creating combined PR'); + const combinedPRsString = combinedPRs.join('\n'); + let body = '✅ This PR was created by the Combine PRs action by combining the following PRs:\n' + combinedPRsString; + if(mergeFailedPRs.length > 0) { + const mergeFailedPRsString = mergeFailedPRs.join('\n'); + body += '\n\n⚠️ The following PRs were left out due to merge conflicts:\n' + mergeFailedPRsString + } + await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Combined PR', + head: '${{ github.event.inputs.combineBranchName }}', + base: baseBranch, + body: body + }); diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 0000000..718572b --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..48c2a98 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,67 @@ +name: "Hello" +on: + push: + branches: [ main, master ] + pull_request: + types: [opened, reopened, synchronize] + +permissions: + contents: read + issues: write + +# concurrency: +# group: ${{ github.ref }} +# cancel-in-progress: true + +env: + GIT_BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_SHA: ${{ github.sha }} + +jobs: + nix-build: + needs: nix-matrix + runs-on: ${{ matrix.os }} + strategy: + matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + - run: nix build -L ".#${{ matrix.attr }}" + + # runs-on: ubuntu-latest + # name: Build on ${{ matrix.distro }} (${{ matrix.version }}) for ${{ matrix.arch }} + + # # strategy: + # # matrix: + # # include: + # # - arch: x86_64 + # # distro: Debian + # # version: bullseye + # # - arch: aarch64 + # # distro: Debian + # # version: bullseye + # # - arch: ppc64le + # # distro: Debian + # # version: bullseye + # # - arch: risc64 + # # distro: Ubuntu + # # version: ubuntu_latest + + # steps: + # - uses: actions/checkout@v3 + # - uses: cachix/install-nix-action@v22 + # with: + # github_access_token: ${{ secrets.GITHUB_TOKEN }} + # - run: nix build -L + # - run: nix flake check + + # nix-build: + # needs: nix-matrix + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: ${{fromJSON(needs.nix-matrix.outputs.matrix)}} + # steps: + # - uses: actions/checkout@v3 + # - uses: cachix/install-nix-action@v22 + # - run: nix build -L ".#${{ matrix.attr }}" diff --git a/.github/workflows/nix-github-actions.yml b/.github/workflows/nix-github-actions.yml new file mode 100644 index 0000000..f260d5f --- /dev/null +++ b/.github/workflows/nix-github-actions.yml @@ -0,0 +1,21 @@ +name: Nix Flake actions + +on: + pull_request: + types: [opened, reopened, synchronize] + push: + branches: [main, master] + +jobs: + nix-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v3 + - uses: cachix/install-nix-action@v22 + - id: set-matrix + name: Generate Nix Matrix + run: | + set -Eeu + echo "matrix=$(nix eval --json '.#githubActions.matrix')" >> "$GITHUB_OUTPUT" diff --git a/.gitignore b/.gitignore index 3273012..cde87e9 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ bulid .libs .links .direnv +.pre-commit-config.yaml version.c diff --git a/TODO b/TODO index 0bba161..8dc659d 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,36 @@ -* add GitHub Actions/workflow to build all targets, upload/publish all artifacts - * deb, rpm?, tgz of source? - * Docker container on DockerHub, GitHub Container Repository (ghcr.io) - * containers could have multiple tags as in `latest` and `1.0.0` -* build windows MSYS2 +GOALS: +------------------------------------------------------------------------------- +* compile + * GNU Autoconf + * GNU GCC +* platforms: + * Linux: + * "i386-linux" "x86_64-linux" + "armv6l-linux" "armv7l-linux" "aarch64-linux" + "powerpc64le-linux" + "riscv64-linux" + * "x86_64-darwin" "aarch64-darwin" + * Windows 10+ 64bit + * "mingw-w64" (zicross or nixcrpkgs?) + * Raspberry Pi? + * "armv7l-hf-multiplatform" (ARMv7, v8? v8.2?) + * "aarch64-hf-multiplatform" (AArch64) + * VM image/OSv + * x86_64, arm?, (kvm, firecracker, hyper-v, ...) +* docker: + * "x86_64-linux", "aarch64-linux" (AWS/EC2 Graviton 1/2) + * upload/publish all artifacts +* installers/packages + * tgz of source for release + * tgz for binaries + * deb, rpm, flake, WiX (Windows) + * signed and published + * macOS? + * asdf? +* CI/CD + * GHA/Actuated.dev + +------------------------------------------------------------------------------- * Gitpod * README.md * build and other badges diff --git a/flake.lock b/flake.lock index f4fd0db..0310f4e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -19,6 +35,24 @@ } }, "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1685518550, + "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { "locked": { "lastModified": 1659877975, "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", @@ -33,6 +67,27 @@ "type": "github" } }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nix-filter": { "locked": { "lastModified": 1666547822, @@ -48,6 +103,26 @@ "type": "github" } }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1693660503, + "narHash": "sha256-B/g2V4v6gjirFmy+I5mwB2bCYc0l3j5scVfwgl6WOl8=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "bd5bdbb52350e145c526108f4ef192eb8e554fa0", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1694532420, @@ -63,7 +138,39 @@ "type": "github" } }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1685801374, + "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.05", + "repo": "nixpkgs", + "type": "github" + } + }, "nixpkgs_2": { + "locked": { + "lastModified": 1689261696, + "narHash": "sha256-LzfUtFs9MQRvIoQ3MfgSuipBVMXslMPH/vZ+nM40LkA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "df1eee2aa65052a18121ed4971081576b25d6b5c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { "locked": { "lastModified": 1653936696, "narHash": "sha256-M6bJShji9AIDZ7Kh7CPwPBPb/T7RiVev2PAcOi4fxDQ=", @@ -79,7 +186,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1661151577, "narHash": "sha256-++S0TuJtuz9IpqP8rKktWyHZKpgdyrzDFUXVY07MTRI=", @@ -95,10 +202,34 @@ "type": "github" } }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils_2", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1694364351, + "narHash": "sha256-oadhSCqopYXxURwIA6/Anpe5IAG11q2LhvTJNP5zE6o=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4f883a76282bc28eb952570afc3d8a1bf6f481d7", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", "zicross": "zicross" } }, @@ -117,6 +248,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "utils": { "locked": { "lastModified": 1667395993, @@ -135,7 +281,7 @@ "zicross": { "inputs": { "nix-filter": "nix-filter", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs_3", "utils": "utils", "zig-binaries": "zig-binaries" }, @@ -155,8 +301,8 @@ }, "zig-binaries": { "inputs": { - "flake-utils": "flake-utils_2", - "nixpkgs": "nixpkgs_3" + "flake-utils": "flake-utils_3", + "nixpkgs": "nixpkgs_4" }, "locked": { "lastModified": 1669076785, diff --git a/flake.nix b/flake.nix index a681270..d34f875 100644 --- a/flake.nix +++ b/flake.nix @@ -10,8 +10,11 @@ flake-utils.url = "github:numtide/flake-utils"; zicross.url = "github:flyx/Zicross"; }; + inputs.pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; + inputs.nix-github-actions.url = "github:nix-community/nix-github-actions"; + inputs.nix-github-actions.inputs.nixpkgs.follows = "nixpkgs"; - outputs = { self, nixpkgs, flake-utils, zicross }: + outputs = { self, nixpkgs, flake-utils, pre-commit-hooks, nix-github-actions, zicross }: let inherit (nixpkgs) lib; officialRelease = false; @@ -22,7 +25,7 @@ then "" else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}"; - supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; + supportedSystems = [ "i386-linux" "x86_64-linux" "armv6l-linux" "armv7l-linux" "aarch64-linux" "powerpc64le-linux" "riscv64-linux" "x86_64-darwin" "aarch64-darwin" ]; # Generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'. forAllSystems = nixpkgs.lib.genAttrs supportedSystems; @@ -55,18 +58,41 @@ ]; nativeBuildInputs = [ autoreconfHook ]; meta = { - maintainers = [ "Symas Corporation " "Greg Burd " ]; - homepage = "https://github.com/openldap/openldap"; - license = licenses.openldap; + maintainers = [ "Greg Burd " ]; + downloadPage = "https://github.com/gburd/hello/releases"; + changelog = "https://raw.githubusercontent.com/gburd/hello/main/ChangeLog"; + platforms = supportedSystems; + homepage = "https://github.com/gburd/hello"; + license = "https://github.com/gburd/hello/LICENSE"; mainProgram = "hello"; }; }; }) ]; + + checks = { + pre-commit-check = pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + nixpkgs-fmt.enable = true; + }; + }; + }; + + devShell = nixpkgs.legacyPackages.${system}.mkShell { + inherit (self.checks.${system}.pre-commit-check) shellHook; + }; + }; in rec { - packages = { inherit (pkgs) hello; }; + packages = { + inherit (pkgs) hello; + + githubActions = nix-github-actions.lib.mkGithubMatrix { + checks = nixpkgs.lib.getAttrs [ "x86_64-linux" "x86_64-darwin" ] self.packages; + }; + }; packages.default = self.packages.${system}.hello; packages.container = pkgs.callPackage ./container.nix { package = packages.default; }; #packages.win64zip = pkgs.callPackage ./win64zip.nix { package = packages.default; }; diff --git a/shell.nix b/shell.nix index 2e72968..a627748 100644 --- a/shell.nix +++ b/shell.nix @@ -1,5 +1,7 @@ { pkgs ? import {} }: + pkgs.mkShell { # nativeBuildInputs is usually what you want -- tools you need to run - nativeBuildInputs = with pkgs.buildPackages; [ ripgrep ]; + nativeBuildInputs = with pkgs.buildPackages; [ ripgrep act ]; + DOCKER_BUILDKIT = 1; }