Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/instructions/hve-core/workflows.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,37 @@ All workflows MUST pass the following validation checks:
fi
```

## YAML Expression Quoting

GitHub Actions expression single quotes (`'...'`) inside `${{ }}` are NOT YAML quotes. The YAML parser treats them as literal characters in a plain scalar. If the expression text contains a colon followed by whitespace (`:` ), the YAML parser interprets it as a mapping value indicator and fails with `mapping values are not allowed in this context`.

**Problem pattern:**

```yaml
# FAILS: ': release' contains colon-space, YAML parser chokes
with:
my-input: ${{ startsWith(value, 'prefix: release') }}
```

**Acceptable solutions (in preference order):**

1. **Shorten the literal to avoid colon-space.** Use a prefix that does not contain a colon followed by whitespace when the specificity tradeoff is acceptable.

```yaml
with:
my-input: ${{ startsWith(value, 'prefix') }}
```

2. **Double-quote the entire expression.** This makes the value a YAML quoted scalar, preventing the parser from interpreting internal colon-space as structure. Add a comment explaining why quotes are required.

```yaml
with:
# Quotes required: expression literal contains ': ' which breaks YAML plain scalars
my-input: "${{ startsWith(value, 'prefix: release') }}"
```

Avoid `format()` workarounds or environment variable indirection when the simpler options above apply.

## Enforcement Statement

The following scripts enforce compliance:
Expand Down
14 changes: 11 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,20 @@ jobs:
token: ${{ steps.app-token.outputs.token }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
# On release commits, skip PR creation to prevent bogus PRs
# from draft release lazy tag timing. Release commits have zero
# unreleased changes so skipping loses nothing. The tag is
# created in the next step, ensuring subsequent runs find it.
skip-github-pull-request: ${{ github.event_name == 'push' && startsWith(github.event.head_commit.message, 'chore(main)') }}

# Workaround: release-please with "draft": true uses lazy tag
# creation — the git tag is not materialized until the release is
# creation. The git tag is not materialized until the release is
# published. Without the tag, release-please cannot find the draft
# on subsequent runs, breaking version anchoring. Create the tag
# explicitly via API. Replace with "force-tag-creation": true in
# on subsequent runs, breaking version anchoring and causing bogus
# major-version PRs. The skip-github-pull-request conditional above
# prevents PR creation on release commits (zero unreleased changes),
# and this step creates the tag so subsequent runs find the release.
# Replace both workarounds with "force-tag-creation": true in
# release-please-config.json once release-please-action ships a
# version that includes googleapis/release-please#2627.
- name: Create git tag for draft release
Expand Down
Loading