Yandex Cloud
Search
Contact UsGet started
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • AI Studio
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Center for Technologies and Society
    • Yandex Cloud Partner program
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
© 2025 Direct Cursus Technology L.L.C.
Yandex Cloud Functions
  • Comparison with other Yandex Cloud services
    • All tutorials
    • Creating a skill for Alice
    • Deploying a web application
    • Creating a skill for Alice and a website with authorization
    • Writing data from a device into a database
    • Writing load balancer logs to PostgreSQL
    • Developing a Slack bot
    • Developing a Telegram bot
    • Connecting to a YDB database from a Python function
    • Connecting to a YDB database from a function in Node.js
    • Converting a video to a GIF in Python
    • Creating a Node.js function using TypeScript
    • Developing a custom integration
    • Creating a budget trigger that invokes a function to stop a VM
    • Creating an interactive serverless application using WebSocket
    • Automatically copying objects from one Object Storage bucket to another
    • Running computations on a schedule in DataSphere
    • Interactive debugging of functions
    • Regular asynchronous recognition of audio files from Object Storage
    • Canary release of Cloud Functions
    • Deploying a fault-tolerant architecture with preemptible VMs
    • Creating triggers that invoke a function to stop a VM and send a Telegram notification
    • Loading data from Yandex Direct to a Yandex Managed Service for ClickHouse® data mart using Yandex Cloud Functions, Yandex Object Storage, and Yandex Data Transfer
    • Status monitoring of geographically distributed devices
    • Sensor reading monitoring and event notifications
    • Emulating multiple IoT devices
    • Streaming Yandex Cloud Postbox events to Yandex Data Streams and analyzing them with Yandex DataLens
    • URL shortener
    • Yandex Tracker: data export and visualization
    • Running computations in DataSphere using the API
    • Developing a Telegram bot for text and audio recognition
    • Configuring responses in Yandex Cloud Logging and Cloud Functions
    • Developing functions in Functions Framework and deploying them to Yandex Serverless Containers
    • Configuring CI/CD with SourceCraft
    • Configuring CI/CD with GitHub
    • Creating an AI agent with Cloud Functions
  • Tools
  • Pricing policy
  • Access management
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Public materials
  • Release notes
  • FAQ

In this article:

  • Get your cloud ready
  • Required paid resources
  • Create a repository
  • Set up your infrastructure in Yandex Cloud
  • Create a service account
  • Create a workload identity federation
  • Create federated credentials for the service account
  • Configure the repository
  • Prepare the project files
  • Push workflow files to the repository
  • Test the workflows
  • Run the CI workflow
  • Check the CI result
  • Run the CT workflow
  • Check the CT result
  • Run the CD workflow
  • Check the CD result
  • How to delete the resources you created
  1. Tutorials
  2. Configuring CI/CD with GitHub

Configuring CI/CD with GitHub

Written by
Yandex Cloud
Updated at September 10, 2025
  • Get your cloud ready
    • Required paid resources
  • Create a repository
  • Set up your infrastructure in Yandex Cloud
    • Create a service account
    • Create a workload identity federation
    • Create federated credentials for the service account
  • Configure the repository
    • Prepare the project files
    • Push workflow files to the repository
  • Test the workflows
    • Run the CI workflow
    • Check the CI result
    • Run the CT workflow
    • Check the CT result
    • Run the CD workflow
    • Check the CD result
  • How to delete the resources you created

GitHub allows storing function code from Yandex Cloud Functions and deploying new function versions if there are updates in the repository.

In this tutorial, you will set up CI/CD between Cloud Functions and GitHub using a Yandex Identity and Access Management workload identity federation and deploy functions from Cloud Functions by running GitHub Actions workflows.

To set up CI/CD:

  1. Get your cloud ready.
  2. Create a repository.
  3. Set up your infrastructure in Yandex Cloud.
  4. Configure the repository.
  5. Test the workflows.

If you no longer need the resources you created, delete them.

Get your cloud readyGet your cloud ready

Sign up for Yandex Cloud and create a billing account:

  1. Navigate to the management console and log in to Yandex Cloud or create a new account.
  2. On the Yandex Cloud Billing page, make sure you have a billing account linked and it has the ACTIVE or TRIAL_ACTIVE status. If you do not have a billing account, create one and link a cloud to it.

