Um momento
0x90Lesson 10 of 14

Secrets, permissions and deployments

Use secrets and variables safely, give GITHUB_TOKEN the least permission, gate deployments with environments, and publish with GitHub Pages.

28 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • Store and use secrets and variables in workflows without leaking them
  • Limit what the GITHUB_TOKEN can do, and prefer OIDC to long-lived cloud keys
  • Deploy through protected environments, schedule jobs, and publish a site with GitHub Pages

Deploying Dungeon Dash’s web demo needs credentials, and credentials must never live in the repository. Instead:

  • Secrets (Settings → Secrets and variables → Actions) are encrypted values available to workflows as ${{ secrets.NAME }}. They’re masked in logs - printed as ***.
  • Variables (${{ vars.NAME }}) hold non-secret configuration, like a server name.
  • Secrets can belong to a repository, an organization (shared by many repos), or an environment.
.github/workflows/deploy.yml
1name: Deploy demo
2on:
3  push:
4    branches: [main]
5
6permissions:
7  contents: read            # least privilege for the GITHUB_TOKEN
8
9jobs:
10  deploy:
11    runs-on: ubuntu-latest
12    environment: production  # protected: needs approval, has its own secrets
13    steps:
14      - uses: actions/checkout@v4
15      - run: ./scripts/deploy.sh "${{ vars.DEMO_HOST }}"
16        env:
17          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Points worth noticing:

  • The secret reaches the script as an environment variable, not pasted into the command line where it could show up in process listings or logs.
  • permissions: limits the automatic GITHUB_TOKEN every run gets. Its default can be broad; granting only contents: read means a compromised step can’t push code or edit releases. Add what a job really needs: pull-requests: write to comment on PRs, packages: write to publish packages.
  • environment: production ties the job to an environment, which can require a reviewer’s approval before it runs, restrict which branches can deploy, and hold its own secrets.
  • Secrets aren’t passed to workflows triggered by pull requests from forks - otherwise anyone could open a PR that prints your secrets.
masking.py
1secrets = {"DEPLOY_TOKEN": "ghp_4f9Xk2", "DB_PASSWORD": "dragon$fire"}
2log = """Deploying to demo.dungeondash.dev
3Using token ghp_4f9Xk2 for auth
4Connecting with password dragon$fire
5Done"""
6for value in sorted(secrets.values(), key=len, reverse=True):
7    log = log.replace(value, "***")
8print(log)
Output
Deploying to demo.dungeondash.dev
Using token *** for auth
Connecting with password ***
Done

Schedules and GitHub Pages

Scheduled workflows use cron syntax - five fields: minute, hour, day of month, month, day of week (0 = Sunday) - always in UTC. 0 3 * * 1 is 03:00 every Monday; */15 * * * * is every 15 minutes (the shortest interval GitHub allows is 5 minutes, and scheduled runs can start a little late).

GitHub Pages hosts static websites for free, straight from a repository: project docs, a portfolio, or Dungeon Dash’s web demo. Build the site in a workflow with actions/upload-pages-artifact, deploy with actions/deploy-pages, and it appears at https://OWNER.github.io/REPO/.

Key takeaways

  • Keep credentials in Actions secrets (masked in logs) and plain configuration in variables.

  • Set permissions: so the GITHUB_TOKEN has only what each job needs; prefer OIDC over cloud keys.

  • Protected environments add approvals, branch rules and their own secrets to deployments.

  • Cron schedules run in UTC; GitHub Pages hosts static sites built by a workflow.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: automate GitHub chores with Python

Real GitHub work involves lots of small automation: matching CODEOWNERS, expanding build matrices, bumping versions, reading the API. Write those helpers in Python and run them against sample inputs - locally in your browser, with no GitHub account needed.

Exercise 1

Mask the secrets

+25 XP

The input has NAME=value secret lines, a line ---, then a build log. Print the log with every occurrence of each secret value replaced by *** (replace longer secrets first, so a secret containing another is masked whole). Then print masked N occurrences and, if any secret appears base64-encoded in the log, warning: NAME appears base64-encoded.

  • Deploy log
  • Nested secrets
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Exercise 2

Does the schedule fire?

+25 XP

Each input line is a cron expression in quotes, then a UTC date and time: "0 3 * * 1" 2026-10-05 03:00. Print fires or doesn’t fire for each.

Support, in each of the five fields (minute, hour, day of month, month, day of week with 0 = Sunday): *, numbers, comma lists 1,15, ranges 1-5, and steps */15 or 0-30/10. As in standard cron, when both day-of-month and day-of-week are restricted (not *), a match on either is enough.

  • Schedules
  • Day OR weekday
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…

Gostou da aula? 😆👍
Apoie nosso trabalho com uma doação: