|
| 1 | +name: npm published smoke |
| 2 | + |
| 3 | +on: |
| 4 | + workflow_run: |
| 5 | + workflows: ['Publish to npm'] |
| 6 | + types: [completed] |
| 7 | + workflow_dispatch: |
| 8 | + inputs: |
| 9 | + version: |
| 10 | + description: 'Published npm version to verify (defaults to package.json from checked-out commit)' |
| 11 | + required: false |
| 12 | + |
| 13 | +jobs: |
| 14 | + smoke: |
| 15 | + if: > |
| 16 | + github.event_name == 'workflow_dispatch' || |
| 17 | + (github.event.workflow_run.conclusion == 'success' && |
| 18 | + github.event.workflow_run.event == 'release') |
| 19 | + runs-on: ubuntu-latest |
| 20 | + permissions: |
| 21 | + contents: read |
| 22 | + steps: |
| 23 | + - uses: actions/checkout@v4 |
| 24 | + with: |
| 25 | + ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} |
| 26 | + |
| 27 | + - uses: actions/setup-node@v4 |
| 28 | + with: |
| 29 | + node-version: 20.x |
| 30 | + registry-url: https://registry.npmjs.org |
| 31 | + |
| 32 | + - name: Verify credentials present |
| 33 | + env: |
| 34 | + TOKEN: ${{ secrets.SWITCHBOT_TOKEN }} |
| 35 | + SECRET: ${{ secrets.SWITCHBOT_SECRET }} |
| 36 | + run: | |
| 37 | + if [ -z "$TOKEN" ] || [ -z "$SECRET" ]; then |
| 38 | + echo "SWITCHBOT_TOKEN / SWITCHBOT_SECRET not set in repo secrets" |
| 39 | + exit 1 |
| 40 | + fi |
| 41 | +
|
| 42 | + - name: Verify npm token present |
| 43 | + env: |
| 44 | + TOKEN: ${{ secrets.NPM_TOKEN }} |
| 45 | + run: | |
| 46 | + if [ -z "$TOKEN" ]; then |
| 47 | + echo "NPM_TOKEN not set in repo secrets" |
| 48 | + exit 1 |
| 49 | + fi |
| 50 | +
|
| 51 | + - name: Resolve target version |
| 52 | + id: version |
| 53 | + run: | |
| 54 | + if [ -n "${{ inputs.version }}" ]; then |
| 55 | + VERSION="${{ inputs.version }}" |
| 56 | + else |
| 57 | + VERSION=$(node -p "require('./package.json').version") |
| 58 | + fi |
| 59 | + echo "version=$VERSION" >> "$GITHUB_OUTPUT" |
| 60 | + echo "target_version=$VERSION" |
| 61 | +
|
| 62 | + - name: Resolve current latest dist-tag |
| 63 | + id: latest |
| 64 | + run: | |
| 65 | + LATEST=$(npm view @switchbot/openapi-cli dist-tags.latest) |
| 66 | + echo "version=$LATEST" >> "$GITHUB_OUTPUT" |
| 67 | + echo "current_latest=$LATEST" |
| 68 | +
|
| 69 | + - name: Wait for npm package to become available |
| 70 | + id: wait_package |
| 71 | + env: |
| 72 | + VERSION: ${{ steps.version.outputs.version }} |
| 73 | + run: | |
| 74 | + for i in $(seq 1 24); do |
| 75 | + if [ "${{ github.event_name }}" = "workflow_run" ]; then |
| 76 | + FOUND=$(npm view "@switchbot/openapi-cli@next" version 2>/dev/null || true) |
| 77 | + if [ "$FOUND" = "$VERSION" ]; then |
| 78 | + echo "npm package is available on next: $FOUND" |
| 79 | + exit 0 |
| 80 | + fi |
| 81 | + echo "waiting for @switchbot/openapi-cli@$VERSION to appear on npm dist-tag next ($i/24); current next=$FOUND" |
| 82 | + else |
| 83 | + FOUND=$(npm view "@switchbot/openapi-cli@$VERSION" version 2>/dev/null || true) |
| 84 | + if [ "$FOUND" = "$VERSION" ]; then |
| 85 | + echo "npm package version is available: $FOUND" |
| 86 | + exit 0 |
| 87 | + fi |
| 88 | + echo "waiting for @switchbot/openapi-cli@$VERSION to appear on npm ($i/24)" |
| 89 | + fi |
| 90 | + sleep 10 |
| 91 | + done |
| 92 | + echo "Timed out waiting for @switchbot/openapi-cli@$VERSION on npm" |
| 93 | + exit 1 |
| 94 | +
|
| 95 | + - name: Install published package in a clean temp project |
| 96 | + id: install_package |
| 97 | + env: |
| 98 | + VERSION: ${{ steps.version.outputs.version }} |
| 99 | + run: | |
| 100 | + TMPDIR=$(mktemp -d) |
| 101 | + echo "TMPDIR=$TMPDIR" >> "$GITHUB_ENV" |
| 102 | + cd "$TMPDIR" |
| 103 | + npm init -y >/dev/null 2>&1 |
| 104 | + npm install "@switchbot/openapi-cli@$VERSION" |
| 105 | +
|
| 106 | + - name: Binary and offline smoke |
| 107 | + id: offline_smoke |
| 108 | + env: |
| 109 | + TMPDIR: ${{ env.TMPDIR }} |
| 110 | + VERSION: ${{ steps.version.outputs.version }} |
| 111 | + run: | |
| 112 | + cd "$TMPDIR" |
| 113 | + ACTUAL=$(npx --no-install switchbot --version) |
| 114 | + test "$ACTUAL" = "$VERSION" |
| 115 | + npx --no-install switchbot --help >/dev/null |
| 116 | + npx --no-install switchbot schema export --compact >/dev/null |
| 117 | + npx --no-install switchbot capabilities --json | jq -e '.data.commandMeta != null' >/dev/null |
| 118 | +
|
| 119 | + - name: Live smoke with configured credentials |
| 120 | + id: live_smoke |
| 121 | + env: |
| 122 | + TMPDIR: ${{ env.TMPDIR }} |
| 123 | + SWITCHBOT_TOKEN: ${{ secrets.SWITCHBOT_TOKEN }} |
| 124 | + SWITCHBOT_SECRET: ${{ secrets.SWITCHBOT_SECRET }} |
| 125 | + run: | |
| 126 | + cd "$TMPDIR" |
| 127 | + npx --no-install switchbot doctor --json | jq -e '.data.summary != null' >/dev/null |
| 128 | + npx --no-install switchbot devices list --json | jq -e '.data.deviceList != null or .data.infraredRemoteList != null' >/dev/null |
| 129 | +
|
| 130 | + - name: Promote verified version to latest |
| 131 | + if: success() |
| 132 | + env: |
| 133 | + VERSION: ${{ steps.version.outputs.version }} |
| 134 | + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
| 135 | + run: | |
| 136 | + npm dist-tag add "@switchbot/openapi-cli@$VERSION" latest |
| 137 | + echo "Promoted @switchbot/openapi-cli@$VERSION to dist-tag latest" |
| 138 | +
|
| 139 | + - name: Deprecate failed version |
| 140 | + if: > |
| 141 | + failure() && |
| 142 | + steps.wait_package.outcome == 'success' && |
| 143 | + ( |
| 144 | + steps.install_package.outcome == 'failure' || |
| 145 | + steps.offline_smoke.outcome == 'failure' |
| 146 | + ) |
| 147 | + env: |
| 148 | + VERSION: ${{ steps.version.outputs.version }} |
| 149 | + PREVIOUS_LATEST: ${{ steps.latest.outputs.version }} |
| 150 | + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
| 151 | + run: | |
| 152 | + npm deprecate "@switchbot/openapi-cli@$VERSION" "Published to dist-tag next but failed package smoke tests. Install @switchbot/openapi-cli@${PREVIOUS_LATEST} or use dist-tag latest." |
| 153 | + echo "Deprecated @switchbot/openapi-cli@$VERSION after package smoke failure" |
| 154 | +
|
| 155 | + - name: Cleanup temp project |
| 156 | + if: always() |
| 157 | + env: |
| 158 | + TMPDIR: ${{ env.TMPDIR }} |
| 159 | + run: | |
| 160 | + if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then |
| 161 | + rm -rf "$TMPDIR" |
| 162 | + fi |
0 commit comments