If you have an active billing account, you can navigate to the cloud page to create or select a folder for your infrastructure.

Learn more about clouds and folders here.

Required paid resourcesRequired paid resources

The infrastructure support cost for this tutorial includes:

  • Fee for the number of function calls, computing resources allocated to a function, and outbound traffic (see Cloud Functions pricing).
  • Fee for function logging and log storage in a log group (see Yandex Cloud Logging pricing).

Create a repositoryCreate a repository

Create a new GitHub repository or use an existing one where you have permissions to view and run GitHub Actions.

You will need the GitHub repository and user names later.

Set up your infrastructure in Yandex CloudSet up your infrastructure in Yandex Cloud

Create a service accountCreate a service account

GitHub will use a service account with the functions.admin role to create a function and its versions.

Management console
Yandex Cloud CLI
API
  1. In the management console, select the folder where you are going to create your infrastructure.
  2. In the list of services, select Identity and Access Management.
  3. Click Create service account.
  4. Enter the service account name: ci-cd-github-sa.
  5. Click Add role and select functions.admin.
  6. Click Create.

If you do not have the Yandex Cloud CLI installed yet, install and initialize it.

By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID> command. You can also set a different folder for any specific command using the --folder-name or --folder-id parameter.

  1. Create a service account:

    yc iam service-account create --name ci-cd-github-sa
    

    Result:

    id: ajehqs5gee2e********
    folder_id: b1g681qpemb4********
    created_at: "2025-07-12T17:53:28.180991864Z"
    name: ci-cd-github-sa
    
  2. Assign the functions.admin role to the service account:

    yc resource-manager folder add-access-binding <folder_name_or_ID> \
      --role functions.admin \
      --subject serviceAccount:<service_account_ID>
    

    Result:

    effective_deltas:
      - action: ADD
        access_binding:
          role_id: functions.admin
          subject:
            id: ajejocsfa1jj********
            type: serviceAccount
    

To create a service account, use the create REST API method for the ServiceAccount resource or the ServiceAccountService/Create gRPC API call.

To assign the service account the functions.admin role for the folder, use the updateAccessBindings REST API method for the Folder resource or the FolderService/UpdateAccessBindings gRPC API call.

Create a workload identity federationCreate a workload identity federation

You need a workload identity federation to set up the exchange of GitHub tokens for Yandex Cloud IAM tokens.

Management console
Yandex Cloud CLI
API
  1. In the management console, select Identity and Access Management.
  2. In the left-hand panel, select Workload identity federations.
  3. Click Create federation.
  4. In the Issuer value (iss) field, enter the OIDC provider's URL: https://token.actions.githubusercontent.com.
  5. In the Acceptable Audience values (AUD) field, enter the token recipient: https://github.com/<GitHub_user_name>.
  6. In the JWKS address field, enter the URL of the public key list: https://token.actions.githubusercontent.com/.well-known/jwks.
  7. In the Name field, enter the federation name: ci-cd-github-federation.
  8. Click Create.

Run this command:

yc iam workload-identity oidc federation create \
  --name ci-cd-github-federation \
  --issuer "https://token.actions.githubusercontent.com" \
  --audiences "https://github.com/<GitHub_user_name>" \
  --jwks-url "https://token.actions.githubusercontent.com/.well-known/jwks"

Where:

  • --name: Name of the new federation.
  • --issuer: URL of the OIDC provider.
  • --audiences: Resources to issue the token for. You can specify multiple resources at once, separated by commas.
  • --jwks-url: URL for retrieving the current public key issued by the OIDC provider and used for JWT signature verification.

Result:

id: ajeoerss1fa4********
name: ci-cd-github-federation
folder_id: b1g681qpemb4********
enabled: true
audiences:
  - https://github.com/eip********
issuer: https://token.actions.githubusercontent.com
jwks_url: https://token.actions.githubusercontent.com/.well-known/jwks
created_at: "2025-07-24T18:20:33.546066838Z"

To create a workload identity federation, use the create REST API method for the Federation resource or the FederationService/Create gRPC API call.

In the request, specify the following settings:

  • issuer: https://token.actions.githubusercontent.com
  • audiences: https://github.com/<GitHub_user_name>
  • jwks-url/jwks_url: https://token.actions.githubusercontent.com/.well-known/jwks

