diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a714d89..3e909e3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -23,22 +23,23 @@ jobs: - name: Check If Tag Exists id: tag - run: echo "exists=$([[ ! -z $(git tag -l "$TAG") ]] && echo true || echo false)" >> $GITHUB_OUTPUT; + run: echo "exists=$(gh release view "$TAG" &> /dev/null && echo "true" || echo "false")" >> $GITHUB_OUTPUT; env: TAG: ${{ steps.version.outputs.version }} + GH_TOKEN: ${{ github.token }} - name: NPM Install - if: steps.tag.outputs.exists == false + if: steps.tag.outputs.exists == 'false' run: npm ci - name: Build Extension id: build_extension - if: steps.tag.outputs.exists == false + if: steps.tag.outputs.exists == 'false' run: npm run package && echo "extension_path=$(ls *.vsix)" >> $GITHUB_OUTPUT; - name: Create release on GitHub id: create_release - if: steps.tag.outputs.exists == false + if: steps.tag.outputs.exists == 'false' uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -49,7 +50,7 @@ jobs: prerelease: false - name: Upload extension as release asset to GitHub - if: steps.tag.outputs.exists == false + if: steps.tag.outputs.exists == 'false' uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -60,7 +61,7 @@ jobs: asset_content_type: application/zip - name: Publish to Marketplace - if: steps.tag.outputs.exists == false + if: steps.tag.outputs.exists == 'false' run: npm run publish env: VSCE_PAT: ${{ secrets.VSCE_PAT }} diff --git a/package-lock.json b/package-lock.json index 1d442e6..43a1233 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "doppler-vscode", - "version": "0.0.2", + "version": "0.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "doppler-vscode", - "version": "0.0.2", + "version": "0.0.3", "license": "Apache-2.0", "dependencies": { "axios": "^1.2.1", diff --git a/package.json b/package.json index c8564ae..d06e8a8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Edit your secrets where you edit your code, with 2 way sync.", "publisher": "doppler", "author": "doppler", - "version": "0.0.2", + "version": "0.0.3", "license": "Apache-2.0", "homepage": "https://github.com/dopplerhq/vscode", "icon": "media/icon.png", diff --git a/src/lib/doppler/secrets.ts b/src/lib/doppler/secrets.ts index 9f82ee9..e3eec9e 100644 --- a/src/lib/doppler/secrets.ts +++ b/src/lib/doppler/secrets.ts @@ -2,7 +2,7 @@ import DopplerAuth from "./auth"; import DopplerRequest from "./request"; export interface DopplerSecrets { - [key: string]: string; + [key: string]: string | null; } export interface DopplerSecretsUpdate { @@ -10,8 +10,8 @@ export interface DopplerSecretsUpdate { } interface DopplerSecretWithRaw { - raw: string; - computed: string; + raw: string | null; + computed: string | null; } interface DopplerSecretsWithRaw { @@ -44,7 +44,7 @@ export class DopplerSecretsProvider { public async fetchRaw(project: string, config: string): Promise { const response = await this.request.get(`/v3/configs/config/secrets`, { - params: { project, config, include_managed_secrets: false }, + params: { project, config, include_managed_secrets: false, raw_only: true }, }); const secretsWithRaw = response.secrets as DopplerSecretsWithRaw; diff --git a/src/lib/explorer/file_system_provider.ts b/src/lib/explorer/file_system_provider.ts index eb75ec8..9e81d65 100644 --- a/src/lib/explorer/file_system_provider.ts +++ b/src/lib/explorer/file_system_provider.ts @@ -1,4 +1,4 @@ -import { EventEmitter, FileSystemProvider, FileChangeEvent, Event, FileType, Uri, Disposable } from "vscode"; +import { EventEmitter, FileSystemProvider, FileChangeEvent, Event, FileType, Uri, Disposable, FileChangeType } from "vscode"; import * as yaml from "yaml"; import * as helpers from "../helpers"; import * as doppler from "../doppler"; @@ -7,6 +7,7 @@ import { TextEncoder, TextDecoder } from "util"; export default class DopplerFileSystemProvider implements FileSystemProvider { // Required part of the FileSystemProvider interface private _emitter = new EventEmitter(); + private needsRefresh = false; readonly onDidChangeFile: Event = this._emitter.event; generateYAMLMessage() { @@ -15,6 +16,9 @@ export default class DopplerFileSystemProvider implements FileSystemProvider { "This file was generated by Doppler. When you make", "changes to this file, they will be saved to your", "config in Doppler as well.", + "", + "A `null` value indicates that the secret is restricted.", + "Restricted secrets may be overwritten but cannot be read.", ]; const longestLineLength = Math.max(...lines.map((el) => el.length)) + 1; const paddingSpaces = Array(padding).join(" "); @@ -43,20 +47,31 @@ export default class DopplerFileSystemProvider implements FileSystemProvider { return `${comment}\n\n${yamlFile}`; } + async getContent(uri: Uri) { + const { project, config } = helpers.parser.fromURI(uri); + return this.jsonToYAML(await doppler.secrets.fetchRaw(project, config)); + } + async stat(uri: Uri) { - const content = await this.readFile(uri); + if (this.needsRefresh) { + setTimeout(() => { + this._emitter.fire([{ uri: uri, type: FileChangeType.Changed }]); + }, 0); + this.needsRefresh = false; + } return { type: FileType.File, - size: content.length, + // vscode will stat and readFile for each file read, it's much less expensive to report a 0-size file. + // This doesn't seem to have a significant impact otherwise. + size: 0, ctime: Date.now(), mtime: Date.now(), }; } async readFile(uri: Uri) { - const { project, config } = helpers.parser.fromURI(uri); - const content = this.jsonToYAML(await doppler.secrets.fetchRaw(project, config)); + const content = await this.getContent(uri); return new TextEncoder().encode(content); } @@ -84,6 +99,7 @@ export default class DopplerFileSystemProvider implements FileSystemProvider { if (Object.keys(changed_secrets).length > 0) { await doppler.secrets.update(project, config, changed_secrets); } + this.needsRefresh = true; } watch(uri: Uri): Disposable { diff --git a/src/lib/hover/providers.ts b/src/lib/hover/providers.ts index 243a3c6..5cbc493 100644 --- a/src/lib/hover/providers.ts +++ b/src/lib/hover/providers.ts @@ -76,7 +76,7 @@ async function hover(language: string, document: TextDocument, position: Positio const text = ["**Doppler**", `Project: ${project}`, `Config: ${config}`].join("
"); const markdown = new MarkdownString(); markdown.appendMarkdown(text); - markdown.appendCodeblock(value); + markdown.appendCodeblock(value ?? "[RESTRICTED]"); markdown.supportHtml = true; return new Hover(markdown); }