From 400cb5169245ef1c0b253462ee1a5d8ad1607801 Mon Sep 17 00:00:00 2001 From: iphydf Date: Tue, 2 Jan 2024 14:30:12 +0000 Subject: [PATCH] feat: Add labels to settings. Also implemented sync. --- admin/settings.yaml | 193 +++++++++++++++++++++++++++++++ src/GitHub/Paths/Repos/Labels.hs | 28 +++++ src/GitHub/Tools/Requests.hs | 12 ++ src/GitHub/Tools/Settings.hs | 59 +++++++--- src/GitHub/Types/Settings.hs | 26 +++++ 5 files changed, 301 insertions(+), 17 deletions(-) create mode 100644 src/GitHub/Paths/Repos/Labels.hs create mode 100644 src/GitHub/Types/Settings.hs diff --git a/admin/settings.yaml b/admin/settings.yaml index 64bad98..7d7f625 100644 --- a/admin/settings.yaml +++ b/admin/settings.yaml @@ -43,6 +43,134 @@ _common: - "code-review/reviewable" - "restyled" + # GitHub Issue/PR labels. + labels: &labels + ############################################################################# + # + # :: PR labels relevant to the release notes. + # + ############################################################################# + + "api break": + color: "d96f0b" + description: "Change breaks API or ABI" + + "bug": + color: "ee0701" + description: "Bug fix for the user, not a fix to a build script" + + "chore": + color: "f9d0c4" + description: "Updating grunt tasks etc; no production code change" + + "cleanup": + color: "fef2c0" + description: "Internal code cleanup, possibly affecting semantics, e.g. deleting a deprecated feature." + + "dependencies": + color: "0366d6" + description: "Pull requests that update a dependency file" + + "documentation": + color: "1d76db" + description: "Changes to the documentation" + + "enhancement": + color: "84b6eb" + description: "New feature for the user, not a new feature for build script" + + "style": + color: "fef2c0" + description: "Formatting, missing semi colons, etc; no production code change" + + "performance": + color: "fef2c0" + description: "A code change that improves performance" + + "refactor": + color: "fef2c0" + description: "Refactoring production code, eg. renaming a variable, not affecting semantics" + + "test": + color: "0e8a16" + description: "Adding missing tests, refactoring tests; no production code change" + + ############################################################################# + # + # :: Bug labels + # + ############################################################################# + + "meta": + color: "256784" + description: "Process related" + + "packaging": + color: "1d76db" + description: "Packaging" + + "proposal": + color: "8effa5" + description: "Proposals" + + "question": + color: "cc317c" + description: "Questions" + + "security": + color: "d93f0b" + description: "Security" + + "suggestion": + color: "d93f0b" + description: "Suggestions" + + "good first issue": + color: "7057ff" + description: "Good first issue" + + "duplicate": + color: "cccccc" + description: "This issue or pull request already exists" + + "help wanted": + color: "128a0c" + description: "Extra attention is needed" + + "not reproducible": + color: "e6e6e6" + description: "Won't Fix (Not reproducible)" + + "wontfix": + color: "ffffff" + description: "Won't Fix (Intended behaviour)" + + "invalid": + color: "d73a49" + description: "Irrelevant or spam" + + ############################################################################# + # + # :: Priority labels + # + ############################################################################# + + "P0": + color: "d93f0b" + description: "Critical priority" + + "P1": + color: "eb6420" + description: "High priority" + + "P2": + color: "ffcccc" + description: "Medium priority" + + "P3": + color: "eeeeee" + description: "Low priority" + btox: editRepo: <<: *editRepo @@ -51,6 +179,12 @@ btox: homepage: https://tox.chat/ topics: toxcore, network, p2p, security, encryption, cryptography, android, ios, web + labels: + <<: *labels + "WIP": + color: "ededed" + description: "Work in progress" + branches: "master": <<: *branchProtection @@ -83,6 +217,7 @@ ci-tools: description: Common tools for building TokTok repositories on CI topics: haskell, ci + labels: *labels branches: "master": <<: *branchProtection @@ -105,6 +240,33 @@ c-toxcore: homepage: "https://tox.chat" topics: "toxcore, network, p2p, security, encryption, cryptography" + labels: + <<: *labels + # Labels specific to c-toxcore. + "bootstrap": + color: "01707f" + description: "Bootstrap" + + "crypto": + color: "1d76db" + description: "Crypto" + + "file transfers": + color: "e02abf" + description: "File Transfers" + + "messenger": + color: "d93f0b" + description: "Messenger" + + "network": + color: "d4c5f9" + description: "Network" + + "toxav": + color: "0052cc" + description: "Audio/video" + branches: "master": <<: *branchProtection @@ -158,6 +320,7 @@ c-toxcore-hs: description: C bindings to the Haskell implementation of the Tox protocol topics: toxcore + labels: *labels branches: "master": <<: *branchProtection @@ -181,6 +344,7 @@ dockerfiles: description: Dockerfiles for (cross-)compiling TokTok projects for various platforms topics: docker, ghc, android, windows, qt, buildfarm, bazel + labels: *labels branches: "master": <<: *branchProtection @@ -216,6 +380,7 @@ experimental: description: "Experimental - Anyone can submit anything in here" homepage: "https://toktok.ltd" + labels: *labels branches: "master": <<: *branchProtection @@ -239,6 +404,7 @@ go-toxcore-c: description: The golang bindings for libtoxcore (Project Tox). topics: toxcore + labels: *labels branches: "master": <<: *branchProtection @@ -262,6 +428,7 @@ hs-apigen: description: FFI API generator for TokTok style C API headers. topics: c, ffi, codegen + labels: *labels branches: "master": <<: *branchProtection @@ -286,6 +453,7 @@ hs-cimple: description: Cimple and Apidsl language parsers and tools topics: c, dsl, parser + labels: *labels branches: "master": <<: *branchProtection @@ -311,6 +479,7 @@ hs-github-tools: description: Small GitHub utilities like pull-status and changelog generator topics: github, haskell + labels: *labels branches: "master": <<: *branchProtection @@ -337,6 +506,7 @@ hs-msgpack-arbitrary: description: Arbitrary instance for Data.MessagePack.Types.Object. topics: msgpack, haskell + labels: *labels branches: "master": <<: *branchProtection @@ -364,6 +534,7 @@ hs-msgpack-binary: homepage: http://msgpack.org/ topics: msgpack, haskell + labels: *labels branches: "master": <<: *branchProtection @@ -390,6 +561,7 @@ hs-msgpack-rpc-conduit: description: A MessagePack RPC implementation in Haskell topics: msgpack, rpc, protocol, network + labels: *labels branches: "master": <<: *branchProtection @@ -417,6 +589,7 @@ hs-msgpack-testsuite: homepage: http://msgpack.org/ topics: msgpack, haskell + labels: *labels branches: "master": <<: *branchProtection @@ -443,6 +616,7 @@ hs-msgpack-types: description: Abstract data types and type classes for Haskell to MessagePack value converters topics: msgpack, haskell + labels: *labels branches: "master": <<: *branchProtection @@ -469,6 +643,7 @@ hs-schema: description: Encoding-independent schemas for Haskell data types homepage: https://hackage.haskell.org/package/schema + labels: *labels branches: "master": <<: *branchProtection @@ -493,6 +668,7 @@ hs-tokstyle: description: Style checker for TokTok C projects topics: linter, style, c + labels: *labels branches: "master": <<: *branchProtection @@ -519,6 +695,7 @@ hs-toxcore-c: description: Haskell bindings to C toxcore implementation topics: toxcore + labels: *labels branches: "master": <<: *branchProtection @@ -546,6 +723,7 @@ hs-toxcore: homepage: https://toktok.ltd/spec topics: haskell, toxcore, network, p2p + labels: *labels branches: "master": <<: *branchProtection @@ -576,6 +754,7 @@ hs-toxcore: # description: A simple console based text client for Tox. # homepage: https://hackage.haskell.org/package/toxxi # +# labels: *labels # branches: # "master": # <<: *branchProtection @@ -601,6 +780,7 @@ js-toxcore-c: homepage: "https://toktok.ltd" topics: "toxcore, js, ffi" + labels: *labels branches: "master": <<: *branchProtection @@ -630,6 +810,12 @@ py-toxcore-c: description: Python binding for Project-Tox the skype replacement. topics: toxcore, python, ffi + labels: + <<: *labels + "error": + color: "ededed" + description: "Error" + branches: "master": <<: *branchProtection @@ -654,6 +840,7 @@ qTox: homepage: https://qtox.github.io/ topics: tox, chat + labels: *labels branches: "master": <<: *branchProtection @@ -676,6 +863,7 @@ spec: homepage: https://toktok.ltd/spec topics: tox, protocol, toxcore + labels: *labels branches: "master": <<: *branchProtection @@ -697,6 +885,7 @@ toktok-stack: description: "A snapshot of the complete software stack (excluding some external libraries and programs)" homepage: "https://toktok.ltd" + labels: *labels branches: "master": <<: *branchProtection @@ -727,6 +916,7 @@ toxic: description: An ncurses-based Tox client topics: tox, console, chat + labels: *labels branches: "master": <<: *branchProtection @@ -753,6 +943,7 @@ toxins: description: A collection of small programs using toxcore. topics: toxcore + labels: *labels branches: "master": <<: *branchProtection @@ -776,6 +967,7 @@ website: description: The TokTok website topics: toktok, tox + labels: *labels branches: "master": <<: *branchProtection @@ -804,6 +996,7 @@ zig-toxcore-c: description: "Zig wrapper for c-toxcore library." homepage: "https://toktok.ltd" + labels: *labels branches: "master": <<: *branchProtection diff --git a/src/GitHub/Paths/Repos/Labels.hs b/src/GitHub/Paths/Repos/Labels.hs new file mode 100644 index 0000000..a5ad2b7 --- /dev/null +++ b/src/GitHub/Paths/Repos/Labels.hs @@ -0,0 +1,28 @@ +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE OverloadedStrings #-} +module GitHub.Paths.Repos.Labels where + +import Data.Aeson (encode) +import Data.Text (Text) +import Data.Vector (Vector) +import GitHub.Data.Request (CommandMethod (Delete, Patch, Post), + FetchCount (FetchAll), + GenRequest (Command), MediaType (..), + RW (..), Request, command, pagedQuery) +import GitHub.Types.Settings (Label) + +getLabelsR :: Text -> Text -> Request 'RO (Vector Label) +getLabelsR user repo = + pagedQuery ["repos", user, repo, "labels"] [] FetchAll + +createLabelR :: Text -> Text -> Label -> Request 'RW Label +createLabelR user repo = + command Post ["repos", user, repo, "labels"] . encode + +updateLabelR :: Text -> Text -> Text -> Label -> Request 'RW Label +updateLabelR user repo name = + command Patch ["repos", user, repo, "labels", name] . encode + +deleteLabelR :: Text -> Text -> Text -> GenRequest 'MtUnit 'RW () +deleteLabelR user repo name = + Command Delete ["repos", user, repo, "labels", name] mempty diff --git a/src/GitHub/Tools/Requests.hs b/src/GitHub/Tools/Requests.hs index dd939b3..9fb2dae 100644 --- a/src/GitHub/Tools/Requests.hs +++ b/src/GitHub/Tools/Requests.hs @@ -7,6 +7,7 @@ import Data.Aeson (FromJSON, ToJSON (toJSON), import qualified Data.Aeson.KeyMap as KeyMap import qualified Data.Vector as V import qualified GitHub +import GitHub.Data.Request (MediaType (..)) import Network.HTTP.Client (Manager) removeNulls :: ToJSON a => a -> Value @@ -49,3 +50,14 @@ mutate auth mgr req = do case response of Left err -> throwM err Right res -> return res + +mutate_ + :: GitHub.Auth + -> Manager + -> GitHub.GenRequest 'MtUnit 'GitHub.RW () + -> IO () +mutate_ auth mgr req = do + response <- GitHub.executeRequestWithMgr mgr auth req + case response of + Left err -> throwM err + Right res -> return res diff --git a/src/GitHub/Tools/Settings.hs b/src/GitHub/Tools/Settings.hs index 6f82c40..20e678a 100644 --- a/src/GitHub/Tools/Settings.hs +++ b/src/GitHub/Tools/Settings.hs @@ -1,21 +1,20 @@ +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE TemplateHaskell #-} -{-# OPTIONS_GHC -Wwarn #-} +{-# LANGUAGE ViewPatterns #-} module GitHub.Tools.Settings ( syncSettings , validateSettings ) where -import Control.Monad (forM_, unless) +import Control.Monad (forM_, unless, when) import Data.Aeson (Value (Array, Object, String)) import qualified Data.Aeson.KeyMap as KeyMap -import Data.Aeson.TH (Options (fieldLabelModifier), - defaultOptions, deriveJSON) import qualified Data.ByteString.Char8 as BS import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HashMap -import Data.List (isPrefixOf, nub, (\\)) +import Data.List (isPrefixOf, nub, sortOn, (\\)) import Data.Maybe (mapMaybe) import Data.Text (Text) import qualified Data.Text as Text @@ -24,16 +23,18 @@ import Data.Yaml (encode) import qualified GitHub import qualified GitHub.Paths.Repos as Repos import qualified GitHub.Paths.Repos.Branches as Branches -import GitHub.Tools.Requests (mutate) -import Network.HTTP.Client (newManager) +import qualified GitHub.Paths.Repos.Labels as Labels +import GitHub.Tools.Requests (mutate, mutate_, request) +import GitHub.Types.Settings (Label (Label, labelName), + Settings (..)) +import Network.HTTP.Client (Manager, newManager) import Network.HTTP.Client.TLS (tlsManagerSettings) -import Text.Casing (camel) -data Settings = Settings - { settingsEditRepo :: Value - , settingsBranches :: Maybe (HashMap Text Value) - } -$(deriveJSON defaultOptions{fieldLabelModifier = camel . drop (Text.length "Settings")} ''Settings) +debug :: Bool +debug = False + +delete :: Bool +delete = False syncSettings :: GitHub.Auth @@ -44,16 +45,40 @@ syncSettings auth repos repoFilter = do -- Initialise HTTP manager so we can benefit from keep-alive connections. mgr <- newManager tlsManagerSettings - forM_ (filterRepos $ each repos) $ \(repo, Settings{..}) -> do + forM_ (sortOn fst . filterRepos . each $ repos) $ \(repo, Settings{..}) -> do editRes <- mutate auth mgr (Repos.editRepoR "TokTok" repo settingsEditRepo) - BS.putStrLn $ encode editRes + when debug $ BS.putStrLn $ encode editRes + syncLabels auth mgr repo settingsLabels forM_ (maybe [] each settingsBranches) $ \(branch, update) -> do protRes <- mutate auth mgr (Branches.addProtectionR "TokTok" repo branch update) - BS.putStrLn $ encode protRes + when debug $ BS.putStrLn $ encode protRes where filterRepos = filter ((repoFilter `Text.isPrefixOf`) . fst) +syncLabels :: GitHub.Auth -> Manager -> Text -> HashMap Text Label -> IO () +syncLabels auth mgr repo labels = do + putStrLn $ "Syncing labels to " <> Text.unpack repo + let newLabels = nub . map (\(Just -> labelName, label) -> label{labelName}) . HashMap.toList $ labels + oldLabels <- nub . V.toList <$> request (Just auth) mgr (Labels.getLabelsR "TokTok" repo) + forM_ (oldLabels \\ newLabels) $ \case + Label{labelName = Nothing} -> return () + lbl@Label{labelName = Just lblName} -> do + if delete + then do + putStrLn $ "DELETING old label: " <> show lbl + mutate_ auth mgr (Labels.deleteLabelR "TokTok" repo lblName) + else putStrLn $ "NOT deleting old label: " <> show lbl + forM_ (newLabels \\ oldLabels) $ \case + Label{labelName = Nothing} -> return () + lbl@Label{labelName = Just lblName} -> do + print lbl + res <- if any (\old -> labelName old == labelName lbl) oldLabels + then mutate auth mgr (Labels.updateLabelR "TokTok" repo lblName lbl) + else mutate auth mgr (Labels.createLabelR "TokTok" repo lbl) + BS.putStrLn $ encode res + + validateSettings :: MonadFail m => HashMap Text Settings -> m () validateSettings repos = do commonBranches <- case HashMap.lookup "_common" repos >>= settingsBranches of diff --git a/src/GitHub/Types/Settings.hs b/src/GitHub/Types/Settings.hs new file mode 100644 index 0000000..010f1cf --- /dev/null +++ b/src/GitHub/Types/Settings.hs @@ -0,0 +1,26 @@ +{-# LANGUAGE TemplateHaskell #-} +module GitHub.Types.Settings + ( Label (..) + , Settings (..) + ) where + +import Data.Aeson (Value) +import Data.Aeson.TH (Options (fieldLabelModifier), + defaultOptions, deriveJSON) +import Data.HashMap.Strict (HashMap) +import Data.Text (Text) +import Text.Casing (camel) + +data Label = Label + { labelName :: Maybe Text + , labelDescription :: Maybe Text + , labelColor :: Text + } deriving (Show, Eq) +$(deriveJSON defaultOptions{fieldLabelModifier = camel . drop (length "Label")} ''Label) + +data Settings = Settings + { settingsEditRepo :: Value + , settingsBranches :: Maybe (HashMap Text Value) + , settingsLabels :: HashMap Text Label + } deriving (Show) +$(deriveJSON defaultOptions{fieldLabelModifier = camel . drop (length "Settings")} ''Settings)