Create federated credentials for the service accountCreate federated credentials for the service account

With federated credentials, you will set up a link between a workload identity federation, your service account, and GitHub.

Management console
Yandex Cloud CLI
API
  1. In the management console, select Identity and Access Management.

  2. Select the ci-cd-github-sa service account.

  3. Navigate to the Workload identity federations tab.

  4. Click Link to federation.

  5. In the Workload identity federation field, select ci-cd-github-federation.

  6. In the Subject value (sub) field, specify the external subject ID for your test environment: repo:<GitHub_user_name>/<repository_name>:environment:preprod.

    The preprod environment will be later used in the ci.yml and ct.yml files.

  7. Click Link.

In a similar way, create federated credentials with the external subject ID for the production environment: repo:<GitHub_user_name>/<repository_name>:ref:refs/heads/main.

To create federated credentials for your test and production environments, run the following commands:

yc iam workload-identity federated-credential create \
  --service-account-id <service_account_ID> \
  --federation-id <federation_ID> \
  --external-subject-id "repo:<GitHub_user_name>/<repository_name>:environment:preprod"

yc iam workload-identity federated-credential create \
  --service-account-id <service_account_ID> \
  --federation-id <federation_ID> \
  --external-subject-id "repo:<GitHub_user_name>/<repository_name>:ref:refs/heads/main"

Where:

  • --service-account-id: ci-cd-github-sa service account ID.

  • --federation-id: ID of the ci-cd-github-federation workload identity federation.

  • --external-subject-id: External subject ID.

    The preprod environment will be later used in the ci.yml and ct.yml files.

Result:

id: ajek9t6ojc53********
service_account_id: ajejocsfa1jj********
federation_id: ajeoerss1fa4********
external_subject_id: repo:eip********/ci-cd-github-repo:environment:preprod
created_at: "2025-07-24T18:21:01.103940710Z"

id: aje82obioirm********
service_account_id: ajejocsfa1jj********
federation_id: ajeoerss1fa4********
external_subject_id: repo:eip********/ci-cd-github-repo:ref:refs/heads/main
created_at: "2025-07-24T18:21:13.925210300Z"

To create federated credentials, use the create REST API method for the FederatedCredential resource or the FederatedCredentialService/Create gRPC API call.

In the request, set the externalSubjectId/external_subject_id parameter as follows:

  • For the test environment: repo:<GitHub_user_name>/<repository_name>:environment:preprod.

    The preprod environment will be later used in the ci.yml and ct.yml files.

  • For the production environment: repo:<GitHub_user_name>/<repository_name>:ref:refs/heads/main.

Configure the repositoryConfigure the repository

Prepare the project filesPrepare the project files

Repository
Manually

Clone the repository:

git clone https://github.com/yandex-cloud-examples/yc-serverless-ci-cd-github

In the repository, you will see:

  • .github/workflows folder with workflow files: cd.yml, ci.yml, and ct.yml.
  • index.js function code with dependencies described in package.json and package-lock.json.
  1. Create a directory named yc-serverless-ci-cd-github and open it.

  2. Create a file named index.js and paste this code into it:

    const sharp = require('sharp');
    
    async function cropImage(imageBase64, width, height) {
        try {
            // Decode image from base64
            const buffer = Buffer.from(imageBase64, 'base64');
    
            const croppedBuffer = await sharp(buffer)
                .resize(width, height) 
                .toBuffer(); 
    
            const croppedImageBase64 = croppedBuffer.toString('base64');
            return croppedImageBase64;
        } catch (error) {
            console.error('Error cropping image:', error);
            throw error;
        }
    }
    
    module.exports.handler = async function (event, context) {
        return {
            content: await cropImage(event.queryStringParameters.content, event.queryStringParameters.width, event.queryStringParameters.height)
        };
    };
    
  3. Create a file named package.json and paste this code into it:

    {
      "name": "from-github",
      "version": "1.0.0"
    }
    
  4. Run this command:

    npm install --package-lock-only
    

    The command will create the package-lock.json file.

  5. Create the cd.yml, ci.yml, and ct.yml files and paste the code with the parameters you need:

    cd.yml
    permissions:
      id-token: write # Required to request a JWT
    
    on: 
      push:
        branches:
          - main
        paths-ignore:
          - '.github/**' # To ignore changes in workflow files
    
      release:
        types:
          - published
    
      # Enables running this workflow manually from the Actions tab
      workflow_dispatch:
    
    env:
      FOLDER_ID: <folder_ID>
      SA_ID: <service_account_ID>
      FUNCTION_NAME: from-github-cd
      FUNCTION_RUNTIME: nodejs22
      FUNCTION_ENTRYPOINT: index.handler
      FUNCTION_MEMORY: "128mb"
      FUNCTION_SOURCEROOT: .
      
    jobs:
      build:
        runs-on: ubuntu-latest
        
        steps:
          - uses: actions/checkout@v4
          - name: Deploy Function
            id: sls-func
            uses: yc-actions/yc-sls-function@v3.1.0
            with:
              yc-sa-id: ${{env.SA_ID}}
              folder-id: ${{env.FOLDER_ID}}
              function-name: ${{env.FUNCTION_NAME}}
              runtime: ${{env.FUNCTION_RUNTIME}}
              entrypoint: ${{env.FUNCTION_ENTRYPOINT}}
              memory: ${{env.FUNCTION_MEMORY}}
              source-root: ${{env.FUNCTION_SOURCEROOT}}
              include: |
                **/*.json
                **/*.js
    
    ci.yml
    permissions:
      id-token: write # Required to request a JWT
    
    on: 
      push:
        branches: [ feature** ]
        paths-ignore:
          - '.github/**'
    
      # Enables running this workflow manually from the Actions tab
      workflow_dispatch:
    
    env:
      FOLDER_ID: <folder_ID>
      SA_ID: <service_account_ID>
      FUNCTION_NAME: from-github-ci
      FUNCTION_RUNTIME: nodejs22
      FUNCTION_ENTRYPOINT: index.handler
      FUNCTION_MEMORY: "128mb"
      FUNCTION_SOURCEROOT: .
      
    jobs:
      build:
        environment: preprod
        runs-on: ubuntu-latest
        
        steps:
          - uses: actions/checkout@v4
          - name: Deploy Function
            id: sls-func
            uses: yc-actions/yc-sls-function@v3.1.0
            with:
              yc-sa-id: ${{env.SA_ID}}
              folder-id: ${{env.FOLDER_ID}}
              function-name: ${{env.FUNCTION_NAME}}
              runtime: ${{env.FUNCTION_RUNTIME}}
              entrypoint: ${{env.FUNCTION_ENTRYPOINT}}
              memory: ${{env.FUNCTION_MEMORY}}
              source-root: ${{env.FUNCTION_SOURCEROOT}}
              include: |
                **/*.json
                **/*.js
    
    ct.yml
    permissions:
      id-token: write # Required to request a JWT
    
    on: 
      pull_request:
        branches: [ main ]
        paths-ignore:
          - '.github/**'
          
      # Enables running this workflow manually from the Actions tab
      workflow_dispatch:
    
    env:
      FOLDER_ID: <folder_ID>
      SA_ID: <service_account_ID>
      FUNCTION_NAME: from-github-ct
      FUNCTION_RUNTIME: nodejs22
      FUNCTION_ENTRYPOINT: index.handler
      FUNCTION_MEMORY: "128mb"
      FUNCTION_SOURCEROOT: .
      
    jobs:
      build:
        environment: preprod
        runs-on: ubuntu-latest
        
        steps:
          - uses: actions/checkout@v4
          - name: Deploy Function
            id: sls-func
            uses: yc-actions/yc-sls-function@v3.1.0
            with:
              yc-sa-id: ${{env.SA_ID}}
              folder-id: ${{env.FOLDER_ID}}
              function-name: ${{env.FUNCTION_NAME}}
              runtime: ${{env.FUNCTION_RUNTIME}}
              entrypoint: ${{env.FUNCTION_ENTRYPOINT}}
              memory: ${{env.FUNCTION_MEMORY}}
              source-root: ${{env.FUNCTION_SOURCEROOT}}
              include: |
                **/*.json
                **/*.js
    

    Where:

    • FOLDER_ID: ID of the folder you are using to complete this tutorial.

    • SA_ID: ID of the service account with federated credentials.

    • FUNCTION_NAME: Function name. Here, examples use the following names:

      • from-github-ci
      • from-github-ct
      • from-github-cd
    • FUNCTION_RUNTIME: Function runtime environment.

    • FUNCTION_ENTRYPOINT: Function entry point.

    • FUNCTION_MEMORY: Function RAM amount.

    • FUNCTION_SOURCEROOT: Path to the function files in the repository.

