GitHub Actions Certification

GitHub Actions Core Concepts

Working with Repository Level Secrets

Securely managing sensitive data in GitHub Actions is essential for robust CI/CD pipelines. In this guide, you’ll learn how to store credentials at the repository level and reference them in your workflows without exposing plain-text values.

Table of Contents


Why Use Secrets and Variables?

Embedding credentials in workflow YAML blocks risks accidental leaks via PRs, clones, or shared logs. GitHub Actions provides a secure mechanism to inject encrypted values at runtime:

  • Secrets for sensitive data (passwords, tokens).
  • Variables for non-sensitive settings (usernames, tags).

Scopes of Secrets and Variables

You can define secrets and variables at three different levels:

ScopeUse CaseVisibility
OrganizationShared across multiple repositoriesOnly Org Admins
RepositoryShared by all workflows in a single repoWrite access to Settings
EnvironmentLimited to specific deployment environmentsEnvironment admins and selected roles

Adding a Repository-Level Secret

  1. Navigate to Settings > Secrets and variables > Actions.
  2. Click New repository secret, set the Name (e.g., DOCKER_PASSWORD), and paste your secret.
  3. Click Add secret to save.

The image shows a GitHub repository settings page where a new secret named "DOCKER_PASSWORD" is being added. The secret value is partially visible, and there's an "Add secret" button.

Note

Repository secrets are encrypted and cannot be viewed once saved. If you lose the value, you must recreate the secret.


Adding a Repository-Level Variable

  1. Still under Settings > Secrets and variables > Actions, select New repository variable.
  2. Enter Name (e.g., DOCKER_USERNAME) and Value.
  3. Click Add variable to confirm.

The image shows a GitHub settings page for adding a new actions variable, with fields for "Name" and "Value." The "Name" field is filled with "DOCKER_USERNAME."

Note

Repository variables are visible in Settings but cannot expose sensitive information.
Use variables for configuration values that are not confidential.


Referencing Secrets and Variables

Below is an insecure example with a plain-text password:

name: Exploring Variables and Secrets
on: [push]

env:
  CONTAINER_REGISTRY: docker.io
  DOCKER_USERNAME: siddharth1
  IMAGE_NAME: github-actions-nginx

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Docker Build
        run: echo docker build

      - name: Docker Login
        env:
          DOCKER_PASSWORD: s3cUrePasSw0rd
        run: echo docker login --username=$DOCKER_USERNAME --password=$DOCKER_PASSWORD

      - name: Docker Publish
        run: echo docker push $CONTAINER_REGISTRY/$DOCKER_USERNAME/$IMAGE_NAME:latest

Secure Workflow with Repository-Level Secrets and Variables

name: Exploring Variables and Secrets
on: [push]

env:
  CONTAINER_REGISTRY: docker.io
  IMAGE_NAME: github-actions-nginx

jobs:
  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Docker Build
        run: |
          echo docker build \
            -t ${{ env.CONTAINER_REGISTRY }}/${{ vars.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest

      - name: Docker Login
        run: |
          echo docker login \
            --username=${{ vars.DOCKER_USERNAME }} \
            --password=${{ secrets.DOCKER_PASSWORD }}

      - name: Docker Publish
        run: |
          echo docker push \
            ${{ env.CONTAINER_REGISTRY }}/${{ vars.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest

  deploy:
    needs: docker
    runs-on: ubuntu-latest
    steps:
      - name: Docker Run
        run: |
          echo docker run -d -p 8080:80 \
            ${{ env.CONTAINER_REGISTRY }}/${{ vars.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest

Warning

Your editor might flag unresolved ${{ vars.* }} or ${{ secrets.* }} references. These work at runtime and can be safely ignored.


Inspecting Workflow Logs

After committing and pushing your workflow, visit the Actions tab to observe the run:

The image shows a GitHub Actions workflow interface with a job named "docker" that is currently queued. The workflow is triggered by a push event and involves a file named `variable-secrets.yml`.

Expand the Docker Login step to verify masking:

echo docker login \
  --username=${{ vars.DOCKER_USERNAME }} \
  --password=${{ secrets.DOCKER_PASSWORD }}
  shell: /usr/bin/bash -e {0}
  env:
    CONTAINER_REGISTRY: docker.io
    IMAGE_NAME: github-actions-nginx
docker login --username=siddharth1 --***

The image shows a GitHub repository settings page focused on "Actions secrets and variables," with a section for managing environment and repository variables. A repository variable named "DOCKER_USERNAME" is highlighted.

Secrets remain hidden (***) and variables load correctly at runtime.


Further Reading

Watch Video

Watch video content

Practice Lab

Practice lab

Previous
Working with Variables at different levels