Merge branch 'fix/consolidate-workflows' into new
This commit is contained in:
commit
315b4fc052
26 changed files with 487 additions and 30 deletions
40
.github/workflows/codeql.yml
vendored
Normal file
40
.github/workflows/codeql.yml
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
name: CodeQL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [dev, main]
|
||||
pull_request:
|
||||
branches: [dev, main]
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [go, javascript-typescript, python, actions]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v4
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
11
go.mod
11
go.mod
|
|
@ -3,7 +3,10 @@ module github.com/host-uk/core
|
|||
go 1.25.5
|
||||
|
||||
require (
|
||||
<<<<<<< HEAD
|
||||
code.gitea.io/sdk/gitea v0.23.2
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
github.com/Snider/Borg v0.2.0
|
||||
github.com/getkin/kin-openapi v0.133.0
|
||||
github.com/host-uk/core/internal/core-ide v0.0.0-20260204004957-989b7e1e6555
|
||||
|
|
@ -36,6 +39,7 @@ require (
|
|||
github.com/42wim/httpsig v1.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||
github.com/Snider/Enchantrix v0.0.2 // indirect
|
||||
github.com/TwiN/go-color v1.4.1 // indirect
|
||||
github.com/adrg/xdg v0.5.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect
|
||||
|
|
@ -62,8 +66,11 @@ require (
|
|||
github.com/ebitengine/purego v0.9.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
<<<<<<< HEAD
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.7.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.16.4 // indirect
|
||||
|
|
@ -74,6 +81,8 @@ require (
|
|||
github.com/godbus/dbus/v5 v5.2.2 // indirect
|
||||
github.com/gofrs/flock v0.12.1 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/go-github/v39 v39.2.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/jsonschema-go v0.4.2 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
|
|
@ -90,6 +99,7 @@ require (
|
|||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
|
||||
|
|
@ -103,6 +113,7 @@ require (
|
|||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/samber/lo v1.52.0 // indirect
|
||||
github.com/schollz/progressbar/v3 v3.18.0 // indirect
|
||||
github.com/sergi/go-diff v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||
|
|
|
|||
39
go.sum
39
go.sum
|
|
@ -16,8 +16,17 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
|
|||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||
<<<<<<< HEAD
|
||||
github.com/Snider/Borg v0.2.0 h1:iCyDhY4WTXi39+FexRwXbn2YpZ2U9FUXVXDZk9xRCXQ=
|
||||
github.com/Snider/Borg v0.2.0/go.mod h1:TqlKnfRo9okioHbgrZPfWjQsztBV0Nfskz4Om1/vdMY=
|
||||
=======
|
||||
github.com/Snider/Borg v0.1.0 h1:tLvrytPMIM2To0xByYP+KHLcT9pg9P9y9uRTyG6r9oc=
|
||||
github.com/Snider/Borg v0.1.0/go.mod h1:0GMzdXYzdFZpR25IFne7ErqV/YFQHsX1THm1BbncMPo=
|
||||
github.com/Snider/Borg v0.2.0 h1:iCyDhY4WTXi39+FexRwXbn2YpZ2U9FUXVXDZk9xRCXQ=
|
||||
github.com/Snider/Borg v0.2.0/go.mod h1:TqlKnfRo9okioHbgrZPfWjQsztBV0Nfskz4Om1/vdMY=
|
||||
github.com/Snider/Enchantrix v0.0.2 h1:ExZQiBhfS/p/AHFTKhY80TOd+BXZjK95EzByAEgwvjs=
|
||||
github.com/Snider/Enchantrix v0.0.2/go.mod h1:CtFcLAvnDT1KcuF1JBb/DJj0KplY8jHryO06KzQ1hsQ=
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc=
|
||||
github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
|
|
@ -79,8 +88,11 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
|
|||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
<<<<<<< HEAD
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ=
|
||||
github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
|
|
@ -123,10 +135,18 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD
|
|||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ=
|
||||
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8=
|
||||
github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
|
|
@ -182,6 +202,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
|
||||
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/modelcontextprotocol/go-sdk v1.2.0 h1:Y23co09300CEk8iZ/tMxIX1dVmKZkzoSBZOpJwUnc/s=
|
||||
github.com/modelcontextprotocol/go-sdk v1.2.0/go.mod h1:6fM3LCm3yV7pAs8isnKLn07oKtB0MP9LHd3DfAcKw10=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
|
|
@ -225,6 +247,8 @@ github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDc
|
|||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
||||
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||
github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA=
|
||||
github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
|
|
@ -303,7 +327,11 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
<<<<<<< HEAD
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
=======
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
|
|
@ -313,10 +341,15 @@ golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHi
|
|||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
|
|
@ -340,6 +373,10 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
|||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
|
|
@ -347,8 +384,10 @@ golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
|||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||
|
|
|
|||
|
|
@ -15,7 +15,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/host-uk/core/pkg/cli"
|
||||
<<<<<<< HEAD
|
||||
errors "github.com/host-uk/core/pkg/framework/core"
|
||||
=======
|
||||
core "github.com/host-uk/core/pkg/framework/core"
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"github.com/host-uk/core/pkg/git"
|
||||
"github.com/host-uk/core/pkg/i18n"
|
||||
"github.com/host-uk/core/pkg/io"
|
||||
|
|
@ -66,19 +70,19 @@ func runApply() error {
|
|||
|
||||
// Validate inputs
|
||||
if applyCommand == "" && applyScript == "" {
|
||||
return errors.E("dev.apply", i18n.T("cmd.dev.apply.error.no_command"), nil)
|
||||
return core.E("dev.apply", i18n.T("cmd.dev.apply.error.no_command"), nil)
|
||||
}
|
||||
if applyCommand != "" && applyScript != "" {
|
||||
return errors.E("dev.apply", i18n.T("cmd.dev.apply.error.both_command_script"), nil)
|
||||
return core.E("dev.apply", i18n.T("cmd.dev.apply.error.both_command_script"), nil)
|
||||
}
|
||||
if applyCommit && applyMessage == "" {
|
||||
return errors.E("dev.apply", i18n.T("cmd.dev.apply.error.commit_needs_message"), nil)
|
||||
return core.E("dev.apply", i18n.T("cmd.dev.apply.error.commit_needs_message"), nil)
|
||||
}
|
||||
|
||||
// Validate script exists
|
||||
if applyScript != "" {
|
||||
if !io.Local.IsFile(applyScript) {
|
||||
return errors.E("dev.apply", "script not found: "+applyScript, nil) // Error mismatch? IsFile returns bool
|
||||
return core.E("dev.apply", "script not found: "+applyScript, nil) // Error mismatch? IsFile returns bool
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +93,7 @@ func runApply() error {
|
|||
}
|
||||
|
||||
if len(targetRepos) == 0 {
|
||||
return errors.E("dev.apply", i18n.T("cmd.dev.apply.error.no_repos"), nil)
|
||||
return core.E("dev.apply", i18n.T("cmd.dev.apply.error.no_repos"), nil)
|
||||
}
|
||||
|
||||
// Show plan
|
||||
|
|
@ -227,12 +231,12 @@ func getApplyTargetRepos() ([]*repos.Repo, error) {
|
|||
// Load registry
|
||||
registryPath, err := repos.FindRegistry(io.Local)
|
||||
if err != nil {
|
||||
return nil, errors.E("dev.apply", "failed to find registry", err)
|
||||
return nil, core.E("dev.apply", "failed to find registry", err)
|
||||
}
|
||||
|
||||
registry, err := repos.LoadRegistry(io.Local, registryPath)
|
||||
if err != nil {
|
||||
return nil, errors.E("dev.apply", "failed to load registry", err)
|
||||
return nil, core.E("dev.apply", "failed to load registry", err)
|
||||
}
|
||||
|
||||
// If --repos specified, filter to those
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package dev
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
|
|
@ -17,25 +16,6 @@ import (
|
|||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// syncInternalToPublic handles the synchronization of internal packages to public-facing directories.
|
||||
// This function is a placeholder for future implementation.
|
||||
func syncInternalToPublic(ctx context.Context, publicDir string) error {
|
||||
// 1. Clean public/internal
|
||||
// 2. Copy relevant files from internal/ to public/internal/
|
||||
// Usually just shared logic, not private stuff.
|
||||
|
||||
// For now, let's assume we copy specific safe packages
|
||||
// Logic to be refined.
|
||||
|
||||
// Example migration of os calls:
|
||||
// internalDirs, err := os.ReadDir(pkgDir) -> coreio.Local.List(pkgDir)
|
||||
// os.Stat -> coreio.Local.IsFile (returns bool) or List for existence check
|
||||
// os.MkdirAll -> coreio.Local.EnsureDir
|
||||
// os.WriteFile -> coreio.Local.Write
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addSyncCommand adds the 'sync' command to the given parent command.
|
||||
func addSyncCommand(parent *cli.Command) {
|
||||
syncCmd := &cli.Command{
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ func (s *Service) runWork(task TaskWork) error {
|
|||
cli.Print(" %s: %d commits\n", st.Name, st.Ahead)
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
if !task.AutoPush {
|
||||
cli.Blank()
|
||||
cli.Print("Push all? [y/N] ")
|
||||
|
|
@ -183,6 +184,15 @@ func (s *Service) runWork(task TaskWork) error {
|
|||
cli.Println("Aborted")
|
||||
return nil
|
||||
}
|
||||
=======
|
||||
cli.Blank()
|
||||
cli.Print("Push all? [y/N] ")
|
||||
var answer string
|
||||
_, _ = cli.Scanln(&answer)
|
||||
if strings.ToLower(answer) != "y" {
|
||||
cli.Println("Aborted")
|
||||
return nil
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
cli.Blank()
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ func scanRepoDocs(repo *repos.Repo) RepoDocInfo {
|
|||
docsDir := filepath.Join(repo.Path, "docs")
|
||||
// Check if directory exists by listing it
|
||||
if _, err := io.Local.List(docsDir); err == nil {
|
||||
filepath.WalkDir(docsDir, func(path string, d fs.DirEntry, err error) error {
|
||||
_ = filepath.WalkDir(docsDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -212,6 +212,7 @@ func addGoCovCommand(parent *cli.Command) {
|
|||
}
|
||||
covPath := covFile.Name()
|
||||
_ = covFile.Close()
|
||||
<<<<<<< HEAD
|
||||
defer func() {
|
||||
if covOutput == "" {
|
||||
_ = os.Remove(covPath)
|
||||
|
|
@ -227,6 +228,9 @@ func addGoCovCommand(parent *cli.Command) {
|
|||
_ = os.Remove(covPath)
|
||||
}
|
||||
}()
|
||||
=======
|
||||
defer func() { _ = os.Remove(covPath) }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
cli.Print("%s %s\n", dimStyle.Render(i18n.Label("coverage")), i18n.ProgressSubject("run", "tests"))
|
||||
// Truncate package list if too long for display
|
||||
|
|
@ -269,7 +273,11 @@ func addGoCovCommand(parent *cli.Command) {
|
|||
parts := strings.Fields(lastLine)
|
||||
if len(parts) >= 3 {
|
||||
covStr := strings.TrimSuffix(parts[len(parts)-1], "%")
|
||||
<<<<<<< HEAD
|
||||
_, _ = fmt.Sscanf(covStr, "%f", &statementCov)
|
||||
=======
|
||||
_, _ = fmt.Sscanf(covStr, "%f", &totalCov)
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,11 @@ func (r *QARunner) buildSpec(check string) *process.RunSpec {
|
|||
phpunitBin := filepath.Join(r.dir, "vendor", "bin", "phpunit")
|
||||
|
||||
var cmd string
|
||||
<<<<<<< HEAD
|
||||
if m.IsFile(pestBin) {
|
||||
=======
|
||||
if _, err := os.Stat(pestBin); err == nil {
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
cmd = pestBin
|
||||
} else if m.IsFile(phpunitBin) {
|
||||
cmd = phpunitBin
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ func needsRedis(dir string) bool {
|
|||
if err != nil {
|
||||
return false
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
defer func() { _ = file.Close() }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
|
|
@ -238,6 +242,10 @@ func GetLaravelAppName(dir string) string {
|
|||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
defer func() { _ = file.Close() }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
|
|
@ -261,6 +269,10 @@ func GetLaravelAppURL(dir string) string {
|
|||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
defer func() { _ = file.Close() }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
lines := strings.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ import (
|
|||
// Commands via self-registration
|
||||
_ "github.com/host-uk/core/internal/cmd/ai"
|
||||
_ "github.com/host-uk/core/internal/cmd/ci"
|
||||
_ "github.com/host-uk/core/internal/cmd/collect"
|
||||
_ "github.com/host-uk/core/internal/cmd/config"
|
||||
_ "github.com/host-uk/core/internal/cmd/crypt"
|
||||
_ "github.com/host-uk/core/internal/cmd/deploy"
|
||||
_ "github.com/host-uk/core/internal/cmd/dev"
|
||||
_ "github.com/host-uk/core/internal/cmd/docs"
|
||||
|
|
@ -37,6 +40,7 @@ import (
|
|||
_ "github.com/host-uk/core/internal/cmd/monitor"
|
||||
_ "github.com/host-uk/core/internal/cmd/php"
|
||||
_ "github.com/host-uk/core/internal/cmd/pkgcmd"
|
||||
_ "github.com/host-uk/core/internal/cmd/plugin"
|
||||
_ "github.com/host-uk/core/internal/cmd/qa"
|
||||
_ "github.com/host-uk/core/internal/cmd/sdk"
|
||||
_ "github.com/host-uk/core/internal/cmd/security"
|
||||
|
|
|
|||
|
|
@ -99,6 +99,10 @@ func loadEnvFile(path string, cfg *Config) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
defer func() { _ = file.Close() }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,11 @@ func (s *MacOSSigner) Notarize(ctx context.Context, fs io.Medium, binary string)
|
|||
if output, err := zipCmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("codesign.Notarize: failed to create zip: %w\nOutput: %s", err, string(output))
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
defer func() { _ = fs.Delete(zipPath) }()
|
||||
=======
|
||||
defer func() { _ = os.Remove(zipPath) }()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
// Submit to Apple and wait
|
||||
submitCmd := exec.CommandContext(ctx, "xcrun", "notarytool", "submit",
|
||||
|
|
|
|||
|
|
@ -13,11 +13,15 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
<<<<<<< HEAD
|
||||
"path/filepath"
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
core "github.com/host-uk/core/pkg/framework/core"
|
||||
<<<<<<< HEAD
|
||||
coreio "github.com/host-uk/core/pkg/io"
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
|
@ -30,13 +34,29 @@ type Config struct {
|
|||
v *viper.Viper
|
||||
medium coreio.Medium
|
||||
path string
|
||||
=======
|
||||
"github.com/host-uk/core/pkg/io"
|
||||
)
|
||||
|
||||
// Config implements the core.Config interface with layered resolution.
|
||||
// Values are resolved in order: defaults -> file -> env -> flags.
|
||||
type Config struct {
|
||||
mu sync.RWMutex
|
||||
medium io.Medium
|
||||
path string
|
||||
data map[string]any
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
// Option is a functional option for configuring a Config instance.
|
||||
type Option func(*Config)
|
||||
|
||||
// WithMedium sets the storage medium for configuration file operations.
|
||||
<<<<<<< HEAD
|
||||
func WithMedium(m coreio.Medium) Option {
|
||||
=======
|
||||
func WithMedium(m io.Medium) Option {
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
return func(c *Config) {
|
||||
c.medium = m
|
||||
}
|
||||
|
|
@ -49,6 +69,7 @@ func WithPath(path string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// WithEnvPrefix sets the prefix for environment variables.
|
||||
func WithEnvPrefix(prefix string) Option {
|
||||
return func(c *Config) {
|
||||
|
|
@ -56,11 +77,14 @@ func WithEnvPrefix(prefix string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
// New creates a new Config instance with the given options.
|
||||
// If no medium is provided, it defaults to io.Local.
|
||||
// If no path is provided, it defaults to ~/.core/config.yaml.
|
||||
func New(opts ...Option) (*Config, error) {
|
||||
c := &Config{
|
||||
<<<<<<< HEAD
|
||||
v: viper.New(),
|
||||
}
|
||||
|
||||
|
|
@ -68,12 +92,21 @@ func New(opts ...Option) (*Config, error) {
|
|||
c.v.SetEnvPrefix("CORE_CONFIG")
|
||||
c.v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
|
||||
=======
|
||||
data: make(map[string]any),
|
||||
}
|
||||
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
|
||||
if c.medium == nil {
|
||||
<<<<<<< HEAD
|
||||
c.medium = coreio.Local
|
||||
=======
|
||||
c.medium = io.Local
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
if c.path == "" {
|
||||
|
|
@ -81,6 +114,7 @@ func New(opts ...Option) (*Config, error) {
|
|||
if err != nil {
|
||||
return nil, core.E("config.New", "failed to determine home directory", err)
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
c.path = filepath.Join(home, ".core", "config.yaml")
|
||||
}
|
||||
|
||||
|
|
@ -91,11 +125,30 @@ func New(opts ...Option) (*Config, error) {
|
|||
if err := c.LoadFile(c.medium, c.path); err != nil {
|
||||
return nil, core.E("config.New", "failed to load config file", err)
|
||||
}
|
||||
=======
|
||||
c.path = home + "/.core/config.yaml"
|
||||
}
|
||||
|
||||
// Load existing config file if it exists
|
||||
if c.medium.IsFile(c.path) {
|
||||
loaded, err := Load(c.medium, c.path)
|
||||
if err != nil {
|
||||
return nil, core.E("config.New", "failed to load config file", err)
|
||||
}
|
||||
c.data = loaded
|
||||
}
|
||||
|
||||
// Overlay environment variables
|
||||
envData := LoadEnv("CORE_CONFIG_")
|
||||
for k, v := range envData {
|
||||
setNested(c.data, k, v)
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// LoadFile reads a configuration file from the given medium and path and merges it into the current config.
|
||||
// It supports YAML and environment files (.env).
|
||||
func (c *Config) LoadFile(m coreio.Medium, path string) error {
|
||||
|
|
@ -126,10 +179,16 @@ func (c *Config) LoadFile(m coreio.Medium, path string) error {
|
|||
// Get retrieves a configuration value by dot-notation key and stores it in out.
|
||||
// If key is empty, it unmarshals the entire configuration into out.
|
||||
// The out parameter must be a pointer to the target type.
|
||||
=======
|
||||
// Get retrieves a configuration value by dot-notation key and stores it in out.
|
||||
// The out parameter must be a pointer to the target type.
|
||||
// Returns an error if the key is not found.
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
func (c *Config) Get(key string, out any) error {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
<<<<<<< HEAD
|
||||
if key == "" {
|
||||
return c.v.Unmarshal(out)
|
||||
}
|
||||
|
|
@ -139,6 +198,14 @@ func (c *Config) Get(key string, out any) error {
|
|||
}
|
||||
|
||||
return c.v.UnmarshalKey(key, out)
|
||||
=======
|
||||
val, ok := getNested(c.data, key)
|
||||
if !ok {
|
||||
return core.E("config.Get", fmt.Sprintf("key not found: %s", key), nil)
|
||||
}
|
||||
|
||||
return assign(val, out)
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
// Set stores a configuration value by dot-notation key and persists to disk.
|
||||
|
|
@ -146,10 +213,16 @@ func (c *Config) Set(key string, v any) error {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
<<<<<<< HEAD
|
||||
c.v.Set(key, v)
|
||||
|
||||
// Persist to disk
|
||||
if err := Save(c.medium, c.path, c.v.AllSettings()); err != nil {
|
||||
=======
|
||||
setNested(c.data, key, v)
|
||||
|
||||
if err := Save(c.medium, c.path, c.data); err != nil {
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
return core.E("config.Set", "failed to save config", err)
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +234,29 @@ func (c *Config) All() map[string]any {
|
|||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
<<<<<<< HEAD
|
||||
return c.v.AllSettings()
|
||||
=======
|
||||
return deepCopyMap(c.data)
|
||||
}
|
||||
|
||||
// deepCopyMap recursively copies a map[string]any.
|
||||
func deepCopyMap(src map[string]any) map[string]any {
|
||||
result := make(map[string]any, len(src))
|
||||
for k, v := range src {
|
||||
switch val := v.(type) {
|
||||
case map[string]any:
|
||||
result[k] = deepCopyMap(val)
|
||||
case []any:
|
||||
cp := make([]any, len(val))
|
||||
copy(cp, val)
|
||||
result[k] = cp
|
||||
default:
|
||||
result[k] = v
|
||||
}
|
||||
}
|
||||
return result
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
// Path returns the path to the configuration file.
|
||||
|
|
@ -169,6 +264,7 @@ func (c *Config) Path() string {
|
|||
return c.path
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// Load reads a YAML configuration file from the given medium and path.
|
||||
// Returns the parsed data as a map, or an error if the file cannot be read or parsed.
|
||||
// Deprecated: Use Config.LoadFile instead.
|
||||
|
|
@ -204,6 +300,107 @@ func Save(m coreio.Medium, path string, data map[string]any) error {
|
|||
return core.E("config.Save", "failed to write config file: "+path, err)
|
||||
}
|
||||
|
||||
=======
|
||||
// getNested retrieves a value from a nested map using dot-notation keys.
|
||||
func getNested(data map[string]any, key string) (any, bool) {
|
||||
parts := strings.Split(key, ".")
|
||||
current := any(data)
|
||||
|
||||
for i, part := range parts {
|
||||
m, ok := current.(map[string]any)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
val, exists := m[part]
|
||||
if !exists {
|
||||
return nil, false
|
||||
}
|
||||
if i == len(parts)-1 {
|
||||
return val, true
|
||||
}
|
||||
current = val
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// setNested sets a value in a nested map using dot-notation keys,
|
||||
// creating intermediate maps as needed.
|
||||
func setNested(data map[string]any, key string, value any) {
|
||||
parts := strings.Split(key, ".")
|
||||
current := data
|
||||
|
||||
for i, part := range parts {
|
||||
if i == len(parts)-1 {
|
||||
current[part] = value
|
||||
return
|
||||
}
|
||||
next, ok := current[part]
|
||||
if !ok {
|
||||
next = make(map[string]any)
|
||||
current[part] = next
|
||||
}
|
||||
m, ok := next.(map[string]any)
|
||||
if !ok {
|
||||
m = make(map[string]any)
|
||||
current[part] = m
|
||||
}
|
||||
current = m
|
||||
}
|
||||
}
|
||||
|
||||
// assign sets the value of out to val, handling type conversions.
|
||||
func assign(val any, out any) error {
|
||||
switch ptr := out.(type) {
|
||||
case *string:
|
||||
switch v := val.(type) {
|
||||
case string:
|
||||
*ptr = v
|
||||
default:
|
||||
*ptr = fmt.Sprintf("%v", v)
|
||||
}
|
||||
case *int:
|
||||
switch v := val.(type) {
|
||||
case int:
|
||||
*ptr = v
|
||||
case float64:
|
||||
*ptr = int(v)
|
||||
case int64:
|
||||
*ptr = int(v)
|
||||
default:
|
||||
return core.E("config.assign", fmt.Sprintf("cannot assign %T to *int", val), nil)
|
||||
}
|
||||
case *bool:
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
*ptr = v
|
||||
default:
|
||||
return core.E("config.assign", fmt.Sprintf("cannot assign %T to *bool", val), nil)
|
||||
}
|
||||
case *float64:
|
||||
switch v := val.(type) {
|
||||
case float64:
|
||||
*ptr = v
|
||||
case int:
|
||||
*ptr = float64(v)
|
||||
case int64:
|
||||
*ptr = float64(v)
|
||||
default:
|
||||
return core.E("config.assign", fmt.Sprintf("cannot assign %T to *float64", val), nil)
|
||||
}
|
||||
case *any:
|
||||
*ptr = val
|
||||
case *map[string]any:
|
||||
switch v := val.(type) {
|
||||
case map[string]any:
|
||||
*ptr = v
|
||||
default:
|
||||
return core.E("config.assign", fmt.Sprintf("cannot assign %T to *map[string]any", val), nil)
|
||||
}
|
||||
default:
|
||||
return core.E("config.assign", fmt.Sprintf("unsupported target type: %T", out), nil)
|
||||
}
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ func TestSave_Good(t *testing.T) {
|
|||
assert.NoError(t, readErr)
|
||||
assert.Contains(t, content, "key: value")
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
func TestConfig_LoadFile_Env(t *testing.T) {
|
||||
m := io.NewMockMedium()
|
||||
|
|
@ -275,3 +276,5 @@ func TestConfig_Get_EmptyKey(t *testing.T) {
|
|||
assert.Equal(t, "test", full.App.Name)
|
||||
assert.Equal(t, 1, full.Version)
|
||||
}
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
|
|
|||
45
pkg/config/loader.go
Normal file
45
pkg/config/loader.go
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
core "github.com/host-uk/core/pkg/framework/core"
|
||||
"github.com/host-uk/core/pkg/io"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Load reads a YAML configuration file from the given medium and path.
|
||||
// Returns the parsed data as a map, or an error if the file cannot be read or parsed.
|
||||
func Load(m io.Medium, path string) (map[string]any, error) {
|
||||
content, err := m.Read(path)
|
||||
if err != nil {
|
||||
return nil, core.E("config.Load", "failed to read config file: "+path, err)
|
||||
}
|
||||
|
||||
data := make(map[string]any)
|
||||
if err := yaml.Unmarshal([]byte(content), &data); err != nil {
|
||||
return nil, core.E("config.Load", "failed to parse config file: "+path, err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Save writes configuration data to a YAML file at the given path.
|
||||
// It ensures the parent directory exists before writing.
|
||||
func Save(m io.Medium, path string, data map[string]any) error {
|
||||
out, err := yaml.Marshal(data)
|
||||
if err != nil {
|
||||
return core.E("config.Save", "failed to marshal config", err)
|
||||
}
|
||||
|
||||
dir := filepath.Dir(path)
|
||||
if err := m.EnsureDir(dir); err != nil {
|
||||
return core.E("config.Save", "failed to create config directory: "+dir, err)
|
||||
}
|
||||
|
||||
if err := m.Write(path, string(out)); err != nil {
|
||||
return core.E("config.Save", "failed to write config file: "+path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -67,6 +67,7 @@ func (s *Service) Set(key string, v any) error {
|
|||
return s.config.Set(key, v)
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// LoadFile merges a configuration file into the central configuration.
|
||||
func (s *Service) LoadFile(m io.Medium, path string) error {
|
||||
if s.config == nil {
|
||||
|
|
@ -75,6 +76,8 @@ func (s *Service) LoadFile(m io.Medium, path string) error {
|
|||
return s.config.LoadFile(m, path)
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
// Ensure Service implements core.Config and Startable at compile time.
|
||||
var (
|
||||
_ core.Config = (*Service)(nil)
|
||||
|
|
|
|||
|
|
@ -436,7 +436,11 @@ func (m *LinuxKitManager) Exec(ctx context.Context, id string, cmd []string) err
|
|||
// Build SSH command
|
||||
sshArgs := []string{
|
||||
"-p", fmt.Sprintf("%d", sshPort),
|
||||
<<<<<<< HEAD
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
=======
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"-o", "UserKnownHostsFile=~/.core/known_hosts",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"root@localhost",
|
||||
|
|
|
|||
|
|
@ -216,7 +216,11 @@ func TestLinuxKitManager_Stop_Bad_NotRunning(t *testing.T) {
|
|||
statePath := filepath.Join(tmpDir, "containers.json")
|
||||
state, err := LoadState(io.Local, statePath)
|
||||
require.NoError(t, err)
|
||||
<<<<<<< HEAD
|
||||
manager := NewLinuxKitManagerWithHypervisor(io.Local, state, NewMockHypervisor())
|
||||
=======
|
||||
manager := NewLinuxKitManagerWithHypervisor(state, NewMockHypervisor())
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
container := &Container{
|
||||
ID: "abc12345",
|
||||
|
|
@ -236,7 +240,11 @@ func TestLinuxKitManager_List_Good(t *testing.T) {
|
|||
statePath := filepath.Join(tmpDir, "containers.json")
|
||||
state, err := LoadState(io.Local, statePath)
|
||||
require.NoError(t, err)
|
||||
<<<<<<< HEAD
|
||||
manager := NewLinuxKitManagerWithHypervisor(io.Local, state, NewMockHypervisor())
|
||||
=======
|
||||
manager := NewLinuxKitManagerWithHypervisor(state, NewMockHypervisor())
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
_ = state.Add(&Container{ID: "aaa11111", Status: StatusStopped})
|
||||
_ = state.Add(&Container{ID: "bbb22222", Status: StatusStopped})
|
||||
|
|
@ -253,7 +261,11 @@ func TestLinuxKitManager_List_Good_VerifiesRunningStatus(t *testing.T) {
|
|||
statePath := filepath.Join(tmpDir, "containers.json")
|
||||
state, err := LoadState(io.Local, statePath)
|
||||
require.NoError(t, err)
|
||||
<<<<<<< HEAD
|
||||
manager := NewLinuxKitManagerWithHypervisor(io.Local, state, NewMockHypervisor())
|
||||
=======
|
||||
manager := NewLinuxKitManagerWithHypervisor(state, NewMockHypervisor())
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
// Add a "running" container with a fake PID that doesn't exist
|
||||
_ = state.Add(&Container{
|
||||
|
|
|
|||
|
|
@ -414,8 +414,19 @@ kernel:
|
|||
err = os.WriteFile(filepath.Join(coreDir, "user-custom.yml"), []byte(templateContent), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
<<<<<<< HEAD
|
||||
tm := NewTemplateManager(io.Local).WithWorkingDir(tmpDir)
|
||||
templates := tm.ListTemplates()
|
||||
=======
|
||||
// Change to the temp directory
|
||||
oldWd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
err = os.Chdir(tmpDir)
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = os.Chdir(oldWd) }()
|
||||
|
||||
templates := ListTemplates()
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
// Should have at least the builtin templates plus the user template
|
||||
assert.GreaterOrEqual(t, len(templates), 3)
|
||||
|
|
@ -449,8 +460,19 @@ services:
|
|||
err = os.WriteFile(filepath.Join(coreDir, "my-user-template.yml"), []byte(templateContent), 0644)
|
||||
require.NoError(t, err)
|
||||
|
||||
<<<<<<< HEAD
|
||||
tm := NewTemplateManager(io.Local).WithWorkingDir(tmpDir)
|
||||
content, err := tm.GetTemplate("my-user-template")
|
||||
=======
|
||||
// Change to the temp directory
|
||||
oldWd, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
err = os.Chdir(tmpDir)
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = os.Chdir(oldWd) }()
|
||||
|
||||
content, err := GetTemplate("my-user-template")
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, content, "kernel:")
|
||||
|
|
@ -583,7 +605,21 @@ func TestGetUserTemplatesDir_Good_NoDirectory(t *testing.T) {
|
|||
tm := NewTemplateManager(io.Local).WithWorkingDir("/tmp/nonexistent-wd").WithHomeDir("/tmp/nonexistent-home")
|
||||
dir := tm.getUserTemplatesDir()
|
||||
|
||||
<<<<<<< HEAD
|
||||
assert.Empty(t, dir)
|
||||
=======
|
||||
// Create a temp directory without .core/linuxkit
|
||||
tmpDir := t.TempDir()
|
||||
err = os.Chdir(tmpDir)
|
||||
require.NoError(t, err)
|
||||
defer func() { _ = os.Chdir(oldWd) }()
|
||||
|
||||
dir := getUserTemplatesDir()
|
||||
|
||||
// Should return empty string since no templates dir exists
|
||||
// (unless home dir has one)
|
||||
assert.True(t, dir == "" || strings.Contains(dir, "linuxkit"))
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
func TestScanUserTemplates_Good_DefaultDescription(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,11 @@ func (d *DevOps) Claude(ctx context.Context, projectDir string, opts ClaudeOptio
|
|||
|
||||
// Build SSH command with agent forwarding
|
||||
args := []string{
|
||||
<<<<<<< HEAD
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
=======
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"-o", "UserKnownHostsFile=~/.core/known_hosts",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-A", // SSH agent forwarding
|
||||
|
|
@ -132,7 +136,11 @@ func (d *DevOps) CopyGHAuth(ctx context.Context) error {
|
|||
|
||||
// Use scp to copy gh config
|
||||
cmd := exec.CommandContext(ctx, "scp",
|
||||
<<<<<<< HEAD
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
=======
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"-o", "UserKnownHostsFile=~/.core/known_hosts",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-P", fmt.Sprintf("%d", DefaultSSHPort),
|
||||
|
|
|
|||
|
|
@ -59,7 +59,11 @@ func (d *DevOps) mountProject(ctx context.Context, path string) error {
|
|||
// Use reverse SSHFS mount
|
||||
// The VM connects back to host to mount the directory
|
||||
cmd := exec.CommandContext(ctx, "ssh",
|
||||
<<<<<<< HEAD
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
=======
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"-o", "UserKnownHostsFile=~/.core/known_hosts",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-R", "10000:localhost:22", // Reverse tunnel for SSHFS
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ func (d *DevOps) Shell(ctx context.Context, opts ShellOptions) error {
|
|||
// sshShell connects via SSH.
|
||||
func (d *DevOps) sshShell(ctx context.Context, command []string) error {
|
||||
args := []string{
|
||||
<<<<<<< HEAD
|
||||
"-o", "StrictHostKeyChecking=yes",
|
||||
=======
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
"-o", "UserKnownHostsFile=~/.core/known_hosts",
|
||||
"-o", "LogLevel=ERROR",
|
||||
"-A", // Agent forwarding
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ func TestFeatures_IsEnabled_Good(t *testing.T) {
|
|||
assert.False(t, c.Features.IsEnabled(""))
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
func TestFeatures_IsEnabled_Edge(t *testing.T) {
|
||||
c, _ := New()
|
||||
c.Features.Flags = []string{" ", "foo"}
|
||||
|
|
@ -139,6 +140,8 @@ func TestFeatures_IsEnabled_Edge(t *testing.T) {
|
|||
assert.False(t, c.Features.IsEnabled("FOO")) // Case sensitive check
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
func TestCore_ServiceLifecycle_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ func (m *Medium) path(p string) string {
|
|||
if p == "" {
|
||||
return m.root
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
// If the path is relative and the medium is rooted at "/",
|
||||
// treat it as relative to the current working directory.
|
||||
|
|
@ -40,6 +41,23 @@ func (m *Medium) path(p string) string {
|
|||
if m.root == "/" && !filepath.IsAbs(p) {
|
||||
cwd, _ := os.Getwd()
|
||||
return filepath.Join(cwd, p)
|
||||
=======
|
||||
clean := strings.ReplaceAll(p, "..", ".")
|
||||
if filepath.IsAbs(clean) {
|
||||
// If root is "/", allow absolute paths through
|
||||
if m.root == "/" {
|
||||
return filepath.Clean(clean)
|
||||
}
|
||||
// Otherwise, sandbox absolute paths by stripping volume + leading separators
|
||||
vol := filepath.VolumeName(clean)
|
||||
clean = strings.TrimPrefix(clean, vol)
|
||||
cutset := string(os.PathSeparator)
|
||||
if os.PathSeparator != '/' {
|
||||
cutset += "/"
|
||||
}
|
||||
clean = strings.TrimLeft(clean, cutset)
|
||||
return filepath.Join(m.root, clean)
|
||||
>>>>>>> fix/consolidate-workflows
|
||||
}
|
||||
|
||||
// Use filepath.Clean with a leading slash to resolve all .. and . internally
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ func (s *Service) ServeTCP(ctx context.Context, addr string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer t.listener.Close()
|
||||
defer func() { _ = t.listener.Close() }()
|
||||
|
||||
// Close listener when context is cancelled to unblock Accept
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
t.listener.Close()
|
||||
_ = t.listener.Close()
|
||||
}()
|
||||
|
||||
if addr == "" {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue