github.com/inspektor-gadget/inspektor-gadget@v0.28.1/docs/devel/ci.md (about)

     1  ---
     2  title: Continuous Integration
     3  weight: 210
     4  description: >
     5    Inspektor Gadget continuous integration workflow
     6  ---
     7  
     8  This repository uses GitHub Actions to create a custom Continuous Integration
     9  (CI) workflow named `Inspektor Gadget CI`. This workflow compiles and uploads
    10  the Inspektor Gadget CLI (`kubectl-gadget` and `ig`) and gadget container
    11  images and runs their unit and integration tests. In addition, it verifies
    12  that the documentation is up-to-date and runs a static code analysis using
    13  Golang linters.
    14  
    15  A fork of this project should enable GitHub Actions in the repo settings page
    16  and add the proper
    17  [secrets](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets#creating-encrypted-secrets-for-a-repository)
    18  to be able to use this workflow. The following sections describes what
    19  secrets need to be added to enable all the CI tests.
    20  
    21  ## Container repository
    22  
    23  To run the integration tests, it is necessary to have the gadget container image
    24  available so that it can be installed/loaded in the Kubernetes cluster where the
    25  tests will run.
    26  
    27  As a default, images are shared via artifacts between workflow jobs
    28  for all CI pipeline. When the target branch correspond to the main or
    29  the push refers to a tag, the images are also pushed to
    30  `ghcr.io/${{ github.repository }}`. This permits a clear separation
    31  between "in development" images and production ones.
    32  
    33  Note that, you need to [set repository packages as public](https://docs.github.com/en/packages/learn-github-packages/configuring-a-packages-access-control-and-visibility#configuring-visibility-of-container-images-for-your-personal-account) to allow anonymous pull.
    34  
    35  ## Run integration tests on ARO
    36  
    37  Optionally, we can add the secrets described in this section so that the
    38  integration tests will also run on a pre-created [Azure Red Hat OpenShift
    39  (ARO)](https://docs.microsoft.com/en-us/azure/openshift/intro-openshift)
    40  cluster. Consider that the Inspektor Gadget workflow will still success even if
    41  no ARO cluster is provided through these secrets.
    42  
    43  ### Create a cluster
    44  
    45  These are the steps to create an ARO cluster using the [Azure
    46  CLI](https://docs.microsoft.com/en-us/cli/azure/):
    47  
    48  ```bash
    49  $ export SUBSCRIPTION=<mySubscription>
    50  $ export RESOURCEGROUP=<myResourceName>
    51  $ export LOCATION=<myLocation>
    52  $ export CLUSTER=<myCluster>
    53  $ export VNET=<myVNET>
    54  $ export MASTSUB=<myMASTSUB>
    55  $ export WORKSUB=<myWORKSUB>
    56  
    57  # Set subscription so that we don't need to specify it at every command
    58  $ az account set --subscription $SUBSCRIPTION
    59  
    60  # Register resource providers
    61  $ az provider register -n Microsoft.RedHatOpenShift --wait
    62  $ az provider register -n Microsoft.Compute --wait
    63  $ az provider register -n Microsoft.Storage --wait
    64  $ az provider register -n Microsoft.Authorization --wait
    65  
    66  # Create resource group
    67  $ az group create --name $RESOURCEGROUP --location $LOCATION
    68  
    69  # Create virtual network and two empty subnets for the master and the worker nodes.
    70  $ az network vnet create --resource-group $RESOURCEGROUP --name $VNET --address-prefixes 10.0.0.0/22
    71  $ az network vnet subnet create --resource-group $RESOURCEGROUP --vnet-name $VNET --name $MASTSUB --address-prefixes 10.0.0.0/23 --service-endpoints Microsoft.ContainerRegistry
    72  $ az network vnet subnet create --resource-group $RESOURCEGROUP --vnet-name $VNET --name $WORKSUB --address-prefixes 10.0.2.0/23 --service-endpoints Microsoft.ContainerRegistry
    73  $ az network vnet subnet update --name $MASTSUB --resource-group $RESOURCEGROUP --vnet-name $VNET --disable-private-link-service-network-policies true
    74  
    75  # Create the cluster (Minimum 3 worker nodes must be used)
    76  $ az aro create --resource-group $RESOURCEGROUP --name $CLUSTER --vnet $VNET --master-subnet $MASTSUB --worker-count 3 --worker-subnet $WORKSUB
    77  ```
    78  
    79  Considerations:
    80  - After executing the `az aro create` command, it normally takes about 35
    81    minutes to create a cluster.
    82  - For the sake of simplicity, we are not providing a [Red Hat pull
    83    secret](https://docs.microsoft.com/en-us/azure/openshift/tutorial-create-cluster#get-a-red-hat-pull-secret-optional)
    84    during the cluster creation, so our cluster will not include samples or
    85    operators from Red Hat or certified partners. However, it is not a requirement
    86    to run the Inspektor Gadget integration tests on it.
    87  - Creating an ARO cluster requires specific permissions, check [the
    88    documentation](https://docs.microsoft.com/en-us/azure/openshift/tutorial-create-cluster#verify-your-permissions)
    89    to be sure you have them.
    90  
    91  ### Delete a cluster
    92  
    93  If we need to delete our cluster, it is enough to execute:
    94  ```bash
    95  $ az group delete --name $RESOURCEGROUP
    96  ```
    97  
    98  Take into account that it will remove the entire resource group and all
    99  resources inside it.
   100  
   101  Further details about creating an ARO cluster can be found in the [Azure Red Hat
   102  OpenShift
   103  documentation](https://docs.microsoft.com/en-us/azure/openshift/tutorial-create-cluster).
   104  
   105  ### Connect to a cluster
   106  
   107  Fist of all, to be able to connect to our cluster, we need the following
   108  information:
   109  
   110  ```bash
   111  # API Server URL
   112  $ az aro show --subscription $SUBSCRIPTION -g $RESOURCEGROUP -n $CLUSTER --query apiserverProfile.url
   113  https://api.server.example.io:1234
   114  
   115  # Credentials
   116  $ az aro list-credentials --subscription $SUBSCRIPTION -g $RESOURCEGROUP -n $CLUSTER
   117  {
   118    "kubeadminPassword": "myPassword",
   119    "kubeadminUsername": "myUsername"
   120  }
   121  ```
   122  
   123  #### From GitHub actions
   124  
   125  The `test-integration` job is already configured to authenticate and set the
   126  kubeconf context to the ARO cluster configured in the GitHub repository. So all
   127  we need to do is to add the following actions secrets:
   128  
   129  - `OPENSHIFT_SERVER`: The API server URL: `https://api.server.example.io:1234`.
   130  - `OPENSHIFT_USER`: The `kubeadminUsername` from the JSON output of the
   131    `list-credentials` command.
   132  - `OPENSHIFT_PASSWORD`: The `kubeadminPassword` from the JSON output of the
   133    `list-credentials` command.
   134  
   135  Further details about connect to an ARO cluster from GitHub actions can be found
   136  in the [Azure Red Hat OpenShift
   137  documentation](https://docs.microsoft.com/en-us/azure/openshift/tutorial-connect-cluster#connect-using-the-openshift-cli)
   138  and the [redhat-actions/oc-login
   139  documentation](https://github.com/redhat-actions/oc-login).
   140  
   141  #### From a host
   142  
   143  For debugging, it might be necessary to connect to the cluster from a host. We
   144  can do it by using the `oc` tool:
   145  
   146  ```bash
   147  $ oc login $apiServer -u $kubeadminUsername -p $kubeadminPassword
   148  ```
   149  
   150  Notice that it configures the kubectl configuration with a new context.
   151  
   152  Please take into account that any change done on this cluster could cause issues
   153  with the integration tests running on GitHub actions at that moment.
   154  
   155  
   156  ## Run integration tests on AKS
   157  
   158  When secrets described in the below sections are set, the integration tests
   159  will also run on
   160  [AKS clusters](https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes).
   161  
   162  ### Create the clusters
   163  
   164  As Inspektor Gadget support both `amd64` and `arm64`, two clusters will be
   165  created when the CI is triggered.
   166  To be able to create them in the CI, you need to follow [these instructions](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure?tabs=azure-cli%2Clinux):
   167  
   168  ```bash
   169  $ subscription_id=<mySubscriptionID>
   170  $ resourcegroup=<myResourceName>
   171  $ location=<myLocation>
   172  $ app_name=<myAppName>
   173  # federated_name should not have spaces!
   174  $ federated_name=<myFederatedCredentialName>
   175  $ organization=<myGitHubOrganization>
   176  $ repository=<myGitHubRepository>
   177  $ environment=<myCIJobEnvironment>
   178  
   179  # Set subscription so that we don't need to specify it at every command.
   180  $ az account set --subscription $subscription_id
   181  
   182  # Create resource group.
   183  # This is not needed to generate secrets but it is mandatory to creates AKS
   184  # cluster in the CI.
   185  $ az group create --name $resourcegroup --location $location
   186  
   187  # Register an application for your CI.
   188  $ az ad app create --display-name $app_name
   189  {
   190  # It should reply with a big JSON object.
   191  }
   192  
   193  # Let's get the ID of the created application
   194  $ app_id=$(az ad app list --display-name $app_name --query [0].id | tr -d '"')
   195  
   196  # Let's create a service principal for the corresponding application.
   197  $ az ad sp create --id $app_id
   198  {
   199  # It should reply with a big JSON object.
   200  }
   201  
   202  # We now want to get the service principal ID.
   203  $ sp_id=$(az ad sp list --display-name $app_name --query [0].id | tr -d '"')
   204  
   205  # Let's create a new role for this service principal.
   206  $ az role assignment create --role contributor --assignee-object-id $sp_id --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscription_id/resourceGroups/$resourcegroup
   207  {
   208  # It should reply with a big JSON object.
   209  }
   210  
   211  # Create the federated credential to be able to "az login" from the CI.
   212  $ az ad app federated-credential create --id $app_id --parameters <(echo "{
   213    \"name\": \"${federated_name}\",
   214    \"issuer\": \"https://token.actions.githubusercontent.com\",
   215    \"subject\": \"repo:${organization}/${repository}:environment:${environment}\",
   216    \"description\": \"AKS federated credentials for CI\",
   217    \"audiences\": [
   218      \"api://AzureADTokenExchange\"
   219    ]
   220  }")
   221  {
   222  # It replies with a JSON object which has name set to $federated_name.
   223  }
   224  ```
   225  
   226  After doing this, you will need to create several secrets:
   227  
   228  1. `AZURE_AKS_CLIENT_ID`: The application ID as given by `az ad app list --display-name $app_name --query [0].appId`.
   229  1. `AZURE_AKS_TENANT_ID`: The tenant ID as given by `az account show --query tenantId`.
   230  1. `AZURE_AKS_SUBSCRIPTION_ID`: The subscription used to create the federated
   231  credentials as given by `az account show --query id`.
   232  1. `AZURE_AKS_RESOURCE_GROUP`: It stores the name of the resource group where
   233  the clusters will be created.
   234  
   235  The workflow will create the `amd64` and `arm64` clusters for you by using the
   236  above information.
   237  By default, each of this cluster features
   238  [3 nodes](https://learn.microsoft.com/en-us/cli/azure/aks?view=azure-cli-latest#az-aks-create).
   239  Once created, the integration tests will be run on these clusters.
   240  Finally, the clusters are deleted, whatsoever is the result of the tests.
   241  
   242  ## Run integration tests on EKS
   243  
   244  We use OpenID Connect to authenticate GitHub Actions against AWS. If you want to run the integration
   245  tests on your fork, follow
   246  [this](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
   247  to configure your AWS account.
   248  
   249  You need to create a role with the [minimum IAM
   250  policies](https://eksctl.io/usage/minimum-iam-policies/) needed by eksctl. Save the name of this
   251  role (including the rull `arn:aws..` prefix). in a [repository
   252  variable](https://docs.github.com/en/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository)
   253  named `AWS_ROLE`.
   254  
   255  ## Run integration tests on GKE
   256  
   257  In order to run the integration tests on GKE on a fork, you need to set the following secrets:
   258  
   259  - `GKE_PROJECT`: The GCP project where the GKE cluster is located.
   260  - `GKE_SERVICE_ACCOUNT`: The service account used to authenticate to GCP.
   261  - `GKE_WORKLOAD_IDENTITY_PROVIDER`: The workload identity provider used to authenticate to GCP.
   262  
   263  these secrets use OpenID Connect to authenticate GitHub Actions against GCP for more information on how it works
   264  you can check the GitHub documentation [here](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform#adding-a-google-cloud-workload-identity-provider).
   265  The steps to create a service account and a workload identity provider can be found in the [google-github-actions/auth](https://github.com/google-github-actions/auth?tab=readme-ov-file#workload-identity-federation-through-a-service-account) repository till step 6.
   266  In terms of permissions, the service account needs to have the following roles:
   267  
   268  - `roles/container.admin`
   269  - `roles/container.clusterAdmin`
   270  - `roles/iam.serviceAccountUser`
   271  
   272  You can see the guide [here](https://cloud.google.com/kubernetes-engine/docs/how-to/iam#assigning_roles_to_service_accounts) to see how these roles can be assigned to the service account.
   273  
   274  ## Benchmarks
   275  
   276  Inspektor Gadget has
   277  [benchmark tests](https://github.com/inspektor-gadget/inspektor-gadget/blob/main/internal/benchmarks/benchmarks_test.go)
   278  that are automatically executed and published by
   279  [github-action-benchmark](https://github.com/benchmark-action/github-action-benchmark). You can see the results on:
   280  
   281  https://inspektor-gadget.github.io/ig-benchmarks/dev/bench/index.html
   282  
   283  This requires a GitHub API token (secret `BENCHMARKS_TOKEN`) configured with read and write access to two repositories:
   284  - [inspektor-gadget/inspektor-gadget](https://github.com/inspektor-gadget/inspektor-gadget): required to allow the bot to post comments
   285  - [inspektor-gadget/ig-benchmarks](https://github.com/inspektor-gadget/ig-benchmarks/tree/gh-pages), see the `gh-pages` branch.
   286  
   287  The GitHub Action is disabled for pushes on forks or PR from forks, so the result page will not be updated by forks.
   288  In this way, forks can still use other parts of the CI without failing, even without the `BENCHMARKS_TOKEN` secret.
   289  
   290  ## Sign release artifact
   291  
   292  We compute hash sum of all our release artifacts and the file containing these checksums is signed using [`cosign`](https://github.com/sigstore/cosign).
   293  To sign this file, you will need to create a private key with an associated password:
   294  
   295  ```bash
   296  $ cosign generate-key-pair
   297  Enter password for private key:
   298  Enter password for private key again:
   299  Private key written to cosign.key
   300  Public key written to cosign.pub
   301  ```
   302  
   303  You will then need to store the content of `cosign.key` in the `COSIGN_PRIVATE_KEY` and the password you used to create the key in `COSIGN_PASSWORD`.
   304  Without these secrets, the release job will not be run.