Command Palette

Search for a command to run...

Hectal
PHASE 2Intermediate ~14 min· topic 2 of 4

Topic 2.2

Secrets & Environments

In one line

GitHub Actions Secrets keep real credentials out of your workflow YAML entirely, and Environments add approval gates and environment-specific secrets on top — the same never-commit-a-real-credential lesson, applied to pipeline configuration.

0/4 · 0%

Key ideas

  1. 01

    This directly extends the exact lesson Git's own course covered in depth (Phase 7.5) and Kubernetes' own course revisited (Phase 5.3) — a real credential (a deployment key, a database password, a cloud API token) must NEVER be written directly into a workflow YAML file, since that file is committed to Git and subject to the exact same permanent-history exposure risk as any other committed secret.

  2. 02

    GITHUB ACTIONS SECRETS (configured in a repository's or organization's own Settings, never in a YAML file) are referenced in a workflow via \${{ secrets.MY_SECRET }} — GitHub injects the actual value at runtime, automatically MASKS it in any log output (replacing it with *** if it would otherwise be printed), and the value itself is never visible in the workflow file or its history at all.

  3. 03

    ORGANIZATION-level secrets can be shared across MANY repositories at once, while REPOSITORY-level secrets are scoped to just one — genuinely useful for a shared credential (an internal artifact registry's access token, say) that many repositories legitimately need, versus one that's genuinely specific to a single project.

  4. 04

    An ENVIRONMENT (production, staging) is a named, configurable target that a job can be scoped to (environment: production) — environments can have their OWN secrets (a production database URL genuinely different from staging's), and critically, can require MANUAL APPROVAL from a specific person or team before a job targeting that environment is allowed to actually run.

  5. 05

    This required-approval mechanism is genuinely the same 'deployment approvals' concept the original DevOps roadmap this course draws from names directly (Section 26, CI/CD Security) — a deployment to production can be configured to pause and wait for an explicit human click before proceeding, giving a real, deliberate gate on the single most consequential kind of pipeline action, even within an otherwise fully automated CI/CD setup.

  6. 06

    Secrets are correctly scoped to the NARROWEST level that genuinely needs them — a production deployment credential belongs in the production environment's own secrets, never as a repository-wide secret every job (including unrelated ones that don't deploy anywhere) could potentially access, exactly the same least-privilege principle Linux, Docker, and Kubernetes' own courses have each applied in their own specific context.

Code & diagrams

SecretsAndEnvironmentsdiagram

A production deployment specifically requires human approval before it's allowed to proceed.

Rendering diagram…
secrets-and-environments.ymlmarkdown

A secret referenced safely, and a production environment requiring approval.

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mvn test

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    environment: staging          # uses staging's own scoped secrets
    steps:
      - run: |
          echo "Deploying to staging..."
          curl -H "Authorization: Bearer ${{ secrets.STAGING_DEPLOY_TOKEN }}" \
            https://staging.example.com/deploy

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production        # this one has a required reviewer configured
    steps:
      - run: |
          echo "Deploying to production..."
          curl -H "Authorization: Bearer ${{ secrets.PROD_DEPLOY_TOKEN }}" \
            https://example.com/deploy

Explain it without notes

01

Why does referencing a secret as \${{ secrets.MY_SECRET }} in a workflow file, committed to Git, not actually expose the secret's real value the way hardcoding it directly would?

02

Why would a team specifically configure required-reviewer approval on the production environment but not on staging?

Practice

01

Add a secret to a real GitHub repository's settings and reference it in a workflow, confirming with a deliberate echo (or checking the logs) that GitHub correctly masks it rather than printing the real value.

02

Configure a GitHub Environment with a required reviewer, and confirm a job targeting that environment genuinely pauses and waits for manual approval before proceeding.

Trade-offs

  • ↔

    Requiring manual approval on production deployments is a genuine, deliberate trade-off between speed and safety — it means production deployments can never be fully 'Continuous Deployment' (Topic 0.1) in the strictest sense, since a human step is always in the path, but for the vast majority of real teams, that trade is exactly correct: the cost of a brief manual approval pause is small compared to the cost of an unreviewed, fully automatic production deployment going wrong.

Done when you can

  • I can add and reference a GitHub Actions secret without ever writing its real value into a workflow file.

  • I understand how a GitHub Environment scopes secrets and can require manual approval.

  • I know to scope a secret to the narrowest environment that genuinely needs it, not repository-wide by default.