1"use strict";(self.webpackChunkdocusaurus_website=self.webpackChunkdocusaurus_website||[]).push([[6702],{8561:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var i=s(85893),o=s(11151);const t={id:"repo",title:"Repository",sidebar_position:8},r=void 0,l={id:"plugins/development/repo",title:"Repository",description:"A plugin repository is a place where you store your plugin binaries. This repository must be publicly available and supports downloading assets via HTTP(s). This document explains how to create Botkube plugin repositories by providing examples based on GitHub functionality. However, any static file server can be used, for instance: s3, gcs, etc.",source:"@site/docs/plugins/development/repository.md",sourceDirName:"plugins/development",slug:"/plugins/development/repo",permalink:"/next/plugins/development/repo",draft:!1,unlisted:!1,editUrl:"https://github.com/kubeshop/botkube-docs/edit/main/docs/plugins/development/repository.md",tags:[],version:"current",sidebarPosition:8,frontMatter:{id:"repo",title:"Repository",sidebar_position:8},sidebar:"docsSidebar",previous:{title:"Local testing",permalink:"/next/plugins/development/local-testing"},next:{title:"Troubleshooting",permalink:"/next/plugins/development/troubleshooting"}},a={},c=[{value:"Index file",id:"index-file",level:2},{value:"Generate index file",id:"generate-index-file",level:3},{value:"Host plugins",id:"host-plugins",level:2},{value:"GitHub releases",id:"github-releases",level:3},{value:"Automation",id:"automation",level:4},{value:"GitHub pages",id:"github-pages",level:3},{value:"Automation",id:"automation-1",level:4},{value:"Use hosted plugins",id:"use-hosted-plugins",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(n.p,{children:["A plugin repository is a place where you store your plugin binaries. This repository must be publicly available and supports downloading assets via HTTP(s). This document explains how to create Botkube plugin repositories by providing examples based on GitHub functionality. However, any static file server can be used, for instance: ",(0,i.jsx)(n.code,{children:"s3"}),", ",(0,i.jsx)(n.code,{children:"gcs"}),", etc."]}),"\n",(0,i.jsxs)(n.p,{children:["This document describes how to set up such repository. If you use or plan to use GitHub you can adapt the ",(0,i.jsx)(n.a,{href:"/next/plugins/development/quick-start",children:"template repository"})," that has batteries included to start developing and hosting Botkube plugins right away."]}),"\n",(0,i.jsx)(n.h2,{id:"index-file",children:"Index file"}),"\n",(0,i.jsx)(n.p,{children:"Your plugin repository must contain at least one index file and one plugin binary. Depending on your needs and preferences, you can create one or more index files to categorize your plugins. You can host both the executor and source plugins in a single repository. You can also include them in the same index file."}),"\n",(0,i.jsx)(n.p,{children:"In the index file, provide an entry for every plugin from your plugin repository. The index file must have the following syntax:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"entries:\n - name: { plugin_name }\n type: { plugin_type } # executor or source\n description: { plugin_description }\n version: { plugin_version }\n urls:\n - url: { url_to_plugin_binary }\n platform:\n os: { plugin_operating_system } # darwin or linux\n architecture: { plugin_architecture } # amd64 or arm64\n dependencies: # optional dependencies\n { dependency_name }:\n url: { url_to_dependency_binary }\n"})}),"\n",(0,i.jsx)(n.p,{children:"It is not required to host a plugin or dependency binary on the same server as the index file."}),"\n",(0,i.jsx)(n.h3,{id:"generate-index-file",children:"Generate index file"}),"\n",(0,i.jsx)(n.p,{children:"You can create the index file by yourself our use our tool to generate it automatically based on the directory with plugins binaries. The binaries must be named according to the following pattern:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["For executors, ",(0,i.jsx)(n.code,{children:"executor_{plugin_name}_{os}_{arch}"}),"; for example, ",(0,i.jsx)(n.code,{children:"executor_kubectl_darwin_amd64"}),"."]}),"\n",(0,i.jsxs)(n.li,{children:["For sources, ",(0,i.jsx)(n.code,{children:"source_{plugin_name}_{os}_{arch}"}),"; for example, ",(0,i.jsx)(n.code,{children:"source_kubernetes_darwin_amd64"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Steps"})}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["In your plugin repository, add ",(0,i.jsx)(n.code,{children:"tools.go"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-go",children:'cat << EOF > tools.go\n//go:build tools\n\npackage tools\n\nimport (\n\t _ "github.com/kubeshop/botkube/hack"\n)\nEOF\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"note",children:(0,i.jsxs)(n.p,{children:["We use the ",(0,i.jsx)(n.code,{children:"tools.go"})," file, which is the ",(0,i.jsx)(n.a,{href:"https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module",children:"recommended way of tracking tool dependencies"}),"."]})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Refresh dependencies:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"go mod tidy\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Build all your plugins. See ",(0,i.jsx)(n.a,{href:"/next/plugins/development/custom-executor",children:(0,i.jsx)(n.strong,{children:"Build plugin binaries"})}),"."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Generate an index file:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'go run github.com/kubeshop/botkube/hack -binaries-path "./dist" -url-base-path "https://example.com"\n'})}),"\n",(0,i.jsx)(n.admonition,{type:"info",children:(0,i.jsxs)(n.p,{children:["Replace the ",(0,i.jsx)(n.code,{children:"-url-base-path"})," flag with the base path of your HTTP server. See ",(0,i.jsx)(n.a,{href:"#host-plugins",children:"Hosting plugins"})," for some examples."]})}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"host-plugins",children:"Host plugins"}),"\n",(0,i.jsx)(n.p,{children:"This section describes example ways for serving Botkube plugins."}),"\n",(0,i.jsx)(n.h3,{id:"github-releases",children:"GitHub releases"}),"\n",(0,i.jsxs)(n.p,{children:["A GitHub release allows you to upload additional assets that are later accessible with a predictable URL. When you generate the index file, specify the ",(0,i.jsx)(n.code,{children:"-url-base-path"})," flag as ",(0,i.jsx)(n.code,{children:"https://github.com/{owner}/{repo}/releases/download/{release_tag}"}),", for example, ",(0,i.jsx)(n.code,{children:"https://github.com/kubeshop/botkube/releases/download/v1.0.0"}),"."]}),"\n",(0,i.jsxs)(n.p,{children:["Once the plugin binaries are built and the index file is generated, you can create a GitHub release using ",(0,i.jsx)(n.a,{href:"https://cli.github.com/",children:"GitHub CLI"}),". For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"gh release create v1.0.0 \\\n ./dist/source_* \\\n ./dist/executor_* \\\n ./plugins-index.yaml\n"})}),"\n",(0,i.jsx)(n.h4,{id:"automation",children:"Automation"}),"\n",(0,i.jsxs)(n.p,{children:["You can use ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/actions",children:"GitHub Actions"})," to publish Botkube plugins automatically each time a new tag is pushed. See the ",(0,i.jsxs)(n.a,{href:"https://github.com/kubeshop/botkube-plugins-template/blob/main/.github/workflows/release.yml",children:[(0,i.jsx)(n.code,{children:"release"})," workflow"]})," on the ",(0,i.jsx)(n.code,{children:"botkube-plugins-template"})," repository for the out-of-the-box solution, which you can use and modify if needed."]}),"\n",(0,i.jsx)(n.h3,{id:"github-pages",children:"GitHub pages"}),"\n",(0,i.jsxs)(n.p,{children:["GitHub allows you to serve static pages via GitHub Pages. When you generate the index file, specify the ",(0,i.jsx)(n.code,{children:"-url-base-path"})," flag as ",(0,i.jsx)(n.code,{children:"https://{user}.github.io/{repository}"}),", for example, ",(0,i.jsx)(n.code,{children:"https://kubeshop.github.io/botkube-plugins"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Initial setup"})}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Navigate to the Git repository with your plugins."}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Create the ",(0,i.jsx)(n.code,{children:"gh-pages"})," branch:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'git switch --orphan gh-pages\ngit commit --allow-empty -m "Initialization commit"\ngit push -u origin gh-pages\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Follow ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-from-a-branch",children:"this"})," guide to make sure your ",(0,i.jsx)(n.code,{children:"gh-pages"})," branch is set as the source for GitHub Pages."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Publishing steps"})}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Clone ",(0,i.jsx)(n.code,{children:"gh-pages"})," into ",(0,i.jsx)(n.code,{children:"/tmp/botkube-plugins"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'git clone -b gh-pages "https://github.com/{owner}/{repo}.git" /tmp/botkube-plugins\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Move built binaries and generated index file:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"mv dist/executor_* /tmp/botkube-plugins/\nmv dist/source_* /tmp/botkube-plugins/\nmv plugins-index.yaml /tmp/botkube-plugins\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:"Commit and push copied files:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'cd /tmp/botkube-plugins\ngit add -A\ngit commit -m "Release Botkube plugins"\ngit push\n'})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:["Remove cloned ",(0,i.jsx)(n.code,{children:"gh-pages"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cd -\nrm -rf /tmp/botkube-charts\n"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["In such setup, you can use your default branch to store your plugins code, and the ",(0,i.jsx)(n.code,{children:"gh-pages"})," branch as a plugin repository."]}),"\n",(0,i.jsx)(n.h4,{id:"automation-1",children:"Automation"}),"\n",(0,i.jsxs)(n.p,{children:["You can use ",(0,i.jsx)(n.a,{href:"https://docs.github.com/en/actions",children:"GitHub Actions"})," to publish Botkube plugins automatically each time a new tag is pushed. See the ",(0,i.jsxs)(n.a,{href:"https://github.com/kubeshop/botkube-plugins-template/blob/main/.github/workflows/pages-release.yml",children:[(0,i.jsx)(n.code,{children:"pages-release"})," workflow"]})," on the ",(0,i.jsx)(n.code,{children:"botkube-plugins-template"})," repository for the out-of-the-box solution, which you can use and modify if needed."]}),"\n",(0,i.jsx)(n.h3,{id:"use-hosted-plugins",children:"Use hosted plugins"}),"\n",(0,i.jsxs)(n.p,{children:["To use the plugins that you published, add your repository under ",(0,i.jsx)(n.code,{children:"plugins"})," in the ",(0,i.jsx)(n.a,{href:"https://github.com/kubeshop/botkube/blob/main/helm/botkube/values.yaml",children:"values.yaml"})," file for a given Botkube deployment. For example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"plugins:\n repositories:\n repo-name:\n url: https://example.com/plugins-index.yaml\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Once the plugin repository is added, you can refer to it in the ",(0,i.jsx)(n.code,{children:"executor"})," or ",(0,i.jsx)(n.code,{children:"sources"})," section."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'executors:\n "plugins":\n repo-name/[email protected]: # Plugin name syntax: {repo}/{plugin}[@{version}]. If version is not provided, the latest version from repository is used.\n enabled: true\n config: {} # Plugin\'s specific configuration.\nsources:\n "plugins":\n repo-name/[email protected]: # Plugin name syntax: {repo}/{plugin}[@{version}]. If version is not provided, the latest version from repository is used.\n enabled: true\n config: {} # Plugin\'s specific configuration.\n'})})]})}function u(e={}){const{wrapper:n}={...(0,o.a)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},11151:(e,n,s)=>{s.d(n,{Z:()=>l,a:()=>r});var i=s(67294);const o={},t=i.createContext(o);function r(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.