-
Notifications
You must be signed in to change notification settings - Fork 0
feat: shared Action - DX DORA metrics + modify release practices #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b0e207d
2d56780
5ad5a39
c80c4cd
522644a
92c9f83
ff5adcb
7b7092e
abab76a
b260279
4db1aaa
f403893
f0aa239
09abd3b
32191e0
09e913c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| # Publish DX DORA Metrics (Trunk-Based) | ||
|
|
||
| Publishes deployment metrics to DX (ecobee.getdx.net) for trunk-based development workflows where code is committed directly to the main branch and deployed. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| **Required Secret:** `DX_API_TOKEN` is configured as a GitHub organizational secret. | ||
|
|
||
| This secret is managed centrally by the SRE team and is automatically available to all repositories in the ecobee organization. | ||
|
|
||
| ## Usage | ||
|
|
||
| ```yaml | ||
| - name: Publish DORA metrics | ||
| uses: ecobee/github-actions/publish_dx_dora_metrics_trunk_based@v1 | ||
| continue-on-error: true | ||
| env: | ||
| DX_API_TOKEN: ${{ secrets.DX_API_TOKEN }} | ||
| with: | ||
| repository: 'ecobee/my-service' | ||
| service: 'my-service' | ||
| # Optional: defaults to 'production' - only needed for testing | ||
| environment: 'staging' | ||
| ``` | ||
|
|
||
| > **Note:** Use `@v1` for the latest stable version, `@v1.0.0` to pin to a specific release, or `@main` for the latest (unstable) version. | ||
| > | ||
| > **Important:** Use `continue-on-error: true` to prevent metrics tracking failures from blocking deployments. | ||
|
|
||
| ## Inputs | ||
|
|
||
| | Input | Description | Required | Default | | ||
| |-------|-------------|----------|---------| | ||
| | `repository` | Repository identifier (e.g., `ecobee/service-name`) | Yes | - | | ||
| | `environment` | Deployment environment | No | `production` | | ||
| | `service` | Service identifier | Yes | - | | ||
|
|
||
| > **Note:** The action automatically extracts the commit timestamp from git for change lead time tracking. | ||
|
|
||
| ## Environment Variables | ||
|
|
||
| | Variable | Description | Required | Source | | ||
| |----------|-------------|----------|--------| | ||
| | `DX_API_TOKEN` | DX API token for authentication | Yes | GitHub organizational secret | | ||
|
|
||
| ## Example Workflow | ||
|
|
||
| ```yaml | ||
| name: Deploy to Production | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| jobs: | ||
| deploy: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| # ... your deployment steps ... | ||
|
|
||
| - name: Publish deployment metrics | ||
| uses: ecobee/github-actions/publish_dx_dora_metrics_trunk_based@v1 | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Figured we need to start having versioning. I'm anticipating creating more shared actions as we go. |
||
| continue-on-error: true | ||
| env: | ||
| DX_API_TOKEN: ${{ secrets.DX_API_TOKEN }} | ||
| with: | ||
| repository: 'ecobee/my-service' | ||
| service: 'my-service' | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried to keep this as simple as possible for teams to use. |
||
| ``` | ||
|
|
||
| ## Versioning | ||
|
|
||
| This action follows [semantic versioning](https://semver.org/). When integrating: | ||
| - Use `@v1` to automatically get non-breaking updates (recommended) | ||
| - Use `@v1.0.0` to pin to a specific release | ||
| - Avoid `@main` in production workflows (unstable) | ||
|
|
||
| ## Security Notes | ||
|
|
||
| - The `DX_API_TOKEN` is **never** passed as an action input to prevent accidental exposure in logs | ||
| - The token is configured as a GitHub organizational secret, managed centrally by the SRE team | ||
| - The action will fail explicitly if the token is not available | ||
| - Never commit tokens or credentials to the repository | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| name: 'Publish DX DORA Metrics (Trunk-Based)' | ||
| description: 'Publishes deployment metrics to DX for trunk-based development workflows. Requires DX_API_TOKEN organizational secret which is managed globally by the SRE team. Teams should not have to worry about it.' | ||
| inputs: | ||
| repository: | ||
| description: 'Repository identifier (e.g., ecobee/op-ts-server-core, ecobee/service-home)' | ||
| required: true | ||
| environment: | ||
| description: 'Deployment environment (defaults to production)' | ||
| required: false | ||
| default: 'production' | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is what's needed to show up in DORA. I've made it overridable so we can test connections by querying in DX and setting this to like "test" and it won't affect our actual DORA metrics. |
||
| service: | ||
| description: 'Service identifier (e.g. communicator, service-home)' | ||
| required: true | ||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - name: Publish deployment to DX | ||
| env: | ||
| REPOSITORY: ${{ inputs.repository }} | ||
| ENVIRONMENT: ${{ inputs.environment }} | ||
| SERVICE: ${{ inputs.service }} | ||
| COMMIT_SHA: ${{ github.sha }} | ||
| run: | | ||
| set -euo pipefail | ||
|
|
||
| # Validate required inputs | ||
| if [ -z "$REPOSITORY" ]; then | ||
| echo "::error::repository input is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -z "$SERVICE" ]; then | ||
| echo "::error::service input is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -z "$COMMIT_SHA" ]; then | ||
| echo "::error::commit-sha input is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Validate DX_API_TOKEN is available | ||
| if [ -z "$DX_API_TOKEN" ]; then | ||
| echo "::error::DX_API_TOKEN environment variable is not set. This should be configured as an organizational secret by the SRE team" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # Get commit timestamp from git | ||
| COMMIT_TIMESTAMP_UNIX=$(git show -s --format=%ct "$COMMIT_SHA") | ||
|
|
||
| # Always use current time for deployment | ||
| DEPLOYED_AT_UNIX=$(date +%s) | ||
|
|
||
| # Construct JSON payload safely using jq | ||
| PAYLOAD=$(jq -n \ | ||
| --arg repo "$REPOSITORY" \ | ||
| --arg env "$ENVIRONMENT" \ | ||
| --arg svc "$SERVICE" \ | ||
| --arg sha "$COMMIT_SHA" \ | ||
| --argjson ts "$DEPLOYED_AT_UNIX" \ | ||
| --argjson ct "$COMMIT_TIMESTAMP_UNIX" \ | ||
| '{ | ||
| repository: $repo, | ||
| environment: $env, | ||
| service: {identifier: $svc}, | ||
| commit_sha: $sha, | ||
| deployed_at: $ts, | ||
| metadata: { | ||
| commit_timestamp: $ct | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This gets us DORA lead time as far as I can tell from the docs |
||
| } | ||
| }') | ||
|
|
||
| # Make API call (fails automatically on 4xx/5xx) | ||
| curl --fail --silent --show-error \ | ||
| -X POST "https://ecobee.getdx.net/api/deployments.create" \ | ||
| -H "Authorization: Bearer ${DX_API_TOKEN}" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d "$PAYLOAD" | ||
| shell: bash | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| # Simple release script for github-actions | ||
| # Usage: ./scripts/set-release-tag.sh <version> | ||
|
|
||
| RED='\033[0;31m' | ||
| GREEN='\033[0;32m' | ||
| YELLOW='\033[1;33m' | ||
| NC='\033[0m' # No Color | ||
|
|
||
| error() { | ||
| echo -e "${RED}ERROR: $1${NC}" >&2 | ||
| exit 1 | ||
| } | ||
|
|
||
| info() { | ||
| echo -e "${GREEN}$1${NC}" | ||
| } | ||
|
|
||
| warn() { | ||
| echo -e "${YELLOW}$1${NC}" | ||
| } | ||
|
|
||
| # Compare semver versions | ||
| # Returns 0 if $1 > $2, 1 otherwise | ||
| version_gt() { | ||
| local ver1=$1 | ||
| local ver2=$2 | ||
|
|
||
| # Strip 'v' prefix if present | ||
| ver1=${ver1#v} | ||
| ver2=${ver2#v} | ||
|
|
||
| # Split into major.minor.patch | ||
| IFS='.' read -ra V1 <<< "$ver1" | ||
| IFS='.' read -ra V2 <<< "$ver2" | ||
|
|
||
| # Compare major | ||
| if [[ ${V1[0]} -gt ${V2[0]} ]]; then return 0; fi | ||
| if [[ ${V1[0]} -lt ${V2[0]} ]]; then return 1; fi | ||
|
|
||
| # Compare minor | ||
| if [[ ${V1[1]:-0} -gt ${V2[1]:-0} ]]; then return 0; fi | ||
| if [[ ${V1[1]:-0} -lt ${V2[1]:-0} ]]; then return 1; fi | ||
|
|
||
| # Compare patch | ||
| if [[ ${V1[2]:-0} -gt ${V2[2]:-0} ]]; then return 0; fi | ||
|
|
||
| return 1 | ||
| } | ||
|
|
||
| # Validate semver format | ||
| validate_semver() { | ||
| local version=$1 | ||
| if [[ ! $version =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| error "Invalid version format: $version (expected: v1.2.3)" | ||
| fi | ||
| } | ||
|
|
||
| main() { | ||
| # Check we're on main branch | ||
| local current_branch=$(git branch --show-current) | ||
| if [[ "$current_branch" != "main" ]]; then | ||
| error "Must be on 'main' branch to publish (currently on: $current_branch)" | ||
| fi | ||
|
|
||
| # Fetch latest tags | ||
| info "Fetching latest tags..." | ||
| git fetch --tags | ||
|
|
||
| # Get latest version tag | ||
| local latest_tag=$(git tag -l "v*.*.*" | sort -V | tail -n1) | ||
|
|
||
| if [[ -z "$latest_tag" ]]; then | ||
| warn "No existing version tags found. This will be the first release." | ||
| latest_tag="v0.0.0" | ||
| else | ||
| info "Latest version: $latest_tag" | ||
| fi | ||
|
|
||
| # Get new version (required) | ||
| local new_version="${1:-}" | ||
| if [[ -z "$new_version" ]]; then | ||
| error "Version argument required. Usage: ./scripts/set-release-tag.sh v1.2.3" | ||
| fi | ||
|
|
||
| # Validate format | ||
| validate_semver "$new_version" | ||
|
|
||
| # Check if tag already exists | ||
| if git rev-parse "$new_version" >/dev/null 2>&1; then | ||
| error "Tag $new_version already exists" | ||
| fi | ||
|
|
||
| # Validate new version is greater than latest | ||
| if [[ "$latest_tag" != "v0.0.0" ]]; then | ||
| if ! version_gt "$new_version" "$latest_tag"; then | ||
| error "New version $new_version must be greater than $latest_tag" | ||
| fi | ||
| fi | ||
|
|
||
| # Extract major version for major tag (e.g., v1 from v1.2.3) | ||
| local major_version=$(echo "$new_version" | sed -E 's/^v([0-9]+)\..*/v\1/') | ||
|
|
||
| echo "" | ||
| info "Release Summary:" | ||
| echo " Previous: $latest_tag" | ||
| echo " New: $new_version" | ||
| echo " Major: $major_version (will be updated)" | ||
| echo "" | ||
|
|
||
| read -p "Create and push these tags? (y/N): " confirm | ||
| if [[ ! "$confirm" =~ ^[Yy]$ ]]; then | ||
| warn "Release cancelled" | ||
| exit 0 | ||
| fi | ||
|
|
||
| # Create and push version tag | ||
| info "Creating tag $new_version..." | ||
| git tag "$new_version" | ||
| git push origin "$new_version" | ||
|
|
||
| # Update major version tag | ||
| info "Updating major version tag $major_version..." | ||
| git tag -f "$major_version" | ||
| git push -f origin "$major_version" | ||
|
|
||
| echo "" | ||
| info "✓ Release complete!" | ||
| echo "" | ||
| echo "Tags created:" | ||
| echo " - $new_version" | ||
| echo " - $major_version" | ||
| echo "" | ||
| echo "Teams can now use: @$major_version or @$new_version" | ||
| } | ||
|
|
||
| main "$@" |
Uh oh!
There was an error while loading. Please reload this page.