Push workflow files to the repositoryPush workflow files to the repository

CLI
  1. Clone your repository if you have not done so already:

    git clone <repository_URL>
    
  2. Copy the workflow files you got to the local copy of your repository:

    • .github/workflows/cd.yml
    • .github/workflows/ci.yml
    • .github/workflows/ct.yml
  3. Push the changes to the remote repository:

    git add . && git commit -m "Added workflows" && git push
    

Test the workflowsTest the workflows

Run the CI, CT, and CD workflows one after the other and check their results.

Run the CI workflowRun the CI workflow

CLI
  1. Switch to the main branch:

    git checkout main
    
  2. Pull changes from a remote repository:

    git pull
    
  3. Create a new branch, feature/smoke-test:

    git checkout -b feature/smoke-test
    
  4. Copy the function files to the root folder in your repository’s local copy:

    • index.js
    • package.json
    • package-lock.json
  5. Save, commit, and push the changes to the remote repository:

    git add .
    git commit -m "Added function"
    git push --set-upstream origin feature/smoke-test
    

    After pushing the changes, the .github/workflows/ci.yml workflow will start automatically.

    Wait for the workflow to complete. You can check the status and execution logs in the Actions tab of your repository.

Check the CI resultCheck the CI result

Management console
  1. In the management console, select Cloud Functions.
  2. Select the from-github-ci function.
  3. Navigate to the Testing tab.
  4. In the Payload field, enter the following code and click Run test:

    {
      "queryStringParameters": {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=",
        "width": 100,
        "height": 100
      }
    }
    

    The Test result section will show the function's response:

    {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAANElEQVR4nO3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAujF1lAABe5jSrAAAAABJRU5ErkJggg=="
    }
    

Run the CT workflowRun the CT workflow

CLI

Using the GitHub interface, create a pull request from the feature/smoke-test branch to the main branch.

Once the pull request is created, the .github/workflows/ct.yml workflow will start automatically.

Wait for the workflow to complete. You can check the status and execution logs in the Actions tab of your repository.

Check the CT resultCheck the CT result

Management console
  1. In the management console, select Cloud Functions.
  2. Select the from-github-ct function.
  3. Navigate to the Testing tab.
  4. In the Payload field, enter the following code and click Run test:

    {
      "queryStringParameters": {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=",
        "width": 100,
        "height": 100
      }
    }
    

    The Test result section will show the function's response:

    {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAANElEQVR4nO3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAujF1lAABe5jSrAAAAABJRU5ErkJggg=="
    }
    

Run the CD workflowRun the CD workflow

CLI

Using the GitHub interface, merge your pull request into the main branch.

This will automatically run the .github/workflows/cd.yml workflow.

Wait for the workflow to complete. You can check the status and execution logs in the Actions tab of your repository.

Check the CD resultCheck the CD result

Management console
  1. In the management console, select Cloud Functions.
  2. Select the from-github-cd function.
  3. Navigate to the Testing tab.
  4. In the Payload field, enter the following code and click Run test:

    {
      "queryStringParameters": {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNgYAAAAAMAASsJTYQAAAAASUVORK5CYII=",
        "width": 100,
        "height": 100
      }
    }
    

    The Test result section will show the function's response:

    {
        "content": "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAACXBIWXMAAAsTAAALEwEAmpwYAAAANElEQVR4nO3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAujF1lAABe5jSrAAAAABJRU5ErkJggg=="
    }
    

How to delete the resources you createdHow to delete the resources you created

To stop paying for the resources you created:

  1. Delete the functions.
  2. Delete the log group.

Was the article helpful?

Previous
Configuring CI/CD with SourceCraft
Next
Creating an AI agent with Cloud Functions
© 2025 Direct Cursus Technology L.L.C.