diff --git a/.github/workflows/FORK_PREVIEW_SETUP.md b/.github/workflows/FORK_PREVIEW_SETUP.md new file mode 100644 index 000000000..066e8be65 --- /dev/null +++ b/.github/workflows/FORK_PREVIEW_SETUP.md @@ -0,0 +1,118 @@ +# Fork Preview Setup Guide + +This workflow automatically builds and deploys preview versions of the site when you push to branches in your fork. This allows you to review your changes before creating a PR to the main project. + +## How it works + +1. Fork the `github/training-kit` repository +2. Push changes to any branch (except `main` or `gh-pages`) +3. The workflow automatically builds the Jekyll site and deploys to your fork's GitHub Pages +4. Preview is available at: `https://your-username.github.io/training-kit/preview/branch-name/` +5. Review your changes before creating a PR to the main project + +## Setup Required (One-time setup) + +### 1. Enable GitHub Pages in your fork + +After you push your first branch, the workflow will create a `gh-pages` branch. Then: + +- Go to your fork's **Settings** → **Pages** +- Under "Source", select **Deploy from a branch** +- Select **gh-pages** branch and **/ (root)** folder +- Click **Save** +- GitHub Pages will be available at: `https://your-username.github.io/training-kit/` + +**That's it!** The workflow uses `GITHUB_TOKEN` which is automatically available in GitHub Actions - no PAT needed. + +## Preview URL Format + +Previews are organized by branch name: +``` +https://{your-username}.github.io/training-kit/preview/{branch-name}/ +``` + +For example: +- Branch `add-spanish-translation` → `https://johndoe.github.io/training-kit/preview/add-spanish-translation/` +- Branch `fix/typo` → `https://johndoe.github.io/training-kit/preview/fix-typo/` (slashes replaced with dashes) + +## Workflow + +### For Contributors (Translation/Content Editors) + +1. **Fork** the repository +2. **Enable GitHub Pages** (one-time setup, see above) +3. **Create a branch** with your changes +4. **Push** to your fork +5. **Check Actions tab** for the deployment status +6. **Review** your preview at the URL shown in the workflow output +7. **Create PR** to the main project once you're satisfied + +### Checking the Preview URL + +After pushing, you can find the preview URL in two places: + +1. **GitHub Actions output:** + - Go to your fork's **Actions** tab + - Click on the latest workflow run + - Expand the "Display preview URL" step + - Copy the preview URL + +2. **Direct URL pattern:** + - Just use: `https://your-username.github.io/training-kit/preview/your-branch-name/` + +## Benefits + +- ✅ **No approval required** - Runs automatically in your fork +- ✅ **No PAT needed** - Uses built-in `GITHUB_TOKEN` +- ✅ **Preview before PR** - Review changes before submitting to main project +- ✅ **Multiple previews** - Each branch gets its own preview URL +- ✅ **Easy for translators** - Non-technical contributors can see their work live + +## Managing Previews + +### Updating a Preview +Just push new commits to the same branch - the preview updates automatically. + +### Cleaning Up Old Previews +To remove old preview directories: +1. Go to your fork +2. Switch to the `gh-pages` branch +3. Delete the `preview/branch-name/` directory +4. Commit and push + +Or use git: +```bash +git checkout gh-pages +git rm -rf preview/old-branch-name +git commit -m "Remove old preview" +git push +``` + +## Differences from Main Project + +- **Main project workflow:** Only deploys to production on push to `main` +- **Fork preview workflow:** Deploys every branch to a preview URL in your fork + +## Security + +- Runs only in forks (not in the main `github/training-kit` repository) +- Uses `GITHUB_TOKEN` with limited permissions +- No secrets or PAT required +- Each contributor controls their own fork and previews + +## Troubleshooting + +### Preview not showing up? +1. Check if GitHub Pages is enabled in Settings → Pages +2. Wait a few minutes - first deployment can take 5-10 minutes +3. Check the Actions tab for any errors + +### 404 on preview URL? +1. Make sure the branch name in the URL matches (slashes become dashes) +2. Check if the workflow completed successfully +3. Verify GitHub Pages is set to deploy from `gh-pages` branch + +### Workflow not running? +1. Make sure you pushed to a branch (not `main` or `gh-pages`) +2. Check that you're working in a fork, not the main repository +3. Check the Actions tab is enabled in your fork settings diff --git a/.github/workflows/PR_PREVIEW_SETUP.md b/.github/workflows/PR_PREVIEW_SETUP.md new file mode 100644 index 000000000..a1e4639c0 --- /dev/null +++ b/.github/workflows/PR_PREVIEW_SETUP.md @@ -0,0 +1,73 @@ +# PR Preview Setup Guide + +This workflow automatically builds and deploys preview versions of the site for pull requests coming from forks. This is especially useful for translation reviews and content editing. + +## How it works + +1. When a PR is opened from a fork, the workflow builds the Jekyll site +2. The built site is deployed to the fork's GitHub Pages under `pr-{number}/` +3. A comment is posted on the PR with the preview URL +4. The preview updates automatically when new commits are pushed + +## Setup Required (For Fork Owners) + +To enable preview deployments from your fork, you need to: + +### 1. Create a Fine-Grained Personal Access Token +- Go to GitHub Settings → Developer settings → Personal access tokens → **Fine-grained tokens** +- Click "Generate new token" +- Configure the token: + - **Token name:** `PR Preview Deploy` + - **Expiration:** Choose your preferred expiration (90 days, 1 year, custom, or no expiration) + - **Resource owner:** Select yourself (the fork owner) + - **Repository access:** Select "Only select repositories" + - Choose your fork repository (e.g., `your-username/training-kit`) + - **Permissions → Repository permissions:** + - ✅ **Contents:** Read and write (required to push to gh-pages branch) + - ✅ **Pages:** Read and write (required to manage GitHub Pages) + - ✅ **Metadata:** Read-only (automatically included) +- Click "Generate token" +- **Copy the token immediately** (you won't see it again) + +### 2. Add the token to your fork's secrets +- Go to your fork's Settings → Secrets and variables → Actions +- Click "New repository secret" +- Name: `PREVIEW_DEPLOY_TOKEN` +- Value: Paste the fine-grained personal access token you created +- Click "Add secret" + +### 3. Enable GitHub Pages in your fork (after first deployment) +After the first PR preview is deployed, the gh-pages branch will be created automatically. Then: +- Go to your fork's Settings → Pages +- Under "Source", select "Deploy from a branch" +- Select **gh-pages** branch and **/ (root)** folder +- Click Save +- GitHub Pages will be available at: `https://your-username.github.io/training-kit/` + +## Preview URL Format + +Previews will be available at: +``` +https://{fork-owner}.github.io/{repo-name}/pr-{number}/ +``` + +For example: +``` +https://johndoe.github.io/training-kit/pr-42/ +``` + +## Security + +- Only runs for PRs from forks (not internal PRs) +- Uses `pull_request_target` to run in the context of the base repository +- Checks out the specific PR SHA to build exactly what was submitted +- Uses fine-grained PAT with minimal required permissions (Contents and Pages only) +- Each fork owner controls their own credentials and deployment + +## Notes + +- The gh-pages branch is created automatically on first deployment +- The first deployment may take a few minutes for GitHub Pages to become available +- Previews persist until manually deleted from the gh-pages branch +- Each PR gets its own isolated preview directory +- You can clean up old previews by deleting directories from the gh-pages branch diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 000000000..dc13f138f --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,136 @@ +# Preview Deployment Workflows + +This repository has two complementary preview workflows for a gradual review process: + +## 1. Fork Preview (Automated - No Approval Needed) +**File:** `fork-preview.yml` + +Runs automatically in contributor forks when pushing to branches. + +### Purpose +- Contributors can preview their changes before creating a PR +- Translation teams can review content without waiting for maintainer approval +- No setup required beyond enabling GitHub Pages + +### When it runs +- On push to any branch in a fork (except `main` and `gh-pages`) +- Automatically, no approval needed + +### Preview URL +``` +https://{fork-owner}.github.io/training-kit/preview/{branch-name}/ +``` + +### Setup +See [FORK_PREVIEW_SETUP.md](./FORK_PREVIEW_SETUP.md) + +--- + +## 2. PR Preview (Maintainer Approved) +**File:** `pr-preview.yml` + +Runs when a PR is created from a fork to the main project. + +### Purpose +- Maintainers can review the exact PR changes before merging +- Provides a canonical preview URL for discussion in the PR +- Allows fine-grained review with maintainer oversight + +### When it runs +- On pull request events (opened, synchronize, reopened) +- Requires maintainer approval for first-time contributors +- Only for PRs from forks (not internal PRs) + +### Preview URL +``` +https://{fork-owner}.github.io/training-kit/pr-{number}/ +``` + +### Setup +See [PR_PREVIEW_SETUP.md](./PR_PREVIEW_SETUP.md) + +--- + +## Gradual Review Process + +### Step 1: Development & Self-Review (Fork Preview) +1. **Contributor:** Fork the repository +2. **Contributor:** Create a branch and push changes +3. **Contributor:** Review at `https://{fork-owner}.github.io/training-kit/preview/{branch}/` +4. **Contributor:** Iterate on changes, preview updates automatically + +### Step 2: Initial Discussion (Fork Preview) +1. **Contributor:** Share fork preview URL with translation team/reviewers +2. **Team:** Discuss and suggest changes using the fork preview +3. **Contributor:** Make adjustments based on feedback +4. **Team:** Approve when ready for formal PR + +### Step 3: PR Submission & Maintainer Review (PR Preview) +1. **Contributor:** Create PR to main project +2. **Maintainer:** Approve workflow run (first-time contributors only) +3. **Workflow:** Deploys to `https://{fork-owner}.github.io/training-kit/pr-{number}/` +4. **Maintainer & Team:** Final review using PR preview URL +5. **Maintainer:** Approve and merge when ready + +--- + +## Comparison + +| Feature | Fork Preview | PR Preview | +|---------|-------------|------------| +| **Trigger** | Push to fork branch | PR from fork | +| **Approval needed** | No | Yes (first-time) | +| **URL pattern** | `/preview/{branch}/` | `/pr-{number}/` | +| **Best for** | Self-review, team discussion | Maintainer review | +| **Setup** | Enable Pages only | Enable Pages + PAT | +| **When to use** | During development | After PR created | + +--- + +## Benefits of This Two-Stage Approach + +### For Contributors +- ✅ Instant feedback without waiting for approval +- ✅ Iterate quickly on changes +- ✅ Share previews with translation teams +- ✅ Submit PR only when ready + +### For Maintainers +- ✅ Review already-vetted content +- ✅ Control workflow execution for security +- ✅ Canonical PR preview URL for discussion +- ✅ Less time spent on back-and-forth + +### For Translation Teams +- ✅ Review translations in context before PR +- ✅ No technical knowledge needed +- ✅ Faster approval process +- ✅ Better quality submissions + +--- + +## Which Setup Do I Need? + +### I'm a contributor/translator +→ **Fork Preview only** +- One-time: Enable GitHub Pages in your fork +- See [FORK_PREVIEW_SETUP.md](./FORK_PREVIEW_SETUP.md) + +### I want PR previews too (optional) +→ **Fork Preview + PR Preview** +- Additionally: Create fine-grained PAT and add to secrets +- See [PR_PREVIEW_SETUP.md](./PR_PREVIEW_SETUP.md) + +### I'm a maintainer +→ **No setup needed** +- Approve workflow runs as needed +- Review using PR preview URLs + +--- + +## Notes + +- Both workflows can coexist - use what fits your workflow +- Fork previews work immediately with just GitHub Pages enabled +- PR previews require additional PAT setup but provide PR-specific URLs +- Contributors can use one or both depending on their needs diff --git a/.github/workflows/fork-preview.yml b/.github/workflows/fork-preview.yml new file mode 100644 index 000000000..75aa9a245 --- /dev/null +++ b/.github/workflows/fork-preview.yml @@ -0,0 +1,83 @@ +name: Fork Preview Deployment + +# This workflow runs on the FORK repository when contributors push changes +# It builds and deploys previews to the fork's GitHub Pages +# Contributors can review their changes before creating a PR to the main project + +on: + push: + branches: + - '**' # Run on all branches + - '!main' # Except main branch + - '!gh-pages' # Except gh-pages branch + +permissions: + contents: write + pages: write + id-token: write + +jobs: + build-and-deploy-preview: + # Only run if this is a fork (not the main github/training-kit repo) + if: github.repository != 'github/training-kit' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + + - name: Install node modules + run: npm install + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Extract branch name + id: branch + run: | + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + # Sanitize branch name for use in URL (replace / with -) + SAFE_BRANCH=$(echo "$BRANCH_NAME" | sed 's/\//-/g') + echo "name=$BRANCH_NAME" >> $GITHUB_OUTPUT + echo "safe=$SAFE_BRANCH" >> $GITHUB_OUTPUT + + - name: Build with Jekyll + run: | + # Build with baseurl including preview path for correct asset/link URLs + bundle exec jekyll build --baseurl "/${{ github.event.repository.name }}/preview/${{ steps.branch.outputs.safe }}" + env: + JEKYLL_ENV: production + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./_site + publish_branch: gh-pages + destination_dir: preview/${{ steps.branch.outputs.safe }} + user_name: 'github-actions[bot]' + user_email: 'github-actions[bot]@users.noreply.github.com' + force_orphan: true + + - name: Display preview URL + run: | + echo "::notice title=Preview Deployed::Preview URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/preview/${{ steps.branch.outputs.safe }}/" + echo "" + echo "=========================================" + echo "🎉 Preview Deployment Successful!" + echo "=========================================" + echo "" + echo "📝 Branch: ${{ steps.branch.outputs.name }}" + echo "🔗 Preview URL: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/preview/${{ steps.branch.outputs.safe }}/" + echo "" + echo "ℹ️ Note: It may take a few minutes for GitHub Pages to update." + echo "ℹ️ Make sure GitHub Pages is enabled in your repository settings." + echo "" + echo "=========================================" diff --git a/.github/workflows/pr-preview.yml b/.github/workflows/pr-preview.yml new file mode 100644 index 000000000..e83acbd4d --- /dev/null +++ b/.github/workflows/pr-preview.yml @@ -0,0 +1,120 @@ +name: PR Preview Deployment + +on: + pull_request_target: + branches: ["main"] + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + # Only run for PRs from forks + check-fork: + runs-on: ubuntu-latest + outputs: + is-fork: ${{ steps.check.outputs.is-fork }} + steps: + - name: Check if PR is from fork + id: check + run: | + if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then + echo "is-fork=true" >> $GITHUB_OUTPUT + else + echo "is-fork=false" >> $GITHUB_OUTPUT + fi + + build-and-deploy-preview: + needs: check-fork + if: needs.check-fork.outputs.is-fork == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout PR branch + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Set up Node + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + + - name: Install node modules + run: npm install + + - name: Set up Ruby + uses: ruby/setup-ruby@ece82769428359c077b5a5eaff268902a303c101 + with: + bundler-cache: true + + - name: Build with Jekyll + run: | + # Build with baseurl including pr path for correct asset/link URLs + bundle exec jekyll build --baseurl "/${{ github.event.pull_request.head.repo.name }}/pr-${{ github.event.pull_request.number }}" + env: + JEKYLL_ENV: production + + - name: Deploy to fork's GitHub Pages + uses: peaceiris/actions-gh-pages@v3 + with: + # This requires the fork to have a fine-grained PAT as a secret + # The fork owner needs to set up PREVIEW_DEPLOY_TOKEN in their repo secrets + personal_token: ${{ secrets.PREVIEW_DEPLOY_TOKEN }} + publish_dir: ./_site + publish_branch: gh-pages + destination_dir: pr-${{ github.event.pull_request.number }} + user_name: 'github-actions[bot]' + user_email: 'github-actions[bot]@users.noreply.github.com' + # Create gh-pages branch if it doesn't exist + force_orphan: true + + - name: Comment preview URL + uses: actions/github-script@v6 + with: + script: | + const prNumber = context.payload.pull_request.number; + const forkOwner = context.payload.pull_request.head.repo.owner.login; + const forkRepo = context.payload.pull_request.head.repo.name; + const previewUrl = `https://${forkOwner}.github.io/${forkRepo}/pr-${prNumber}/`; + + const comment = `## 📝 Preview Deployment + + Your preview is ready! 🎉 + + 🔗 **Preview URL:** ${previewUrl} + + This preview will be updated automatically when you push new commits to this PR. + + > **Note:** The preview is deployed to the fork's GitHub Pages. Make sure GitHub Pages is enabled in your fork's settings.`; + + // Find existing preview comment + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + }); + + const botComment = comments.find(comment => + comment.user.type === 'Bot' && + comment.body.includes('Preview Deployment') + ); + + if (botComment) { + // Update existing comment + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: comment + }); + } else { + // Create new comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: comment + }); + } diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..ffd7047ad --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,537 @@ +# AGENTS.md - Guide for AI Agents Working in training-kit + +## Project Overview + +This is the **GitHub Training Kit** repository - an open source courseware project from the GitHub Professional Services team. The repository contains Git and GitHub cheat sheets translated into 25+ languages, Git guides, and training materials served as a static website. + +**Primary Purpose**: Provide educational resources for people learning Git and GitHub +**Tech Stack**: Jekyll static site generator, Primer CSS (GitHub's CSS toolkit), Markdown content +**Deployment**: GitHub Pages +**Repository**: https://github.com/github/training-kit + +## Essential Commands + +### Development Workflow (Scripts to Rule Them All Pattern) + +This project follows the [Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all) pattern. All main scripts are in the `script/` directory: + +```bash +# Initial setup - Install all dependencies (Ruby gems + Node modules) +script/bootstrap + +# Build the site (runs rake build which includes jekyll build) +script/build + +# Start local development server +script/server +# Opens site at http://127.0.0.1:4000/ + +# Package site for distribution behind firewall +script/package +# Creates release-.tgz with built site +``` + +### Rake Commands + +The project uses Rake for build automation (see `Rakefile`): + +```bash +# Build the site (cleans first, then builds with Jekyll) +bundle exec rake build + +# Serve the site (builds first, then serves) +bundle exec rake serve + +# Run full test suite (builds + runs html-proofer validation) +bundle exec rake test +# or just: bundle exec rake (test is default task) + +# Clean generated files +bundle exec rake clean +``` + +### Direct Jekyll Commands + +```bash +# Build site directly with Jekyll +bundle exec jekyll build + +# Build with production environment +JEKYLL_ENV=production bundle exec jekyll build + +# Build with custom baseurl (used in CI) +bundle exec jekyll build --baseurl "/some-path" + +# Serve site directly +bundle exec jekyll serve +``` + +### Dependency Management + +```bash +# Install Ruby dependencies +bundle install --path vendor/gems --binstubs bin + +# Install Node dependencies +npm install + +# Update dependencies +bundle update +npm update +``` + +## Project Structure + +``` +training-kit/ +├── _config.yml # Jekyll configuration +├── _layouts/ # Jekyll layout templates +│ ├── default.html # Base layout with header/footer +│ └── cheat-sheet.html # Layout for cheat sheets +├── _includes/ # Reusable HTML partials +│ ├── header.html # Site navigation header +│ ├── footer.html # Site footer +│ ├── head.html # HTML head with meta tags +│ ├── breadcrumbs.html # Breadcrumb navigation +│ └── analytics.html # Google Analytics tracking +├── _pages/ # Standalone pages +│ └── 404.md +├── downloads/ # Main content directory +│ ├── github-git-cheat-sheet.md # English Git cheat sheet +│ ├── / # Language-specific directories (de/, fr/, ja/, etc.) +│ │ └── github-git-cheat-sheet.md # Translated cheat sheets +│ ├── subversion-migration.md +│ └── submodule-vs-subtree-cheat-sheet.md +├── git-guides/ # Educational Git guides +│ ├── git-commit.md +│ ├── git-clone.md +│ ├── git-add.md +│ └── ... +├── assets/ # Frontend assets +│ ├── css/ # Compiled CSS +│ ├── _scss/ # Sass source files +│ └── fonts/ # Font files (FontAwesome) +├── index.html # Homepage with language links +├── script/ # Build/dev scripts +├── Gemfile # Ruby dependencies +├── package.json # Node dependencies +└── Rakefile # Build tasks +``` + +## Content Organization + +### Cheat Sheets + +- **Location**: `downloads/` directory +- **Layout**: Use `layout: cheat-sheet` in front matter +- **Structure**: Two-column layout using Liquid capture blocks (`{% capture colOne %}` / `{% capture colTwo %}`) +- **Translations**: Each language gets its own subdirectory (e.g., `downloads/fr/`, `downloads/ja/`) +- **Naming**: Use language code subdirectory names from ISO 639-1 (with regional variants like `zh_CN`, `pt_BR`) + +### Git Guides + +- **Location**: `git-guides/` directory +- **Format**: Standard Markdown files +- **Topics**: Individual Git commands and concepts (git-commit, git-clone, etc.) +- **Style**: Educational, beginner-friendly, includes explanations of how commands work + +### Index Page + +- **File**: `index.html` +- **Purpose**: Landing page with links to all translated cheat sheets and resources +- **When adding translations**: Must update this file to add new language links +- **Format**: HTML with Liquid templating, uses Primer CSS classes and Octicons + +## Content Conventions + +### Front Matter + +All Markdown files require Jekyll front matter: + +```yaml +--- +layout: cheat-sheet # or 'default' +title: "Page Title" +redirect_to: false # Important: prevents auto-redirect to training.github.com +--- +``` + +**Critical**: The `redirect_to: false` is essential for content pages. Without it, pages redirect to the parent site due to the default in `_config.yml:88-89`. + +### Markdown Files + +- Use standard Markdown with Kramdown extensions +- Code blocks: Use triple backticks with optional language specifier +- Command examples: Prefix with `$` to indicate shell commands +- Formatting: Follow existing patterns in similar files + +### Cheat Sheet Structure + +Two-column layout using Liquid capture blocks: + +```liquid +{% capture colOne %} +## Section Title +Content here... +{% endcapture %} +
+{{ colOne | markdownify }} +
+ +{% capture colTwo %} +## Another Section +More content... +{% endcapture %} +
+{{ colTwo | markdownify }} +
+``` + +### HTML/Liquid Templates + +- **Primer CSS**: Use Primer utility classes (e.g., `d-flex`, `flex-items-center`, `color-bg-subtle`) +- **Octicons**: Include icons with `{% octicon icon-name %}` +- **Conditionals**: Check for page variables with `{% if page.variable %}` +- **Loops**: Iterate collections with `{% for item in collection %}` + +### Styling + +- **Framework**: Primer CSS v20+ (GitHub's design system) +- **Import**: Main stylesheet imports from `@primer/css/index.scss` +- **Custom styles**: In `assets/_scss/` directory +- **Variables**: Use Primer CSS variables (e.g., `$spacer-4`, `--color-scale-blue-6`) +- **Responsive**: Use Primer's responsive utilities (`col-12 col-md-6`) + +## Translation Workflow + +When adding a new translation: + +1. **Create language directory**: `downloads//` +2. **Copy English version**: Start from `downloads/github-git-cheat-sheet.md` +3. **Translate content**: Keep front matter, translate body +4. **Update index.html**: Add link to new translation in the appropriate list +5. **Follow language codes**: + - Two-letter codes: `de`, `fr`, `ja`, `ko` + - Regional variants: `pt_BR`, `pt_PT`, `es_ES`, `zh_CN`, `zh_TW` + - Use underscores for separators, not hyphens +6. **Get native speaker review**: As per CONTRIBUTING.md, @ mention friends for review +7. **PDF versions** (optional): Some languages have both `.md` and `.pdf` versions + +## Testing + +### Local Testing + +```bash +# Build and serve locally +script/server + +# Visit http://127.0.0.1:4000/ in browser +``` + +### Automated Testing (html-proofer) + +The `rake test` task validates: +- ✅ HTML validity +- ✅ Valid links (internal and external) +- ✅ Images use HTTPS +- ✅ Favicon exists +- ✅ Alt tags on images + +**Note**: External link checking can be slow and may fail due to rate limiting or temporary outages. + +### CI/CD + +GitHub Actions workflows in `.github/workflows/`: + +- **jekyll.yml**: Main build/test/deploy workflow + - On PR: Runs `bundle exec rake` (full test suite) + - On push to main: Builds with Jekyll and deploys to GitHub Pages + - Uses Node 16 and Ruby (version from Gemfile) +- **codeql.yml**: Security scanning +- **dependency-review.yml**: Dependency security checks + +## Important Gotchas + +### 1. Default Redirect Behavior + +**CRITICAL**: The `_config.yml` sets a global default redirect: + +```yaml +defaults: + - scope: + path: "" + values: + redirect_to: + - https://training.github.com +``` + +**Solution**: Every content page MUST override with `redirect_to: false` in front matter, or it will redirect away from the site. + +### 2. Package Script Platform Dependency + +The `script/package` uses `sed -i ""` which is macOS-specific: +```bash +sed -i "" 's/tracking_id *:.*/tracking_id:/' _config.yml +``` + +On Linux, `sed -i` doesn't take an empty string argument. May need adjustment for cross-platform use. + +### 3. Jekyll Plugins + +Required plugins (see `_config.yml:38-45`): +- jekyll-paginate +- jekyll-sitemap +- jekyll-gist +- jekyll-feed +- jemoji (emoji support) +- jekyll-redirect-from +- jekyll-octicons (GitHub icon support) + +All must be installed via bundle for site to build correctly. + +### 4. Primer CSS Import + +The project uses `@primer/css` from npm, imported in Sass files. Must run `npm install` before building or styles will fail to compile. + +### 5. Sass Configuration + +Uses `sass-embedded` implementation (see `_config.yml:78`). If you encounter Sass compilation errors, ensure this gem is installed. + +### 6. Language/Locale Handling + +The site uses `lang` variable for internationalization: +- Default: `en` (set in `_config.yml:81`) +- Per-page: Set `lang: ""` in front matter +- Used in templates to fetch language-specific navigation data + +### 7. Breadcrumbs Configuration + +Breadcrumbs are enabled globally (`breadcrumbs: true` in `_config.yml:18`) but can be controlled per-page. Some pages set `breadcrumbColor` to customize appearance. + +## File and Directory Conventions + +### File Naming + +- **Markdown files**: Use lowercase with hyphens (e.g., `github-git-cheat-sheet.md`) +- **Directories**: Lowercase, use underscores for language variants (e.g., `pt_BR`, `zh_CN`) +- **Layouts/includes**: Lowercase with hyphens (e.g., `cheat-sheet.html`) + +### Front Matter Requirements + +Minimum front matter for content pages: +```yaml +--- +layout: default +title: "Page Title" +redirect_to: false +--- +``` + +For cheat sheets: +```yaml +--- +layout: cheat-sheet +redirect_to: false +title: "Cheat Sheet Title" +byline: "Brief description" +leadingpath: ../../ # Relative path to root for assets +--- +``` + +### Excluded from Build + +Per `_config.yml:47-59`, these are excluded from Jekyll build: +- `bin/` +- `Gemfile*` +- `node_modules/` +- `Rakefile` +- `README.md` +- `script/` +- `vendor/` +- `package.json` +- `package-lock.json` + +Don't reference these files from content pages. + +## Code Style and Patterns + +### HTML/Liquid + +- **Indentation**: 2 spaces +- **Liquid tags**: Space inside delimiters: `{% if condition %}` not `{%if condition%}` +- **Primer utilities**: Prefer utility classes over custom CSS +- **Semantic HTML**: Use appropriate elements (`
`, `