mirror of
https://github.com/foomo/sesamy-cli.git
synced 2025-10-16 12:35:36 +00:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61d671341c | ||
|
|
df04a14c25 | ||
|
|
c3a1a68c9b | ||
|
|
97ef3a7ce6 | ||
|
|
35d4393f4e | ||
|
|
fe98357ece | ||
|
|
3e6697a98d | ||
|
|
d5358405af | ||
|
|
27dff33e47 | ||
|
|
acf13a73b1 | ||
|
|
de67860229 | ||
|
|
f6539da3c0 | ||
|
|
53794ef0f8 | ||
|
|
a021b3eafd | ||
|
|
e2ce7e64fe | ||
|
|
539624ceb3 | ||
|
|
740d4981ea | ||
|
|
5fdd26d867 | ||
|
|
b1b71cc166 | ||
|
|
c6f5292df3 | ||
|
|
9df36edda0 | ||
|
|
3e03bc1226 | ||
|
|
1cfbaecfee | ||
|
|
937d05dd7e | ||
|
|
8b13d71d7a | ||
|
|
2561217100 | ||
|
|
48c093b015 | ||
|
|
203ad0bfa4 | ||
|
|
be65ea9157 | ||
|
|
7fcd2912a6 | ||
|
|
ab5bb5d07f | ||
|
|
15fc18c62c | ||
|
|
e3fa04dd0a | ||
|
|
487358ee89 | ||
|
|
9d9a7352eb | ||
|
|
f2efac7342 | ||
|
|
f93177867a | ||
|
|
7acd33aa8c | ||
|
|
9dc885eeb7 | ||
|
|
36f9e0f81c | ||
|
|
e7967d1eb2 | ||
|
|
2591b7b875 | ||
|
|
ad1fa735e0 | ||
|
|
72378c8024 | ||
|
|
408e227f92 | ||
|
|
705fe333bf | ||
|
|
5b55eb2b84 | ||
|
|
0c9bb7ea73 | ||
|
|
bc28c78ad8 | ||
|
|
0617588911 | ||
|
|
7cb97d0475 | ||
|
|
4f632d515a | ||
|
|
8569b47ed4 | ||
|
|
f3596f9f06 | ||
|
|
91f32ebf3b | ||
|
|
3e40a767da | ||
|
|
268f0c499b | ||
|
|
9826788be4 | ||
|
|
284f12171b | ||
|
|
315738f70c | ||
|
|
f1fe8c2c72 | ||
|
|
3880d503f1 | ||
|
|
898f63a1ad | ||
|
|
82d5b597f5 | ||
|
|
ea147e3865 | ||
|
|
058d2134e6 | ||
|
|
e4a99eb2d3 | ||
|
|
ac8f7298b7 | ||
|
|
7aa4f843e5 | ||
|
|
e2f259bf5c | ||
|
|
a92d456ed2 | ||
|
|
339f91085d | ||
|
|
741c6bb44e | ||
|
|
2983e5ee7d | ||
|
|
233db21350 | ||
|
|
952ca528b8 | ||
|
|
3f1cf4f092 | ||
|
|
7cdee0e36e | ||
|
|
d66e4ba2e9 | ||
|
|
a096008783 | ||
|
|
c86a7f01b1 | ||
|
|
02c118c3c5 | ||
|
|
90c63fa159 | ||
|
|
fc4349ae11 | ||
|
|
3c045e165d | ||
|
|
c17a587e7d | ||
|
|
2e6b01b08e | ||
|
|
092b49487d | ||
|
|
62465edf0d | ||
|
|
33f2863e8d | ||
|
|
3112bcc7f1 | ||
|
|
8cd029ee69 | ||
|
|
6f20c9bf96 | ||
|
|
2321cd483b | ||
|
|
09fa7bb1da | ||
|
|
98399f961d | ||
|
|
10a5197998 | ||
|
|
837b8ae069 | ||
|
|
a15d637c0c | ||
|
|
f2d17d0e47 | ||
|
|
1717f77f2f |
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
sesamy
|
||||
dist
|
||||
21
.github/CONTRIBUTING.md
vendored
Normal file
21
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Contributing
|
||||
|
||||
If you want to submit a pull request to fix a bug or enhance an existing
|
||||
feature, please first open an issue and link to that issue when you
|
||||
submit your pull request.
|
||||
|
||||
If you have any questions about a possible submission, feel free to open
|
||||
an issue too.
|
||||
|
||||
### Pull request process
|
||||
|
||||
1. Fork this repository
|
||||
2. Create a branch in your fork to implement the changes. We recommend using
|
||||
the issue number as part of your branch name, e.g. `1234-fixes`
|
||||
3. Ensure that any documentation is updated with the changes that are required
|
||||
by your fix.
|
||||
4. Ensure that any samples are updated if the base image has been changed.
|
||||
5. Submit the pull request. *Do not leave the pull request blank*. Explain exactly
|
||||
what your changes are meant to do and provide simple steps on how to validate
|
||||
your changes. Ensure that you reference the issue you created as well.
|
||||
The pull request will be review before it is merged.
|
||||
17
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Report a bug you encountered
|
||||
labels: bug
|
||||
---
|
||||
**What happened**:
|
||||
|
||||
**What you expected to happen**:
|
||||
|
||||
**How to reproduce it (as minimally and precisely as possible)**:
|
||||
|
||||
**Anything else we need to know?**:
|
||||
|
||||
**Environment**:
|
||||
- Affected Version:
|
||||
- OS (e.g: `cat /etc/os-release`):
|
||||
- Others:
|
||||
8
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
8
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
name: Enhancement Request
|
||||
about: Suggest an enhancement
|
||||
labels: enhancement
|
||||
---
|
||||
**What would you like to be added**:
|
||||
|
||||
**Why is this needed**:
|
||||
19
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
19
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
### Type of Change
|
||||
- [ ] New feature
|
||||
- [ ] Bug fix
|
||||
- [ ] Documentation update
|
||||
- [ ] Refactoring
|
||||
- [ ] Hotfix
|
||||
- [ ] Security patch
|
||||
|
||||
### Description
|
||||
_[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]_
|
||||
|
||||
### Related Issues
|
||||
_[If this pull request addresses an issue, please link to it here (e.g., Fixes #123).]_
|
||||
|
||||
### Checklist
|
||||
- [ ] My code adheres to the coding and style guidelines of the project.
|
||||
- [ ] I have performed a self-review of my own code.
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas.
|
||||
- [ ] I have made corresponding changes to the documentation.
|
||||
45
.github/SECURITY.md
vendored
Normal file
45
.github/SECURITY.md
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# Security Guidelines
|
||||
|
||||
## How security is managed on this project
|
||||
|
||||
The foomo team and community take security seriously and wants to ensure that
|
||||
we maintain a secure environment and provide secure solutions for the open
|
||||
source community. To help us achieve these goals, please note the
|
||||
following before using this software:
|
||||
|
||||
- Review the software license to understand the contributor's obligations in
|
||||
terms of warranties and suitability for purpose
|
||||
- For any questions or concerns about security, you can
|
||||
[create an issue][new-issue] or [report a vulnerability][new-sec-issue]
|
||||
- We request that you work with our security team and opt for
|
||||
responsible disclosure using the guidelines below
|
||||
- All security related issues and pull requests you make should be tagged with
|
||||
"security" for easy identification
|
||||
- Please monitor this repository and update your environment in a timely manner
|
||||
as we release patches and updates
|
||||
|
||||
## Responsibly Disclosing Security Bugs
|
||||
|
||||
If you find a security bug in this repository, please work with contributors
|
||||
following responsible disclosure principles and these guidelines:
|
||||
|
||||
- Do not submit a normal issue or pull request in our public repository, instead
|
||||
[report it directly][new-sec-issue].
|
||||
- We will review your submission and may follow up for additional details
|
||||
- If you have a patch, we will review it and approve it privately; once approved
|
||||
for release you can submit it as a pull request publicly in the repository (we
|
||||
give credit where credit is due)
|
||||
- We will keep you informed during our investigation, feel free to check in for
|
||||
a status update
|
||||
- We will release the fix and publicly disclose the issue as soon as possible,
|
||||
but want to ensure we due properly due diligence before releasing
|
||||
- Please do not publicly blog or post about the security issue until after we
|
||||
have updated the public repo so that other downstream users have an opportunity
|
||||
to patch
|
||||
|
||||
## Contact / Misc
|
||||
|
||||
If you have any questions, please reach out directly by [creating an issue][new-issue].
|
||||
|
||||
[new-issue]: https://github.com/foomo/sesamy-cli/issues/new/choose
|
||||
[new-sec-issue]: https://github.com/foomo/sesamy-cli/security/advisories/new
|
||||
13
.github/dependabot.yml
vendored
13
.github/dependabot.yml
vendored
@ -1,26 +1,33 @@
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
- package-ecosystem: 'github-actions'
|
||||
open-pull-requests-limit: 1
|
||||
directory: '/'
|
||||
schedule:
|
||||
day: 'sunday'
|
||||
interval: 'weekly'
|
||||
groups:
|
||||
github-actions:
|
||||
patterns:
|
||||
- '*'
|
||||
patterns: ['*']
|
||||
|
||||
- package-ecosystem: 'gomod'
|
||||
open-pull-requests-limit: 1
|
||||
directory: '/'
|
||||
schedule:
|
||||
day: 'sunday'
|
||||
interval: 'weekly'
|
||||
groups:
|
||||
gomod-security:
|
||||
patterns: ['*']
|
||||
applies-to: security-updates
|
||||
update-types: ['minor', 'patch']
|
||||
patterns: ['*']
|
||||
gomod-update:
|
||||
applies-to: version-updates
|
||||
update-types: ['minor', 'patch']
|
||||
patterns: ['*']
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
|
||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@ -22,15 +22,22 @@ jobs:
|
||||
check-latest: true
|
||||
go-version-file: go.mod
|
||||
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- id: app_token
|
||||
uses: tibdex/github-app-token@v2
|
||||
with:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Login to docker.io
|
||||
run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
version: latest
|
||||
version: '~> v2'
|
||||
args: release --clean
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app_token.outputs.token }}
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -7,6 +7,10 @@ on:
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}"
|
||||
cancel-in-progress: true
|
||||
@ -26,7 +30,7 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: golangci/golangci-lint-action@v6
|
||||
- uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
version: latest
|
||||
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@ -16,10 +16,18 @@
|
||||
## Editorconfig
|
||||
!.editorconfig
|
||||
|
||||
## Docker
|
||||
!.dockerignore
|
||||
|
||||
## Husky
|
||||
!.husky/
|
||||
!.husky.yaml
|
||||
|
||||
## Golang
|
||||
go.work
|
||||
go.work.sum
|
||||
!.golangci.yml
|
||||
!.goreleaser.yml
|
||||
|
||||
## Ownbrew
|
||||
!.ownbrew.yaml
|
||||
|
||||
209
.golangci.yml
209
.golangci.yml
@ -1,108 +1,13 @@
|
||||
# yaml-language-server: $schema=https://golangci-lint.run/jsonschema/golangci.jsonschema.json
|
||||
# https://golangci-lint.run/usage/configuration/
|
||||
|
||||
version: "2"
|
||||
run:
|
||||
go: 1.24.0
|
||||
go: 1.24.3
|
||||
build-tags: [safe]
|
||||
modules-download-mode: readonly
|
||||
|
||||
issues:
|
||||
exclude-dirs:
|
||||
- 'bin'
|
||||
- 'tmp'
|
||||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
|
||||
linters-settings:
|
||||
# https://golangci-lint.run/usage/linters/#misspell
|
||||
misspell:
|
||||
mode: restricted
|
||||
# https://golangci-lint.run/usage/linters/#asasalint
|
||||
asasalint:
|
||||
ignore-test: true
|
||||
# https://golangci-lint.run/usage/linters/#exhaustive
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
# https://golangci-lint.run/usage/linters/#predeclared
|
||||
predeclared:
|
||||
ignore: "new,error"
|
||||
# https://golangci-lint.run/usage/linters/#gocritic
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- commentFormatting
|
||||
# https://golangci-lint.run/usage/linters/#testifylint
|
||||
testifylint:
|
||||
disable:
|
||||
- float-compare
|
||||
# https://golangci-lint.run/usage/linters/#gosec
|
||||
gosec:
|
||||
confidence: medium
|
||||
# https://golangci-lint.run/usage/linters/#importas
|
||||
importas:
|
||||
no-unaliased: true
|
||||
# https://golangci-lint.run/usage/linters/#gomoddirectives
|
||||
gomoddirectives:
|
||||
replace-local: true
|
||||
# https://golangci-lint.run/usage/linters/#revive
|
||||
revive:
|
||||
ignore-generated-header: true
|
||||
enable-all-rules: true
|
||||
rules:
|
||||
- name: line-length-limit
|
||||
disabled: true
|
||||
- name: cognitive-complexity
|
||||
disabled: true
|
||||
- name: unused-parameter
|
||||
disabled: true
|
||||
- name: add-constant
|
||||
disabled: true
|
||||
- name: cyclomatic
|
||||
disabled: true
|
||||
- name: function-length
|
||||
disabled: true
|
||||
- name: function-result-limit
|
||||
disabled: true
|
||||
- name: flag-parameter
|
||||
disabled: true
|
||||
- name: unused-receiver
|
||||
disabled: true
|
||||
- name: argument-limit
|
||||
disabled: true
|
||||
- name: max-control-nesting
|
||||
disabled: true
|
||||
- name: comment-spacings
|
||||
disabled: true
|
||||
- name: max-public-structs
|
||||
disabled: true
|
||||
- name: struct-tag
|
||||
arguments:
|
||||
- "json,inline"
|
||||
- "yaml,squash"
|
||||
- name: unhandled-error
|
||||
arguments:
|
||||
- "fmt.Println"
|
||||
- "viper.BindPFlag"
|
||||
- "strings.Builder.WriteString"
|
||||
# TODO remove
|
||||
- name: deep-exit
|
||||
disabled: true
|
||||
- name: if-return
|
||||
disabled: true
|
||||
- name: empty-block
|
||||
disabled: true
|
||||
- name: indent-error-flow
|
||||
disabled: true
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
default: none
|
||||
enable:
|
||||
## Default linters
|
||||
- errcheck # errcheck is a program for checking for unchecked errors in Go code. These unchecked errors can be critical bugs in some cases [fast: false, auto-fix: false]
|
||||
- gosimple # (megacheck) Linter for Go source code that specializes in simplifying code [fast: false, auto-fix: false]
|
||||
- govet # (vet, vetshadow) Vet examines Go source code and reports suspicious constructs. It is roughly the same as 'go vet' and uses its passes. [fast: false, auto-fix: false]
|
||||
- ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
|
||||
- staticcheck # (megacheck) It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint. [fast: false, auto-fix: false]
|
||||
@ -131,9 +36,7 @@ linters:
|
||||
- gochecksumtype # Run exhaustiveness checks on Go "sum types" [fast: false, auto-fix: false]
|
||||
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
|
||||
- gocritic # Provides diagnostics that check for bugs, performance and style issues. [fast: false, auto-fix: true]
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
|
||||
- goheader # Checks is file header matches to pattern [fast: true, auto-fix: true]
|
||||
- goimports # Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode. [fast: true, auto-fix: true]
|
||||
- gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. [fast: true, auto-fix: false]
|
||||
- gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. [fast: true, auto-fix: false]
|
||||
- goprintffuncname # Checks that printf-like functions are named with `f` at the end. [fast: true, auto-fix: false]
|
||||
@ -166,7 +69,6 @@ linters:
|
||||
- rowserrcheck # checks whether Rows.Err of rows is checked successfully [fast: false, auto-fix: false]
|
||||
- spancheck # Checks for mistakes with OpenTelemetry/Census spans. [fast: false, auto-fix: false]
|
||||
- sqlclosecheck # Checks that sql.Rows, sql.Stmt, sqlx.NamedStmt, pgx.Query are closed. [fast: false, auto-fix: false]
|
||||
- stylecheck # Stylecheck is a replacement for golint [fast: false, auto-fix: false]
|
||||
- testableexamples # linter checks if examples are testable (have an expected output) [fast: true, auto-fix: false]
|
||||
- testifylint # Checks usage of github.com/stretchr/testify. [fast: false, auto-fix: false]
|
||||
- testpackage # linter that makes you use a separate _test package [fast: true, auto-fix: false]
|
||||
@ -188,7 +90,6 @@ linters:
|
||||
#- err113 # Go linter to check the errors handling expressions [fast: false, auto-fix: false]
|
||||
#- exhaustruct # Checks if all structure fields are initialized [fast: false, auto-fix: false]
|
||||
#- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
|
||||
#- gci # Gci controls Go package import order and makes it always deterministic. [fast: true, auto-fix: true]
|
||||
#- ginkgolinter # enforces standards of using ginkgo and gomega [fast: false, auto-fix: false]
|
||||
#- gochecknoglobals # Check that no global variables exist. [fast: false, auto-fix: false]
|
||||
#- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
|
||||
@ -196,7 +97,6 @@ linters:
|
||||
#- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
|
||||
#- godot # Check if comments end in a period [fast: true, auto-fix: true]
|
||||
#- godox # Tool for detection of comment keywords [fast: true, auto-fix: false]
|
||||
#- gofumpt # Gofumpt checks whether code was gofumpt-ed. [fast: true, auto-fix: true]
|
||||
#- interfacebloat # A linter that checks the number of methods inside an interface. [fast: true, auto-fix: false]
|
||||
#- intrange # (go >= 1.22) intrange is a linter to find places where for loops could make use of an integer range. [fast: true, auto-fix: false]
|
||||
#- ireturn # Accept Interfaces, Return Concrete Types [fast: false, auto-fix: false]
|
||||
@ -216,3 +116,106 @@ linters:
|
||||
#- wrapcheck # Checks that errors returned from external packages are wrapped [fast: false, auto-fix: false]
|
||||
#- wsl # add or remove empty lines [fast: true, auto-fix: false]
|
||||
#- zerologlint # Detects the wrong usage of `zerolog` that a user forgets to dispatch with `Send` or `Msg` [fast: false, auto-fix: false]
|
||||
settings:
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- commentFormatting
|
||||
gomoddirectives:
|
||||
replace-local: true
|
||||
gosec:
|
||||
confidence: medium
|
||||
importas:
|
||||
no-unaliased: true
|
||||
misspell:
|
||||
mode: restricted
|
||||
predeclared:
|
||||
ignore:
|
||||
- new
|
||||
- error
|
||||
revive:
|
||||
enable-all-rules: true
|
||||
rules:
|
||||
- name: line-length-limit
|
||||
disabled: true
|
||||
- name: cognitive-complexity
|
||||
disabled: true
|
||||
- name: unused-parameter
|
||||
disabled: true
|
||||
- name: add-constant
|
||||
disabled: true
|
||||
- name: cyclomatic
|
||||
disabled: true
|
||||
- name: function-length
|
||||
disabled: true
|
||||
- name: function-result-limit
|
||||
disabled: true
|
||||
- name: flag-parameter
|
||||
disabled: true
|
||||
- name: unused-receiver
|
||||
disabled: true
|
||||
- name: argument-limit
|
||||
disabled: true
|
||||
- name: max-control-nesting
|
||||
disabled: true
|
||||
- name: comment-spacings
|
||||
disabled: true
|
||||
- name: max-public-structs
|
||||
disabled: true
|
||||
- name: struct-tag
|
||||
arguments:
|
||||
- json,inline
|
||||
- yaml,squash
|
||||
- name: unhandled-error
|
||||
arguments:
|
||||
- fmt.Println
|
||||
- viper.BindPFlag
|
||||
- strings.Builder.WriteString
|
||||
- name: deep-exit
|
||||
disabled: true
|
||||
- name: if-return
|
||||
disabled: true
|
||||
- name: empty-block
|
||||
disabled: true
|
||||
- name: indent-error-flow
|
||||
disabled: true
|
||||
- name: var-naming
|
||||
disabled: true
|
||||
testifylint:
|
||||
disable:
|
||||
- float-compare
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- linters:
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
path: _test\.go
|
||||
- linters:
|
||||
- asasalint
|
||||
path: (.+)_test\.go
|
||||
paths:
|
||||
- bin
|
||||
- tmp
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- bin
|
||||
- tmp
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
@ -16,6 +16,7 @@ builds:
|
||||
- '7'
|
||||
flags:
|
||||
- -trimpath
|
||||
- -tags=safe
|
||||
ldflags:
|
||||
- -s -w -X github.com/foomo/sesamy-cli/cmd.version={{.Version}}
|
||||
|
||||
@ -23,10 +24,10 @@ release:
|
||||
prerelease: auto
|
||||
|
||||
archives:
|
||||
- format: tar.gz
|
||||
- formats: [ tar.gz ]
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
formats: [ zip ]
|
||||
|
||||
changelog:
|
||||
use: github-native
|
||||
@ -38,3 +39,76 @@ brews:
|
||||
caveats: "sesamy --help"
|
||||
homepage: "https://github.com/foomo/sesamy-cli"
|
||||
description: "CLI utitlity to manage Server Side Tag Management"
|
||||
test: |
|
||||
system "#{bin}/sesamy --version"
|
||||
|
||||
dockers:
|
||||
- use: buildx
|
||||
goos: linux
|
||||
goarch: amd64
|
||||
dockerfile: Dockerfile
|
||||
image_templates:
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:latest-amd64{{ end }}'
|
||||
- 'foomo/sesamy:{{ .Version }}-amd64'
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:{{ .Major }}-amd64{{ end }}'
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:{{ .Major }}.{{ .Minor }}-amd64{{ end }}'
|
||||
build_flag_templates:
|
||||
- '--pull'
|
||||
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
|
||||
- '--label=org.opencontainers.image.title={{.ProjectName}}'
|
||||
- '--label=org.opencontainers.image.description=CLI utility manage infrastructure as code with helm'
|
||||
- '--label=org.opencontainers.image.source={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.url={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.documentation={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.created={{.Date}}'
|
||||
- '--label=org.opencontainers.image.revision={{.FullCommit}}'
|
||||
- '--label=org.opencontainers.image.version={{.Version}}'
|
||||
- '--platform=linux/amd64'
|
||||
|
||||
- use: buildx
|
||||
goos: linux
|
||||
goarch: arm64
|
||||
dockerfile: Dockerfile
|
||||
image_templates:
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:latest-arm64{{ end }}'
|
||||
- 'foomo/sesamy:{{ .Version }}-arm64'
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:{{ .Major }}-arm64{{ end }}'
|
||||
- '{{ if eq .Prerelease "" }}foomo/sesamy:{{ .Major }}.{{ .Minor }}-arm64{{ end }}'
|
||||
build_flag_templates:
|
||||
- '--pull'
|
||||
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
|
||||
- '--label=org.opencontainers.image.title={{.ProjectName}}'
|
||||
- '--label=org.opencontainers.image.description=CLI utility manage infrastructure as code with helm'
|
||||
- '--label=org.opencontainers.image.source={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.url={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.documentation={{.GitURL}}'
|
||||
- '--label=org.opencontainers.image.created={{.Date}}'
|
||||
- '--label=org.opencontainers.image.revision={{.FullCommit}}'
|
||||
- '--label=org.opencontainers.image.version={{.Version}}'
|
||||
- '--platform=linux/arm64'
|
||||
|
||||
docker_manifests:
|
||||
# basic
|
||||
- name_template: 'foomo/sesamy:latest'
|
||||
image_templates:
|
||||
- 'foomo/sesamy:latest-amd64'
|
||||
- 'foomo/sesamy:latest-arm64'
|
||||
skip_push: auto
|
||||
|
||||
- name_template: 'foomo/sesamy:{{ .Version }}'
|
||||
image_templates:
|
||||
- 'foomo/sesamy:{{ .Version }}-amd64'
|
||||
- 'foomo/sesamy:{{ .Version }}-arm64'
|
||||
skip_push: auto
|
||||
|
||||
- name_template: 'foomo/sesamy:{{ .Major }}'
|
||||
image_templates:
|
||||
- 'foomo/sesamy:{{ .Major }}-amd64'
|
||||
- 'foomo/sesamy:{{ .Major }}-arm64'
|
||||
skip_push: auto
|
||||
|
||||
- name_template: 'foomo/sesamy:{{ .Major }}.{{ .Minor }}'
|
||||
image_templates:
|
||||
- 'foomo/sesamy:{{ .Major }}.{{ .Minor }}-amd64'
|
||||
- 'foomo/sesamy:{{ .Major }}.{{ .Minor }}-arm64'
|
||||
skip_push: auto
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
hooks:
|
||||
pre-commit:
|
||||
- golangci-lint run --fast
|
||||
- golangci-lint run --fast-only
|
||||
- husky lint-staged
|
||||
commit-msg:
|
||||
# only execute if not in a merge
|
||||
@ -8,7 +8,7 @@ hooks:
|
||||
|
||||
lint-staged:
|
||||
'*.go':
|
||||
- goimports -l -w
|
||||
- golangci-lint fmt
|
||||
|
||||
lint-commit:
|
||||
types: '^(feat|fix|build|chore|docs|perf|refactor|revert|style|test|wip)$'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/foomo/ownbrew/refs/tags/v0.1.0/ownbrew.schema.json
|
||||
version: '1.0'
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/foomo/ownbrew/refs/tags/v0.2.3/ownbrew.schema.json
|
||||
version: '1.1'
|
||||
|
||||
binDir: "bin"
|
||||
tapDir: ".ownbrew/tap"
|
||||
@ -9,7 +9,7 @@ packages:
|
||||
## https://github.com/golangci/golangci-lint/releases
|
||||
- name: golangci-lint
|
||||
tap: foomo/tap/golangci/golangci-lint
|
||||
version: 1.61.0
|
||||
version: 2.1.6
|
||||
## https://github.com/go-courier/husky/releases
|
||||
- name: husky
|
||||
tap: foomo/tap/go-courier/husky
|
||||
12
Dockerfile
Normal file
12
Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk --no-cache add ca-certificates
|
||||
|
||||
RUN adduser -D -u 1001 -g 1001 sesamy
|
||||
|
||||
COPY sesamy /usr/bin/
|
||||
|
||||
USER sesamy
|
||||
WORKDIR /home/sesamy
|
||||
|
||||
ENTRYPOINT ["sesamy"]
|
||||
73
Makefile
73
Makefile
@ -1,9 +1,6 @@
|
||||
.DEFAULT_GOAL:=help
|
||||
.DEFAULT_GOAL := help
|
||||
-include .makerc
|
||||
|
||||
# --- Config -----------------------------------------------------------------
|
||||
|
||||
export PATH := bin:$(PATH)
|
||||
PATH:=bin:$(PATH)
|
||||
|
||||
# --- Targets -----------------------------------------------------------------
|
||||
|
||||
@ -20,12 +17,7 @@ export PATH := bin:$(PATH)
|
||||
fi
|
||||
@git config core.hooksPath .husky
|
||||
|
||||
## === Tasks ===
|
||||
|
||||
.PHONY: brew
|
||||
## Install project binaries
|
||||
brew:
|
||||
@ownbrew install
|
||||
### Tasks
|
||||
|
||||
.PHONY: doc
|
||||
## Open go docs
|
||||
@ -36,7 +28,7 @@ doc:
|
||||
.PHONY: test
|
||||
## Run tests
|
||||
test:
|
||||
@GO_TEST_TAGS=-skip go test -coverprofile=coverage.out -race -json ./... | gotestfmt
|
||||
@GO_TEST_TAGS=-skip go test -tags=safe -coverprofile=coverage.out -race -json -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
|
||||
|
||||
.PHONY: lint
|
||||
## Run linter
|
||||
@ -62,48 +54,41 @@ outdated:
|
||||
## Build binary
|
||||
build:
|
||||
@mkdir -p bin
|
||||
@go build -o bin/sesamy main.go
|
||||
@echo "building: bin/sesamy"
|
||||
@go build -tags=safe -o bin/sesamy main.go
|
||||
|
||||
.PHONY: install
|
||||
## Install binary
|
||||
install:
|
||||
@go build -o ${GOPATH}/bin/sesamy main.go
|
||||
@echo "installing: ${GOPATH}/bin/sesamy"
|
||||
@go build -tags=safe -o ${GOPATH}/bin/sesamy main.go
|
||||
|
||||
.PHONY: install.debug
|
||||
## Install debug binary
|
||||
install.debug:
|
||||
@go build -gcflags "all=-N -l" -o ${GOPATH}/bin/sesamy main.go
|
||||
@go build -tags=safe -gclags="all=-N -l" -o ${GOPATH}/bin/sesamy main.go
|
||||
|
||||
## === Utils ===
|
||||
### Utils
|
||||
|
||||
.PHONY: brew
|
||||
## Install project binaries
|
||||
brew:
|
||||
@ownbrew install
|
||||
|
||||
.PHONY: help
|
||||
## Show help text
|
||||
help:
|
||||
@echo "\033[1;36mSesamy CLI\033[0m"
|
||||
@awk '{ \
|
||||
if ($$0 ~ /^.PHONY: [a-zA-Z\-\_0-9]+$$/) { \
|
||||
helpCommand = substr($$0, index($$0, ":") + 2); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^[a-zA-Z\-\_0-9.]+:/) { \
|
||||
helpCommand = substr($$0, 0, index($$0, ":")); \
|
||||
if (helpMessage) { \
|
||||
printf "\033[36m%-23s\033[0m %s\n", \
|
||||
helpCommand, helpMessage"\n"; \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
} else if ($$0 ~ /^##/) { \
|
||||
if (helpMessage) { \
|
||||
helpMessage = helpMessage"\n "substr($$0, 3); \
|
||||
} else { \
|
||||
helpMessage = substr($$0, 3); \
|
||||
} \
|
||||
} else { \
|
||||
if (helpMessage) { \
|
||||
print "\n "helpMessage"\n" \
|
||||
} \
|
||||
helpMessage = ""; \
|
||||
} \
|
||||
}' \
|
||||
$(MAKEFILE_LIST)
|
||||
if($$0 ~ /^### /){ \
|
||||
if(help) printf "\033[36m%-23s\033[0m %s\n\n", cmd, help; help=""; \
|
||||
printf "\n\033[1;36m%s\033[0m\n", substr($$0,5); \
|
||||
} else if($$0 ~ /^[a-zA-Z0-9._-]+:/){ \
|
||||
cmd = substr($$0, 1, index($$0, ":")-1); \
|
||||
if(help) printf " \033[36m%-23s\033[0m %s\n", cmd, help; help=""; \
|
||||
} else if($$0 ~ /^##/){ \
|
||||
help = help ? help "\n " substr($$0,3) : substr($$0,3); \
|
||||
} else if(help){ \
|
||||
print "\n " help "\n"; help=""; \
|
||||
} \
|
||||
}' $(MAKEFILE_LIST)
|
||||
|
||||
131
README.md
131
README.md
@ -33,7 +33,9 @@ Available Commands:
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
config Print config
|
||||
help Help about any command
|
||||
tagmanager Provision Google Tag Manager containers
|
||||
list List Google Tag Manager containers
|
||||
provision Provision Google Tag Manager containers
|
||||
tags Print out all available tags
|
||||
typescript Generate typescript events
|
||||
version Print version
|
||||
|
||||
@ -51,7 +53,7 @@ Add a `sesamy.yaml` configuration
|
||||
|
||||
```yaml
|
||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/foomo/sesamy-cli/refs/heads/main/sesamy.schema.json
|
||||
version: '1.0'
|
||||
version: '1.1'
|
||||
|
||||
# Whether to redact the visitor ip
|
||||
redactVisitorIp: true
|
||||
@ -78,16 +80,20 @@ googleTagManager:
|
||||
tagId: GTM-57BHX34G
|
||||
# The container id
|
||||
containerId: '175355532'
|
||||
# The workspace id that should be used by the api
|
||||
# (Optional) The workspace id that should be used by the api
|
||||
workspaceId: '23'
|
||||
# (Optional) The workspace name that should be used by the api
|
||||
workspace: 'Default Workspace'
|
||||
# Server container settings
|
||||
serverContainer:
|
||||
# The container tag id
|
||||
tagId: GTM-5NWPR4QW
|
||||
# The container id
|
||||
containerId: '175348980'
|
||||
# The workspace id that should be used by the api
|
||||
# (Optional) The workspace id that should be used by the api
|
||||
workspaceId: '10'
|
||||
# (Optional) The workspace name that should be used by the api
|
||||
workspace: 'Default Workspace'
|
||||
# Web container variables
|
||||
webContainerVariables:
|
||||
dataLayer:
|
||||
@ -113,10 +119,14 @@ googleTag:
|
||||
tagId: G-PZ5ELRCR31
|
||||
# Whether a page_view should be sent on initial load
|
||||
sendPageView: true
|
||||
# Optional custom server container url
|
||||
serverContainerUrl: ''
|
||||
# TypeScript settings
|
||||
typeScript:
|
||||
# Target directory for generate files
|
||||
outputPath: path/to/target
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -198,6 +208,8 @@ googleAnalytics:
|
||||
ecommerceItems: true
|
||||
# Google Tag Manager web container settings
|
||||
webContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -206,6 +218,8 @@ googleAnalytics:
|
||||
- SelectItem
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -235,10 +249,20 @@ googleAds:
|
||||
conversion:
|
||||
# Enable Google Ads Conversion
|
||||
enabled: true
|
||||
# Google Ads Conversion Tracking Label
|
||||
conversionLabel: ''
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Conversion settings map
|
||||
settings:
|
||||
add_to_cart:
|
||||
- label: ''
|
||||
- conversionId: ''
|
||||
label: ''
|
||||
purchase:
|
||||
- label: ''
|
||||
- conversionId: ''
|
||||
label: ''
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -256,6 +280,8 @@ conversionLinker:
|
||||
enabled: true
|
||||
# Consent mode name
|
||||
mode: ad_storage
|
||||
# Accept incoming linker parameters
|
||||
enableLinkerParams: true
|
||||
|
||||
# --- Umami settings
|
||||
umami:
|
||||
@ -275,6 +301,8 @@ umami:
|
||||
mode: analytics_storage
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -293,6 +321,8 @@ criteo:
|
||||
applicationId: com.foomo
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -324,6 +354,8 @@ facebook:
|
||||
# Consent mode name
|
||||
mode: ad_storage
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -352,6 +384,8 @@ emarsys:
|
||||
mode: analytics_storage
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -376,6 +410,8 @@ tracify:
|
||||
mode: analytics_storage
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Path to the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: github.com/foomo/sesamy-go/pkg/event
|
||||
@ -407,6 +443,87 @@ cookiebot:
|
||||
urlPassthrough: false
|
||||
# Enable advertiser consent mode
|
||||
advertiserConsentModeEnabled: false
|
||||
# Default Consent state
|
||||
regionSettings:
|
||||
# Region (leave blank to apply globally)
|
||||
- region: ''
|
||||
# Default consent for functionality_storage and personalization_storage
|
||||
preferences: denied
|
||||
# Default consent for analytics_storage
|
||||
statistics: denied
|
||||
# Default consent for ad_storage
|
||||
marketing: denied
|
||||
# Default consent ad_user_data
|
||||
adUserData: denied
|
||||
# Default consent ad_personalization
|
||||
adPersonalization: denied
|
||||
|
||||
# --- Mixpanel
|
||||
mixpanel:
|
||||
# Enable provider
|
||||
enabled: true
|
||||
# Project Token
|
||||
projectToken: ''
|
||||
# Google Consent settings
|
||||
googleConsent:
|
||||
# Enable consent mode
|
||||
enabled: true
|
||||
# Consent mode name
|
||||
mode: analytics_storage
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Track events
|
||||
track:
|
||||
# Directory containing the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: 'github.com/foomo/sesamy-go/pkg/event'
|
||||
types:
|
||||
- AddPaymentInfo
|
||||
- AddShippingInfo
|
||||
- AddToCart
|
||||
- BeginCheckout
|
||||
- PageView
|
||||
- Purchase
|
||||
- RemoveFromCart
|
||||
- Search
|
||||
- SelectItem
|
||||
- ViewCart
|
||||
- ViewItem
|
||||
- ViewItemList
|
||||
|
||||
# --- Pinterest
|
||||
pinterest:
|
||||
# Enable provider
|
||||
enabled: true
|
||||
# Pinterest advertiser id
|
||||
advertiserId: ''
|
||||
# Pinterest API access token
|
||||
apiAccessToken: ''
|
||||
# Enable test mode
|
||||
testModeEnabled: false
|
||||
# Google Consent settings
|
||||
googleConsent:
|
||||
# Enable consent mode
|
||||
enabled: true
|
||||
# Consent mode name
|
||||
mode: analytics_storage
|
||||
# Google Tag Manager server container settings
|
||||
serverContainer:
|
||||
# Directory containing the go.mod file
|
||||
directory: .
|
||||
# Contemplate package config for generated events
|
||||
packages:
|
||||
- path: 'github.com/foomo/sesamy-go/pkg/event'
|
||||
types:
|
||||
- AddToCart
|
||||
- GenerateLead
|
||||
- PageView
|
||||
- Purchase
|
||||
- Search
|
||||
- SignUp
|
||||
- ViewItemList
|
||||
```
|
||||
|
||||
## Caveats
|
||||
@ -415,7 +532,7 @@ You might need to increase your Google Tag Manager API quotas, since they are li
|
||||
|
||||
## How to Contribute
|
||||
|
||||
Make a pull request...
|
||||
Please refer to the [CONTRIBUTING](.github/CONTRIBUTING.md) details and follow the [CODE_OF_CONDUCT](.github/CODE_OF_CONDUCT.md) and [SECURITY](.github/SECURITY.md) guidelines.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -1,34 +1,49 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/chroma/quick"
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/itchyny/json2yaml"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func NewConfig(root *cobra.Command) {
|
||||
func NewConfig(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Print config",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l := pkgcmd.Logger()
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to marshal config")
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
return nil
|
||||
var buf bytes.Buffer
|
||||
if err := json2yaml.Convert(&buf, bytes.NewBuffer(out)); err != nil {
|
||||
return errors.Wrap(err, "failed to convert config")
|
||||
}
|
||||
|
||||
return quick.Highlight(os.Stdout, buf.String(), "yaml", "terminal", "monokai")
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
23
cmd/diff.go
Normal file
23
cmd/diff.go
Normal file
@ -0,0 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/cmd/diff"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewDiff represents the diff command
|
||||
func NewDiff(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "diff",
|
||||
Short: "Print Google Tag Manager container status diff",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
diff.NewWeb(l),
|
||||
diff.NewServer(l),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
400
cmd/diff/diff.go
Normal file
400
cmd/diff/diff.go
Normal file
@ -0,0 +1,400 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/itchyny/json2yaml"
|
||||
"github.com/sters/yaml-diff/yamldiff"
|
||||
)
|
||||
|
||||
const ChangeStatusDeleted = "deleted"
|
||||
|
||||
func diff(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager) (string, error) {
|
||||
l.Info("└ ⬇︎ Loading status")
|
||||
s, err := tm.Service().Accounts.Containers.Workspaces.GetStatus(tm.WorkspacePath()).Context(ctx).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if len(s.WorkspaceChange) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
l.Info("└ ⬇︎ Loading live version")
|
||||
live, err := tm.Service().Accounts.Containers.Versions.Live(tm.ContainerPath()).Do()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var res []string
|
||||
for _, entity := range s.WorkspaceChange {
|
||||
switch {
|
||||
case entity.Tag != nil:
|
||||
res = append(res, " # Tag: "+entity.Tag.Name+" ("+entity.ChangeStatus+")\n")
|
||||
|
||||
// unset props
|
||||
entity.Tag.Path = ""
|
||||
entity.Tag.Fingerprint = ""
|
||||
entity.Tag.WorkspaceId = ""
|
||||
entity.Tag.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Tag)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Tag {
|
||||
if value.Name == entity.Tag.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Folder != nil:
|
||||
res = append(res, " # Folder: "+entity.Folder.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Folder.Path = ""
|
||||
entity.Folder.Fingerprint = ""
|
||||
entity.Folder.WorkspaceId = ""
|
||||
entity.Folder.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Folder)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Folder {
|
||||
if value.Name == entity.Folder.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Trigger != nil:
|
||||
res = append(res, " # Trigger: "+entity.Trigger.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Trigger.Path = ""
|
||||
entity.Trigger.Fingerprint = ""
|
||||
entity.Trigger.WorkspaceId = ""
|
||||
entity.Trigger.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Trigger)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Trigger {
|
||||
if value.Name == entity.Trigger.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Variable != nil:
|
||||
res = append(res, " # Variable: "+entity.Variable.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Variable.Path = ""
|
||||
entity.Variable.Fingerprint = ""
|
||||
entity.Variable.WorkspaceId = ""
|
||||
entity.Variable.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Variable)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Variable {
|
||||
if value.Name == entity.Variable.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Client != nil:
|
||||
res = append(res, " # Client: "+entity.Client.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Client.Path = ""
|
||||
entity.Client.Fingerprint = ""
|
||||
entity.Client.WorkspaceId = ""
|
||||
entity.Client.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Client)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Client {
|
||||
if value.Name == entity.Client.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.GtagConfig != nil:
|
||||
res = append(res, " # GtagConfig: "+entity.GtagConfig.AccountId+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.GtagConfig.Path = ""
|
||||
entity.GtagConfig.Fingerprint = ""
|
||||
entity.GtagConfig.WorkspaceId = ""
|
||||
entity.GtagConfig.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.GtagConfig)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.GtagConfig {
|
||||
if value.AccountId == entity.GtagConfig.AccountId {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.BuiltInVariable != nil:
|
||||
res = append(res, " # BuiltInVariable: "+entity.BuiltInVariable.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.BuiltInVariable.Path = ""
|
||||
entity.BuiltInVariable.WorkspaceId = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.BuiltInVariable)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.BuiltInVariable {
|
||||
if value.Name == entity.BuiltInVariable.Name {
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.CustomTemplate != nil:
|
||||
res = append(res, " # CustomTemplate: "+entity.CustomTemplate.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.CustomTemplate.Path = ""
|
||||
entity.CustomTemplate.Fingerprint = ""
|
||||
entity.CustomTemplate.WorkspaceId = ""
|
||||
entity.CustomTemplate.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.CustomTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.CustomTemplate {
|
||||
if value.Name == entity.CustomTemplate.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
case entity.Transformation != nil:
|
||||
res = append(res, " # Transformation: "+entity.Transformation.Name+" ("+entity.ChangeStatus+")")
|
||||
|
||||
// unset props
|
||||
entity.Transformation.Path = ""
|
||||
entity.Transformation.Fingerprint = ""
|
||||
entity.Transformation.WorkspaceId = ""
|
||||
entity.Transformation.TagManagerUrl = ""
|
||||
|
||||
var changed string
|
||||
if entity.ChangeStatus != ChangeStatusDeleted {
|
||||
changed, err = ToYalm(entity.Transformation)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var original string
|
||||
for _, value := range live.Transformation {
|
||||
if value.Name == entity.Transformation.Name {
|
||||
// unset props
|
||||
value.Fingerprint = ""
|
||||
|
||||
original, err = ToYalm(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d, err := ToDiff(original, changed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
res = append(res, d...)
|
||||
default:
|
||||
l.Warn("unknown entity type", "entity", entity)
|
||||
}
|
||||
}
|
||||
return strings.Join(res, " ---\n"), nil
|
||||
}
|
||||
|
||||
type Marshelable interface {
|
||||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
func ToDiff(original, changed string) ([]string, error) {
|
||||
yamls1, err := yamldiff.Load(original)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
yamls2, err := yamldiff.Load(changed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ret []string
|
||||
for _, d := range yamldiff.Do(yamls1, yamls2) {
|
||||
if value := d.Dump(); len(value) > 4 {
|
||||
ret = append(ret, value)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func ToYalm(m Marshelable) (string, error) {
|
||||
if m == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
out, err := m.MarshalJSON()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var ret bytes.Buffer
|
||||
if err := json2yaml.Convert(&ret, bytes.NewBuffer(out)); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ret.String(), nil
|
||||
}
|
||||
68
cmd/diff/server.go
Normal file
68
cmd/diff/server.go
Normal file
@ -0,0 +1,68 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewServer represents the server command
|
||||
func NewServer(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Print Google Tag Manager Server Container status diff",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l.Info("☕ Retrieving Server Container status")
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tm, err := tagmanager.New(
|
||||
cmd.Context(),
|
||||
l,
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.ServerContainer,
|
||||
tagmanager.WithRequestQuota(cfg.GoogleAPI.RequestQuota),
|
||||
tagmanager.WithClientOptions(cfg.GoogleAPI.GetClientOption()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := diff(cmd.Context(), l, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
68
cmd/diff/web.go
Normal file
68
cmd/diff/web.go
Normal file
@ -0,0 +1,68 @@
|
||||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewWeb represents the web command
|
||||
func NewWeb(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "web",
|
||||
Short: "Print Google Tag Manager Web Container status diff",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l.Info("☕ Retrieving Web Container status")
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tm, err := tagmanager.New(
|
||||
cmd.Context(),
|
||||
l,
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.WebContainer,
|
||||
tagmanager.WithRequestQuota(cfg.GoogleAPI.RequestQuota),
|
||||
tagmanager.WithClientOptions(cfg.GoogleAPI.GetClientOption()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := diff(cmd.Context(), l, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
11
cmd/list.go
11
cmd/list.go
@ -1,20 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/cmd/list"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewList represents the list command
|
||||
func NewList(root *cobra.Command) *cobra.Command {
|
||||
func NewList(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List Google Tag Manager containers",
|
||||
}
|
||||
|
||||
list.NewServer(cmd)
|
||||
list.NewWeb(cmd)
|
||||
root.AddCommand(cmd)
|
||||
cmd.AddCommand(
|
||||
list.NewWeb(l),
|
||||
list.NewServer(l),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -2,71 +2,69 @@ package list
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/chroma/quick"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/itchyny/json2yaml"
|
||||
)
|
||||
|
||||
func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) error {
|
||||
func dump(i interface{ MarshalJSON() ([]byte, error) }, err error) (string, error) {
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
out, err := i.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
// if err := json.Indent(ret, out, "", " "); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// fmt.Println(ret.String())
|
||||
|
||||
var output strings.Builder
|
||||
if err := json2yaml.Convert(&output, bytes.NewBuffer(out)); err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
// fmt.Print(output.String())
|
||||
return quick.Highlight(os.Stdout, output.String(), "yaml", "terminal", "monokai")
|
||||
return output.String(), nil
|
||||
}
|
||||
|
||||
func list(l *slog.Logger, tm *tagmanager.TagManager, resource string) error {
|
||||
func list(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, resource string) (string, error) {
|
||||
switch resource {
|
||||
case "status":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.GetStatus(tm.WorkspacePath()).Do())
|
||||
case "environments":
|
||||
return dump(tm.Service().Accounts.Containers.Environments.List(tm.ContainerPath()).Context(ctx).Do())
|
||||
case "workspaces":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.List(tm.ContainerPath()).Context(ctx).Do())
|
||||
case "clients":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Clients.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Clients.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "tags":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Tags.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Tags.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "built-in-variables":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.BuiltInVariables.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.BuiltInVariables.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "folders":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Folders.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Folders.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "variables":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Variables.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Variables.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "templates":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Templates.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Templates.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "templates-data":
|
||||
r, err := tm.Service().Accounts.Containers.Workspaces.Templates.List(tm.WorkspacePath()).Do()
|
||||
r, err := tm.Service().Accounts.Containers.Workspaces.Templates.List(tm.WorkspacePath()).Context(ctx).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
var ret strings.Builder
|
||||
for _, template := range r.Template {
|
||||
l.Info("---- Template data: " + template.Name + " ----------------------")
|
||||
fmt.Println(template.TemplateData)
|
||||
ret.WriteString("---- Template data: " + template.Name + " ----------------------\n")
|
||||
ret.WriteString(template.TemplateData + "\n")
|
||||
}
|
||||
return nil
|
||||
return ret.String(), nil
|
||||
case "gtag-config":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.GtagConfig.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.GtagConfig.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "triggers":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Triggers.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Triggers.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "transformations":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Transformations.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Transformations.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
case "zones":
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Zones.List(tm.WorkspacePath()).Do())
|
||||
return dump(tm.Service().Accounts.Containers.Workspaces.Zones.List(tm.WorkspacePath()).Context(ctx).Do())
|
||||
default:
|
||||
return fmt.Errorf("unknown resource %s", resource)
|
||||
return "", fmt.Errorf("unknown resource %s", resource)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewServer represents the server command
|
||||
func NewServer(root *cobra.Command) {
|
||||
func NewServer(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "List Google Tag Manager Server Container",
|
||||
@ -15,6 +22,7 @@ func NewServer(root *cobra.Command) {
|
||||
ValidArgs: []cobra.Completion{
|
||||
"built-in-variables",
|
||||
"clients",
|
||||
"environments",
|
||||
"folders",
|
||||
"gtag-config",
|
||||
"status",
|
||||
@ -24,14 +32,14 @@ func NewServer(root *cobra.Command) {
|
||||
"transformations",
|
||||
"triggers",
|
||||
"variables",
|
||||
"workspaces",
|
||||
"zones",
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
resource := args[0]
|
||||
l := pkgcmd.Logger()
|
||||
l.Info("☕ Listing Server Container resources: " + resource)
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -48,9 +56,30 @@ func NewServer(root *cobra.Command) {
|
||||
return err
|
||||
}
|
||||
|
||||
return list(l, tm, resource)
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := list(cmd.Context(), l, tm, resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -1,19 +1,27 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewWeb represents the web command
|
||||
func NewWeb(root *cobra.Command) {
|
||||
func NewWeb(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "web",
|
||||
Short: "List Google Tag Manager Web Container",
|
||||
Args: cobra.OnlyValidArgs,
|
||||
ValidArgs: []cobra.Completion{
|
||||
"built-in-variables",
|
||||
"environments",
|
||||
"folders",
|
||||
"gtag-config",
|
||||
"status",
|
||||
@ -23,14 +31,14 @@ func NewWeb(root *cobra.Command) {
|
||||
"transformations",
|
||||
"triggers",
|
||||
"variables",
|
||||
"workspaces",
|
||||
"zones",
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
resource := args[0]
|
||||
l := pkgcmd.Logger()
|
||||
l.Info("☕ Listing Web Container resources: " + resource)
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -47,9 +55,30 @@ func NewWeb(root *cobra.Command) {
|
||||
return err
|
||||
}
|
||||
|
||||
return list(l, tm, resource)
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := list(cmd.Context(), l, tm, resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.GetBool("raw") {
|
||||
out = utils.Highlight(out)
|
||||
}
|
||||
_, err = fmt.Println(out)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.Bool("raw", false, "print raw output")
|
||||
_ = c.BindPFlag("raw", flags.Lookup("raw"))
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
71
cmd/open.go
Normal file
71
cmd/open.go
Normal file
@ -0,0 +1,71 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewOpen represents the open command
|
||||
func NewOpen(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "open",
|
||||
Short: "Open links in the browser",
|
||||
Args: cobra.OnlyValidArgs,
|
||||
ValidArgs: []cobra.Completion{
|
||||
"ga",
|
||||
"gtm-web",
|
||||
"gtm-server",
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var url string
|
||||
switch args[0] {
|
||||
case "ga":
|
||||
if cfg.GoogleAnalytics.PropertyID == "" {
|
||||
return errors.New("missing Google Analytics Property ID")
|
||||
}
|
||||
url = fmt.Sprintf(
|
||||
"https://analytics.google.com/analytics/web/#/p%s/",
|
||||
cfg.GoogleAnalytics.PropertyID,
|
||||
)
|
||||
case "gtm-web":
|
||||
url = fmt.Sprintf(
|
||||
"https://tagmanager.google.com/#/container/accounts/%s/containers/%s/",
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.WebContainer.ContainerID,
|
||||
)
|
||||
case "gtm-server":
|
||||
url = fmt.Sprintf(
|
||||
"https://tagmanager.google.com/#/container/accounts/%s/containers/%s/",
|
||||
cfg.GoogleTagManager.AccountID,
|
||||
cfg.GoogleTagManager.ServerContainer.ContainerID,
|
||||
)
|
||||
default:
|
||||
return fmt.Errorf("invalid container type: %s", args[0])
|
||||
}
|
||||
|
||||
l.Info("↗ Navigating to Google Tag Manager Container: " + url)
|
||||
|
||||
return browser.OpenURL(url)
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
@ -1,20 +1,23 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/cmd/provision"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewProvision represents the provision command
|
||||
func NewProvision(root *cobra.Command) *cobra.Command {
|
||||
func NewProvision(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "provision",
|
||||
Short: "Provision Google Tag Manager containers",
|
||||
}
|
||||
|
||||
provision.NewServer(cmd)
|
||||
provision.NewWeb(cmd)
|
||||
root.AddCommand(cmd)
|
||||
cmd.AddCommand(
|
||||
provision.NewServer(l),
|
||||
provision.NewWeb(l),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package provision
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
conversionlinkerprovider "github.com/foomo/sesamy-cli/pkg/provider/conversionlinker"
|
||||
criteoprovider "github.com/foomo/sesamy-cli/pkg/provider/criteo"
|
||||
@ -11,9 +13,13 @@ import (
|
||||
googletagprovider "github.com/foomo/sesamy-cli/pkg/provider/googletag"
|
||||
googletagmanagerprovider "github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
|
||||
microsoftadsprovider "github.com/foomo/sesamy-cli/pkg/provider/microsoftads"
|
||||
mixpanelprovider "github.com/foomo/sesamy-cli/pkg/provider/mixpanel"
|
||||
pinterestprovider "github.com/foomo/sesamy-cli/pkg/provider/pinterest"
|
||||
tracifyprovider "github.com/foomo/sesamy-cli/pkg/provider/tracify"
|
||||
umamiprovider "github.com/foomo/sesamy-cli/pkg/provider/umami"
|
||||
ptermx "github.com/foomo/sesamy-cli/pkg/pterm"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
@ -21,12 +27,14 @@ import (
|
||||
)
|
||||
|
||||
// NewServer represents the server command
|
||||
func NewServer(root *cobra.Command) {
|
||||
func NewServer(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Provision Google Tag Manager Server Container",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l := pkgcmd.Logger()
|
||||
l := pkgcmd.NewLogger()
|
||||
l.Info("☕ Provisioning Server Container")
|
||||
|
||||
tags, err := cmd.Flags().GetStringSlice("tags")
|
||||
@ -34,7 +42,7 @@ func NewServer(root *cobra.Command) {
|
||||
return errors.Wrap(err, "error reading tags flag")
|
||||
}
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -51,81 +59,99 @@ func NewServer(root *cobra.Command) {
|
||||
return err
|
||||
}
|
||||
|
||||
if pkgcmd.Tag(googletagprovider.Tag, tags) {
|
||||
if err := googletagprovider.Server(tm, cfg.GoogleTag); err != nil {
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if utils.Tag(googletagprovider.Tag, tags) {
|
||||
if err := googletagprovider.Server(cmd.Context(), tm, cfg.GoogleTag); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google tag provider")
|
||||
}
|
||||
}
|
||||
|
||||
if pkgcmd.Tag(googletagmanagerprovider.Tag, tags) {
|
||||
if err := googletagmanagerprovider.Server(tm, cfg.GoogleTagManager, cfg.EnableGeoResolution); err != nil {
|
||||
if utils.Tag(googletagmanagerprovider.Tag, tags) {
|
||||
if err := googletagmanagerprovider.Server(cmd.Context(), tm, cfg.GoogleTagManager, cfg.EnableGeoResolution); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google tag manager")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.GoogleAnalytics.Enabled && pkgcmd.Tag(googleanalyticsprovider.Tag, tags) {
|
||||
if cfg.GoogleAnalytics.Enabled && utils.Tag(googleanalyticsprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", googleanalyticsprovider.Name, "tag", googleanalyticsprovider.Tag)
|
||||
if err := googleanalyticsprovider.Server(tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP, cfg.EnableGeoResolution); err != nil {
|
||||
if err := googleanalyticsprovider.Server(cmd.Context(), tm, cfg.GoogleAnalytics, cfg.RedactVisitorIP, cfg.EnableGeoResolution); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google analytics")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.ConversionLinker.Enabled && pkgcmd.Tag(conversionlinkerprovider.Tag, tags) {
|
||||
if cfg.ConversionLinker.Enabled && utils.Tag(conversionlinkerprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", conversionlinkerprovider.Name, "tag", conversionlinkerprovider.Tag)
|
||||
if err := conversionlinkerprovider.Server(tm, cfg.ConversionLinker); err != nil {
|
||||
if err := conversionlinkerprovider.Server(cmd.Context(), tm, cfg.ConversionLinker); err != nil {
|
||||
return errors.Wrap(err, "failed to provision conversion linker")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Umami.Enabled && pkgcmd.Tag(umamiprovider.Tag, tags) {
|
||||
if cfg.Umami.Enabled && utils.Tag(umamiprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", umamiprovider.Name, "tag", umamiprovider.Tag)
|
||||
if err := umamiprovider.Server(tm, cfg.Umami); err != nil {
|
||||
if err := umamiprovider.Server(cmd.Context(), tm, cfg.Umami); err != nil {
|
||||
return errors.Wrap(err, "failed to provision umami")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Facebook.Enabled && pkgcmd.Tag(facebookprovider.Tag, tags) {
|
||||
if cfg.Facebook.Enabled && utils.Tag(facebookprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", facebookprovider.Name, "tag", facebookprovider.Tag)
|
||||
if err := facebookprovider.Server(l, tm, cfg.Facebook); err != nil {
|
||||
if err := facebookprovider.Server(cmd.Context(), l, tm, cfg.Facebook); err != nil {
|
||||
return errors.Wrap(err, "failed to provision facebook")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.GoogleAds.Enabled && pkgcmd.Tag(googleadsprovider.Tag, tags) {
|
||||
if cfg.GoogleAds.Enabled && utils.Tag(googleadsprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", googleadsprovider.Name, "tag", googleadsprovider.Tag)
|
||||
if err := googleadsprovider.Server(l, tm, cfg.GoogleAds); err != nil {
|
||||
if err := googleadsprovider.Server(cmd.Context(), l, tm, cfg.GoogleAds); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google ads")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Emarsys.Enabled && pkgcmd.Tag(emarsysprovider.Tag, tags) {
|
||||
if cfg.Emarsys.Enabled && utils.Tag(emarsysprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", emarsysprovider.Name, "tag", emarsysprovider.Tag)
|
||||
if err := emarsysprovider.Server(l, tm, cfg.Emarsys); err != nil {
|
||||
if err := emarsysprovider.Server(cmd.Context(), l, tm, cfg.Emarsys); err != nil {
|
||||
return errors.Wrap(err, "failed to provision emarsys")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Tracify.Enabled && pkgcmd.Tag(tracifyprovider.Tag, tags) {
|
||||
if cfg.Tracify.Enabled && utils.Tag(tracifyprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", tracifyprovider.Name, "tag", tracifyprovider.Tag)
|
||||
if err := tracifyprovider.Server(l, tm, cfg.Tracify); err != nil {
|
||||
if err := tracifyprovider.Server(cmd.Context(), l, tm, cfg.Tracify); err != nil {
|
||||
return errors.Wrap(err, "failed to provision tracify")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Criteo.Enabled && pkgcmd.Tag(criteoprovider.Tag, tags) {
|
||||
if cfg.Criteo.Enabled && utils.Tag(criteoprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", criteoprovider.Name, "tag", criteoprovider.Tag)
|
||||
if err := criteoprovider.Server(l, tm, cfg.Criteo); err != nil {
|
||||
if err := criteoprovider.Server(cmd.Context(), l, tm, cfg.Criteo); err != nil {
|
||||
return errors.Wrap(err, "failed to provision criteo")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.MicrosoftAds.Enabled && pkgcmd.Tag(microsoftadsprovider.Tag, tags) {
|
||||
if cfg.MicrosoftAds.Enabled && utils.Tag(microsoftadsprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", microsoftadsprovider.Name, "tag", microsoftadsprovider.Tag)
|
||||
if err := microsoftadsprovider.Server(l, tm, cfg.MicrosoftAds); err != nil {
|
||||
if err := microsoftadsprovider.Server(cmd.Context(), l, tm, cfg.MicrosoftAds); err != nil {
|
||||
return errors.Wrap(err, "failed to provision microsoftads")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Mixpanel.Enabled && utils.Tag(mixpanelprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", mixpanelprovider.Name, "tag", mixpanelprovider.Tag)
|
||||
if err := mixpanelprovider.Server(cmd.Context(), l, tm, cfg.Mixpanel); err != nil {
|
||||
return errors.Wrap(err, "failed to provision mixpanel")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Pinterest.Enabled && utils.Tag(pinterestprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", pinterestprovider.Name, "tag", pinterestprovider.Tag)
|
||||
if err := pinterestprovider.Server(cmd.Context(), l, tm, cfg.Pinterest); err != nil {
|
||||
return errors.Wrap(err, "failed to provision mixpanel")
|
||||
}
|
||||
}
|
||||
|
||||
if missed := tm.Missed(); len(tags) == 0 && len(missed) > 0 {
|
||||
tree := pterm.TreeNode{
|
||||
Text: "♻️ Missed resources (potentially garbage)",
|
||||
@ -139,7 +165,8 @@ func NewServer(root *cobra.Command) {
|
||||
}
|
||||
tree.Children = append(tree.Children, child)
|
||||
}
|
||||
if err := pterm.DefaultTree.WithRoot(tree).Render(); err != nil {
|
||||
|
||||
if err := pterm.DefaultTree.WithRoot(tree).WithWriter(ptermx.NewWriter(pterm.Warning)).Render(); err != nil {
|
||||
l.Warn("failed to render missed resources", "error", err)
|
||||
}
|
||||
}
|
||||
@ -148,8 +175,13 @@ func NewServer(root *cobra.Command) {
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSlice("tags", nil, "list of tags to provision")
|
||||
_ = viper.BindPFlag("tags", cmd.Flags().Lookup("tags"))
|
||||
flags := cmd.Flags()
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
flags.StringSlice("tags", nil, "list of tags to provision")
|
||||
_ = c.BindPFlag("tags", flags.Lookup("tags"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package provision
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
cookiebotprovider "github.com/foomo/sesamy-cli/pkg/provider/cookiebot"
|
||||
criteoprovider "github.com/foomo/sesamy-cli/pkg/provider/criteo"
|
||||
@ -9,7 +11,9 @@ import (
|
||||
googletagprovider "github.com/foomo/sesamy-cli/pkg/provider/googletag"
|
||||
googletagmanagerprovider "github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
|
||||
hotjarprovider "github.com/foomo/sesamy-cli/pkg/provider/hotjar"
|
||||
ptermx "github.com/foomo/sesamy-cli/pkg/pterm"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
@ -17,12 +21,14 @@ import (
|
||||
)
|
||||
|
||||
// NewWeb represents the web command
|
||||
func NewWeb(root *cobra.Command) {
|
||||
func NewWeb(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "web",
|
||||
Short: "Provision Google Tag Manager Web Container",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l := pkgcmd.Logger()
|
||||
l := pkgcmd.NewLogger()
|
||||
l.Info("☕ Provisioning Web Container")
|
||||
|
||||
tags, err := cmd.Flags().GetStringSlice("tags")
|
||||
@ -30,7 +36,7 @@ func NewWeb(root *cobra.Command) {
|
||||
return errors.Wrap(err, "error reading tags flag")
|
||||
}
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -47,50 +53,54 @@ func NewWeb(root *cobra.Command) {
|
||||
return err
|
||||
}
|
||||
|
||||
if pkgcmd.Tag(googletagprovider.Tag, tags) {
|
||||
if err := tm.EnsureWorkspaceID(cmd.Context()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if utils.Tag(googletagprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", googletagprovider.Name, "tag", googletagprovider.Tag)
|
||||
if err := googletagprovider.Web(tm, cfg.GoogleTag); err != nil {
|
||||
if err := googletagprovider.Web(cmd.Context(), tm, cfg.GoogleTag); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google tag provider")
|
||||
}
|
||||
}
|
||||
|
||||
if pkgcmd.Tag(googletagmanagerprovider.Tag, tags) {
|
||||
if err := googletagmanagerprovider.Web(tm, cfg.GoogleTagManager); err != nil {
|
||||
if utils.Tag(googletagmanagerprovider.Tag, tags) {
|
||||
if err := googletagmanagerprovider.Web(cmd.Context(), tm, cfg.GoogleTagManager); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google tag manager")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.GoogleAnalytics.Enabled && pkgcmd.Tag(googleanaylticsprovider.Tag, tags) {
|
||||
if cfg.GoogleAnalytics.Enabled && utils.Tag(googleanaylticsprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", googleanaylticsprovider.Name, "tag", googleanaylticsprovider.Tag)
|
||||
if err := googleanaylticsprovider.Web(tm, cfg.GoogleAnalytics); err != nil {
|
||||
if err := googleanaylticsprovider.Web(cmd.Context(), tm, cfg.GoogleAnalytics); err != nil {
|
||||
return errors.Wrap(err, "failed to provision google analytics provider")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Emarsys.Enabled && pkgcmd.Tag(emarsysprovider.Tag, tags) {
|
||||
if cfg.Emarsys.Enabled && utils.Tag(emarsysprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", emarsysprovider.Name, "tag", emarsysprovider.Tag)
|
||||
if err := emarsysprovider.Web(tm, cfg.Emarsys); err != nil {
|
||||
if err := emarsysprovider.Web(cmd.Context(), tm, cfg.Emarsys); err != nil {
|
||||
return errors.Wrap(err, "failed to provision emarsys provider")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Hotjar.Enabled && pkgcmd.Tag(hotjarprovider.Tag, tags) {
|
||||
if cfg.Hotjar.Enabled && utils.Tag(hotjarprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", hotjarprovider.Name, "tag", hotjarprovider.Tag)
|
||||
if err := hotjarprovider.Web(tm, cfg.Hotjar); err != nil {
|
||||
if err := hotjarprovider.Web(cmd.Context(), tm, cfg.Hotjar); err != nil {
|
||||
return errors.Wrap(err, "failed to provision hotjar provider")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Criteo.Enabled && pkgcmd.Tag(criteoprovider.Tag, tags) {
|
||||
if cfg.Criteo.Enabled && utils.Tag(criteoprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", criteoprovider.Name, "tag", criteoprovider.Tag)
|
||||
if err := criteoprovider.Web(l, tm, cfg.Criteo); err != nil {
|
||||
if err := criteoprovider.Web(cmd.Context(), l, tm, cfg.Criteo); err != nil {
|
||||
return errors.Wrap(err, "failed to provision criteo provider")
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.Cookiebot.Enabled && pkgcmd.Tag(cookiebotprovider.Tag, tags) {
|
||||
if cfg.Cookiebot.Enabled && utils.Tag(cookiebotprovider.Tag, tags) {
|
||||
l.Info("🅿️ Running provider", "name", cookiebotprovider.Name, "tag", cookiebotprovider.Tag)
|
||||
if err := cookiebotprovider.Web(tm, cfg.Cookiebot); err != nil {
|
||||
if err := cookiebotprovider.Web(cmd.Context(), tm, cfg.Cookiebot); err != nil {
|
||||
return errors.Wrap(err, "failed to provision cookiebot provider")
|
||||
}
|
||||
}
|
||||
@ -108,7 +118,7 @@ func NewWeb(root *cobra.Command) {
|
||||
}
|
||||
tree.Children = append(tree.Children, child)
|
||||
}
|
||||
if err := pterm.DefaultTree.WithRoot(tree).Render(); err != nil {
|
||||
if err := pterm.DefaultTree.WithRoot(tree).WithWriter(ptermx.NewWriter(pterm.Warning)).Render(); err != nil {
|
||||
l.Warn("failed to render missed resources", "error", err)
|
||||
}
|
||||
}
|
||||
@ -117,8 +127,13 @@ func NewWeb(root *cobra.Command) {
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringSlice("tags", nil, "list of tags to provision")
|
||||
_ = viper.BindPFlag("tags", cmd.Flags().Lookup("tags"))
|
||||
flags := cmd.Flags()
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
flags.StringSlice("tags", nil, "list of tags to provision")
|
||||
_ = c.BindPFlag("tags", flags.Lookup("tags"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
51
cmd/root.go
51
cmd/root.go
@ -1,44 +1,31 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"log/slog"
|
||||
|
||||
pkgcmd "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var root *cobra.Command
|
||||
|
||||
func init() {
|
||||
root = NewRoot()
|
||||
NewConfig(root)
|
||||
NewVersion(root)
|
||||
NewTags(root)
|
||||
NewList(root)
|
||||
NewProvision(root)
|
||||
NewTypeScript(root)
|
||||
cobra.OnInitialize(pkgcmd.InitConfig)
|
||||
}
|
||||
|
||||
// NewRoot represents the base command when called without any subcommands
|
||||
func NewRoot() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "sesamy",
|
||||
Short: "Server Side Tag Management System",
|
||||
}
|
||||
cmd.PersistentFlags().BoolP("verbose", "v", false, "output debug information")
|
||||
_ = viper.BindPFlag("verbose", cmd.PersistentFlags().Lookup("verbose"))
|
||||
func NewRoot(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "sesamy",
|
||||
Short: "Server Side Tag Management System",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
||||
pterm.PrintDebugMessages = viper.GetBool("verbose")
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.PersistentFlags()
|
||||
|
||||
flags.BoolP("verbose", "v", false, "output debug information")
|
||||
_ = c.BindPFlag("verbose", flags.Lookup("verbose"))
|
||||
|
||||
cmd.PersistentFlags().StringP("config", "c", "sesamy.yaml", "config file (default is sesamy.yaml)")
|
||||
_ = viper.BindPFlag("config", cmd.PersistentFlags().Lookup("config"))
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := root.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
50
cmd/tags.go
50
cmd/tags.go
@ -1,6 +1,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/conversionlinker"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/cookiebot"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/criteo"
|
||||
@ -13,6 +17,8 @@ import (
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/hotjar"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/microsoftads"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/mixpanel"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/pinterest"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/tracify"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/umami"
|
||||
"github.com/pterm/pterm"
|
||||
@ -20,35 +26,37 @@ import (
|
||||
)
|
||||
|
||||
// NewTags represents the tags command
|
||||
func NewTags(root *cobra.Command) *cobra.Command {
|
||||
func NewTags(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "tags",
|
||||
Short: "Print out all available tags",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Define the data for the first table
|
||||
data := pterm.TableData{
|
||||
{"Name", "Tag"},
|
||||
{conversionlinker.Name, conversionlinker.Tag},
|
||||
{cookiebot.Name, cookiebot.Tag},
|
||||
{criteo.Name, criteo.Tag},
|
||||
{emarsys.Name, emarsys.Tag},
|
||||
{facebook.Name, facebook.Tag},
|
||||
{googleads.Name, googleads.Tag},
|
||||
{googleanalytics.Name, googleanalytics.Tag},
|
||||
{googletag.Name, googletag.Tag},
|
||||
{googleconsent.Name, googleconsent.Tag},
|
||||
{googletagmanager.Name, googletagmanager.Tag},
|
||||
{hotjar.Name, hotjar.Tag},
|
||||
{microsoftads.Name, microsoftads.Tag},
|
||||
{tracify.Name, tracify.Tag},
|
||||
{umami.Name, umami.Tag},
|
||||
tags := map[string]string{
|
||||
conversionlinker.Name: conversionlinker.Tag,
|
||||
cookiebot.Name: cookiebot.Tag,
|
||||
criteo.Name: criteo.Tag,
|
||||
emarsys.Name: emarsys.Tag,
|
||||
facebook.Name: facebook.Tag,
|
||||
googleads.Name: googleads.Tag,
|
||||
googleanalytics.Name: googleanalytics.Tag,
|
||||
googletag.Name: googletag.Tag,
|
||||
googleconsent.Name: googleconsent.Tag,
|
||||
googletagmanager.Name: googletagmanager.Tag,
|
||||
hotjar.Name: hotjar.Tag,
|
||||
microsoftads.Name: microsoftads.Tag,
|
||||
mixpanel.Name: mixpanel.Tag,
|
||||
tracify.Name: tracify.Tag,
|
||||
umami.Name: umami.Tag,
|
||||
pinterest.Name: pinterest.Tag,
|
||||
}
|
||||
// Define the data for the first table
|
||||
data := pterm.TableData{{"Name", "Tag"}}
|
||||
for _, name := range slices.Sorted(maps.Keys(tags)) {
|
||||
data = append(data, []string{name, tags[name]})
|
||||
}
|
||||
|
||||
return pterm.DefaultTable.WithHasHeader().WithData(data).Render()
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"maps"
|
||||
"os"
|
||||
"path"
|
||||
@ -12,22 +13,25 @@ import (
|
||||
"github.com/foomo/sesamy-cli/pkg/typescript/generator"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewTypeScript represents the typescript command
|
||||
func NewTypeScript(root *cobra.Command) *cobra.Command {
|
||||
func NewTypeScript(l *slog.Logger) *cobra.Command {
|
||||
c := viper.New()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "typescript",
|
||||
Short: "Generate typescript events",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
l := pkgcmd.Logger()
|
||||
l := pkgcmd.NewLogger()
|
||||
|
||||
cfg, err := pkgcmd.ReadConfig(l, cmd)
|
||||
cfg, err := pkgcmd.ReadConfig(l, c, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctpl, err := contemplate.Load(&cfg.GoogleTag.TypeScript.Config)
|
||||
ctpl, err := contemplate.Load(cmd.Context(), &cfg.GoogleTag.TypeScript.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -57,7 +61,10 @@ func NewTypeScript(root *cobra.Command) *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
flags := cmd.Flags()
|
||||
|
||||
flags.StringSliceP("config", "c", []string{"sesamy.yaml"}, "config files (default is sesamy.yaml)")
|
||||
_ = c.BindPFlag("config", flags.Lookup("config"))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -2,13 +2,14 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var version = "latest"
|
||||
|
||||
func NewVersion(root *cobra.Command) {
|
||||
func NewVersion(l *slog.Logger) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print version",
|
||||
@ -17,5 +18,5 @@ func NewVersion(root *cobra.Command) {
|
||||
},
|
||||
}
|
||||
|
||||
root.AddCommand(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
108
go.mod
108
go.mod
@ -1,87 +1,95 @@
|
||||
module github.com/foomo/sesamy-cli
|
||||
|
||||
go 1.24.0
|
||||
go 1.25.1
|
||||
|
||||
require (
|
||||
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/fatih/structtag v1.2.0
|
||||
github.com/foomo/go v0.0.3
|
||||
github.com/foomo/gocontemplate v0.1.4
|
||||
github.com/foomo/sesamy-go v0.8.1
|
||||
github.com/foomo/gocontemplate v0.2.0
|
||||
github.com/foomo/sesamy-go v0.11.2
|
||||
github.com/invopop/jsonschema v0.13.0
|
||||
github.com/itchyny/json2yaml v0.1.4
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4
|
||||
github.com/knadh/koanf/parsers/yaml v1.1.0
|
||||
github.com/knadh/koanf/providers/file v1.2.0
|
||||
github.com/knadh/koanf/providers/rawbytes v1.0.0
|
||||
github.com/knadh/koanf/v2 v2.2.2
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pterm/pterm v0.12.80
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/stoewer/go-strcase v1.3.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/wissance/stringFormatter v1.3.0
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa
|
||||
google.golang.org/api v0.222.0
|
||||
github.com/pterm/pterm v0.12.81
|
||||
github.com/spf13/cobra v1.10.1
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/sters/yaml-diff v1.4.1
|
||||
github.com/stoewer/go-strcase v1.3.1
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/wissance/stringFormatter v1.5.0
|
||||
google.golang.org/api v0.249.0
|
||||
)
|
||||
|
||||
require (
|
||||
atomicgo.dev/cursor v0.2.0 // indirect
|
||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||
atomicgo.dev/schedule v0.1.0 // indirect
|
||||
cloud.google.com/go/auth v0.14.1 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
cloud.google.com/go/auth v0.16.5 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.8.0 // indirect
|
||||
github.com/Code-Hex/go-wordwrap v1.0.0 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/containerd/console v1.0.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/foomo/gostandards v0.2.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||
github.com/goccy/go-yaml v1.15.6 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
|
||||
github.com/gookit/color v1.6.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/knadh/koanf/maps v0.1.2 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.12.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/mod v0.23.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/oauth2 v0.26.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/tools v0.30.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
|
||||
google.golang.org/grpc v1.70.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
golang.org/x/term v0.35.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
235
go.sum
235
go.sum
@ -6,12 +6,16 @@ atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
|
||||
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
|
||||
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
|
||||
cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0=
|
||||
cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
|
||||
cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
|
||||
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
|
||||
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4 h1:y80Hd9hmB+rsEH/p4c5ti5PbO0PhBmxw4NgbpFZvoHg=
|
||||
github.com/Code-Hex/Neo-cowsay/v2 v2.0.4/go.mod h1:6k40Pwrc2FazLf1BUbmAC36E9LvT+DErjZr30isbXhg=
|
||||
github.com/Code-Hex/go-wordwrap v1.0.0 h1:yl5fLyZEz3+hPGbpTRlTQ8mQJ1HXWcTq1FCNR1ch6zM=
|
||||
github.com/Code-Hex/go-wordwrap v1.0.0/go.mod h1:/SsbgkY2Q0aPQRyvXcyQwWYTQOIwSORKe6MPjRVGIWU=
|
||||
github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs=
|
||||
github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8=
|
||||
github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII=
|
||||
@ -29,54 +33,60 @@ github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xW
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
|
||||
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.0.3 h1:5pGzcPC78dImuBTT7nsZZnH+GIQUylbCtMkFEH26uZk=
|
||||
github.com/foomo/go v0.0.3/go.mod h1:x6g64wiQusqaFElnh5rlk9unCgLKmfUWy0YFLejJxio=
|
||||
github.com/foomo/gocontemplate v0.1.4 h1:MYSsoltno9pNMU5NwALd7PNSQ1XjN1tpqMGWAhCUETc=
|
||||
github.com/foomo/gocontemplate v0.1.4/go.mod h1:BH8eODDwlqWhasSl86avbtMN3Zfgt4pWwr8/PBPM5v0=
|
||||
github.com/foomo/gocontemplate v0.2.0 h1:YbgNUwZ9mK9Wj05cGVTPamCpMuxlaL4qegkbZv2eqOY=
|
||||
github.com/foomo/gocontemplate v0.2.0/go.mod h1:VOYIvxPPAT7HxrderRexS0EttcT8pyfSRkCMvS8rtxA=
|
||||
github.com/foomo/gostandards v0.2.0 h1:Ryd7TI9yV3Xk5B84DcUDB7KcL3LzQ8NS+TVOrFxTYfA=
|
||||
github.com/foomo/gostandards v0.2.0/go.mod h1:XQx7Ur6vyvxaIe2cQvAthuhPYDe+d2soibqVcXDXOh4=
|
||||
github.com/foomo/sesamy-go v0.8.1 h1:5m1ySZB5gW9Dymz8MFggU8DXs7F1AAcV6WW2ieX9DPI=
|
||||
github.com/foomo/sesamy-go v0.8.1/go.mod h1:9TlGLPABYmjt/louonKy4Na4nmx9RHq7N9KyZ6Sy7Xw=
|
||||
github.com/foomo/sesamy-go v0.11.2 h1:P405IMMDzW/4hMKbAbvCVBaFjOARb26/PdG1wTBAxBM=
|
||||
github.com/foomo/sesamy-go v0.11.2/go.mod h1:yORAeN0fDaZ0irXx4QdMp61wuDBAeEBHD0bTN4JjKxA=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
|
||||
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-yaml v1.15.6 h1:gy5kf1yjMia3/c3wWD+u1z3lU5XlhpT8FZGaLJU9cOA=
|
||||
github.com/goccy/go-yaml v1.15.6/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
||||
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
|
||||
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
|
||||
github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0=
|
||||
github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/gookit/color v1.6.0 h1:JjJXBTk1ETNyqyilJhkTXJYYigHG24TM9Xa2M1xAhRA=
|
||||
github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
@ -90,6 +100,16 @@ github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuOb
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo=
|
||||
github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
|
||||
github.com/knadh/koanf/parsers/yaml v1.1.0 h1:3ltfm9ljprAHt4jxgeYLlFPmUaunuCgu1yILuTXRdM4=
|
||||
github.com/knadh/koanf/parsers/yaml v1.1.0/go.mod h1:HHmcHXUrp9cOPcuC+2wrr44GTUB0EC+PyfN3HZD9tFg=
|
||||
github.com/knadh/koanf/providers/file v1.2.0 h1:hrUJ6Y9YOA49aNu/RSYzOTFlqzXSCpmYIDXI7OJU6+U=
|
||||
github.com/knadh/koanf/providers/file v1.2.0/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
|
||||
github.com/knadh/koanf/providers/rawbytes v1.0.0 h1:MrKDh/HksJlKJmaZjgs4r8aVBb/zsJyc/8qaSnzcdNI=
|
||||
github.com/knadh/koanf/providers/rawbytes v1.0.0/go.mod h1:KxwYJf1uezTKy6PBtfE+m725NGp4GPVA7XoNTJ/PtLo=
|
||||
github.com/knadh/koanf/v2 v2.2.2 h1:ghbduIkpFui3L587wavneC9e3WIliCgiCgdxYO/wd7A=
|
||||
github.com/knadh/koanf/v2 v2.2.2/go.mod h1:abWQc0cBXLSF/PSOMCB/SK+T13NXDsPvOksbpi5e/9Q=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
@ -99,19 +119,22 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY=
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -124,34 +147,35 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
|
||||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg=
|
||||
github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo=
|
||||
github.com/pterm/pterm v0.12.81 h1:ju+j5I2++FO1jBKMmscgh5h5DPFDFMB7epEjSoKehKA=
|
||||
github.com/pterm/pterm v0.12.81/go.mod h1:TyuyrPjnxfwP+ccJdBTeWHtd/e0ybQHkOS/TakajZCw=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
|
||||
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
|
||||
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
|
||||
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/sters/yaml-diff v1.4.1 h1:0W3jnFKCu8/DV7nh2aXSDA2VVfxfHu2+qdh81CuFmZo=
|
||||
github.com/sters/yaml-diff v1.4.1/go.mod h1:K286Xp2z+aGkok7z9k3zXcq0ZsrDaDp7/wyGwFjM9Y8=
|
||||
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
|
||||
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@ -161,12 +185,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/wissance/stringFormatter v1.3.0 h1:BVl9tEvS/JgE2YCE3voaBDe3F4SB8sGrH2E3VUzX3I0=
|
||||
github.com/wissance/stringFormatter v1.3.0/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA=
|
||||
github.com/wissance/stringFormatter v1.5.0 h1:hiGpYEJS3B3H/6M03HecqW8nDO0OXgQ75REVTXp6reM=
|
||||
github.com/wissance/stringFormatter v1.5.0/go.mod h1:H7Mz15+5i8ypmv6bLknM/uD+U1teUW99PlW0DNCNscA=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
@ -175,43 +199,43 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
|
||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
|
||||
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
|
||||
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -223,46 +247,49 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.222.0 h1:Aiewy7BKLCuq6cUCeOUrsAlzjXPqBkEeQ/iwGHVQa/4=
|
||||
google.golang.org/api v0.222.0/go.mod h1:efZia3nXpWELrwMlN5vyQrD4GmJN1Vw0x68Et3r+a9c=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w=
|
||||
google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
50
main.go
50
main.go
@ -1,7 +1,53 @@
|
||||
package main
|
||||
|
||||
import "github.com/foomo/sesamy-cli/cmd"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
|
||||
cowsay "github.com/Code-Hex/Neo-cowsay/v2"
|
||||
"github.com/foomo/sesamy-cli/cmd"
|
||||
cmdx "github.com/foomo/sesamy-cli/pkg/cmd"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
l := cmdx.NewLogger()
|
||||
|
||||
root := cmd.NewRoot(l)
|
||||
root.AddCommand(
|
||||
cmd.NewConfig(l),
|
||||
cmd.NewList(l),
|
||||
cmd.NewDiff(l),
|
||||
cmd.NewOpen(l),
|
||||
cmd.NewProvision(l),
|
||||
cmd.NewTags(l),
|
||||
cmd.NewTypeScript(l),
|
||||
cmd.NewVersion(l),
|
||||
)
|
||||
|
||||
say := func(msg string) string {
|
||||
if say, cerr := cowsay.Say(msg, cowsay.BallonWidth(80)); cerr == nil {
|
||||
msg = say
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
code := 0
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
l.Error(say("It's time to panic"))
|
||||
l.Error(fmt.Sprintf("%v", r))
|
||||
l.Error(string(debug.Stack()))
|
||||
code = 1
|
||||
}
|
||||
os.Exit(code)
|
||||
}()
|
||||
|
||||
if err := root.Execute(); err != nil {
|
||||
l.Error(say(strings.Split(errors.Cause(err).Error(), ":")[0]))
|
||||
l.Error(err.Error())
|
||||
code = 1
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,57 +1,47 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/knadh/koanf/parsers/yaml"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/providers/rawbytes"
|
||||
"github.com/knadh/koanf/v2"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// InitConfig reads in config file and ENV variables if set.
|
||||
func InitConfig() {
|
||||
filename := viper.GetString("config")
|
||||
func ReadConfig(l *slog.Logger, c *viper.Viper, cmd *cobra.Command) (*config.Config, error) {
|
||||
k := koanf.NewWithConf(koanf.Conf{
|
||||
Delim: "/",
|
||||
})
|
||||
|
||||
viper.SetConfigType("yaml")
|
||||
if filename == "-" {
|
||||
// do nothing
|
||||
} else if filename != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(filename)
|
||||
} else {
|
||||
// Search config in home directory with name ".sesamy" (without extension).
|
||||
viper.AddConfigPath(".")
|
||||
viper.SetConfigName("sesamy")
|
||||
}
|
||||
}
|
||||
|
||||
func ReadConfig(l *slog.Logger, cmd *cobra.Command) (*config.Config, error) {
|
||||
filename := viper.GetString("config")
|
||||
|
||||
if filename == "-" {
|
||||
l.Debug("using config from stdin")
|
||||
b, err := io.ReadAll(cmd.InOrStdin())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, filename := range c.GetStringSlice("config") {
|
||||
var p koanf.Provider
|
||||
if filename == "-" {
|
||||
pterm.Debug.Println("reading config from stdin")
|
||||
if b, err := io.ReadAll(cmd.InOrStdin()); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
p = rawbytes.Provider(b)
|
||||
}
|
||||
} else {
|
||||
pterm.Debug.Println("reading config from filename: " + filename)
|
||||
p = file.Provider(filename)
|
||||
}
|
||||
if err := viper.ReadConfig(bytes.NewBuffer(b)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
l.Debug("using config file", "filename", viper.ConfigFileUsed())
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return nil, err
|
||||
if err := k.Load(p, yaml.Parser()); err != nil {
|
||||
return nil, errors.Wrap(err, "error loading config file: "+filename)
|
||||
}
|
||||
}
|
||||
// l.Debug("config", l.ArgsFromMap(viper.AllSettings()))
|
||||
|
||||
var cfg *config.Config
|
||||
if err := viper.Unmarshal(&cfg, func(decoderConfig *mapstructure.DecoderConfig) {
|
||||
decoderConfig.TagName = "yaml"
|
||||
pterm.Debug.Println("unmarshalling config")
|
||||
if err := k.UnmarshalWithConf("", &cfg, koanf.UnmarshalConf{
|
||||
Tag: "yaml",
|
||||
}); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal config")
|
||||
}
|
||||
|
||||
@ -2,22 +2,36 @@ package cmd
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
ptermx "github.com/foomo/sesamy-cli/pkg/pterm"
|
||||
"github.com/pterm/pterm"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func Logger() *slog.Logger {
|
||||
verbose := viper.GetBool("verbose")
|
||||
func init() {
|
||||
pterm.Info.Prefix.Text = "⎈"
|
||||
pterm.Info.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
pterm.Debug.Prefix.Text = "⛏︎"
|
||||
pterm.Debug.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
pterm.Fatal.Prefix.Text = "⛔︎"
|
||||
pterm.Fatal.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
pterm.Error.Prefix.Text = "⛌"
|
||||
pterm.Error.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
pterm.Warning.Prefix.Text = "⚠"
|
||||
pterm.Warning.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
pterm.Success.Prefix.Text = "✓"
|
||||
pterm.Success.Scope.Style = &pterm.ThemeDefault.DebugMessageStyle
|
||||
|
||||
plogger := pterm.DefaultLogger.WithTime(false)
|
||||
if verbose {
|
||||
plogger = plogger.WithLevel(pterm.LogLevelTrace).WithCaller(true)
|
||||
if scope := os.Getenv("SESAMY_SCOPE"); scope != "" {
|
||||
pterm.Info.Scope.Text = scope
|
||||
pterm.Debug.Scope.Text = scope
|
||||
pterm.Fatal.Scope.Text = scope
|
||||
pterm.Error.Scope.Text = scope
|
||||
pterm.Warning.Scope.Text = scope
|
||||
pterm.Success.Scope.Text = scope
|
||||
}
|
||||
|
||||
// Create a new slog handler with the default PTerm logger
|
||||
handler := pterm.NewSlogHandler(plogger)
|
||||
|
||||
// Create a new slog logger with the handler
|
||||
return slog.New(handler)
|
||||
}
|
||||
|
||||
func NewLogger() *slog.Logger {
|
||||
return slog.New(ptermx.NewSlogHandler())
|
||||
}
|
||||
|
||||
@ -26,6 +26,10 @@ type Config struct {
|
||||
Facebook Facebook `json:"facebook" yaml:"facebook"`
|
||||
// MicrosoftAds provider settings
|
||||
MicrosoftAds MicrosoftAds `json:"microsoftAds" yaml:"microsoftAds"`
|
||||
// Mixpanel provider settings
|
||||
Mixpanel Mixpanel `json:"mixpanel" yaml:"mixpanel"`
|
||||
// Pinterest provider settings
|
||||
Pinterest Pinterest `json:"pinterest" yaml:"pinterest"`
|
||||
// Emarsys provider settings
|
||||
Emarsys Emarsys `json:"emarsys" yaml:"emarsys"`
|
||||
// Hotjar provider settings
|
||||
|
||||
@ -5,4 +5,6 @@ type ConversionLinker struct {
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Google Consent settings
|
||||
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
|
||||
// Accept incoming linker parameters
|
||||
EnableLinkerParams bool `json:"enableLinkerParams" yaml:"enableLinkerParams"`
|
||||
}
|
||||
|
||||
@ -2,10 +2,17 @@ package config
|
||||
|
||||
type Cookiebot struct {
|
||||
// Enable provider
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
TemplateName string `json:"templateName" yaml:"templateName"`
|
||||
CookiebotID string `json:"cookiebotId" yaml:"cookiebotId"`
|
||||
CDNRegion string `json:"cdnRegion" yaml:"cdnRegion"`
|
||||
URLPassthrough bool `json:"urlPassthrough" yaml:"urlPassthrough"`
|
||||
AdvertiserConsentModeEnabled bool `json:"advertiserConsentModeEnabled" yaml:"advertiserConsentModeEnabled"`
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Name of the manually installed Cookiebot CMP tag template
|
||||
TemplateName string `json:"templateName" yaml:"templateName"`
|
||||
// Create an account on Cookiebot.com and copy 'Domain Group ID' from the tab 'Your Scripts' in Cookiebot
|
||||
CookiebotID string `json:"cookiebotId" yaml:"cookiebotId"`
|
||||
// Select which CDN region Cookiebot uses
|
||||
CDNRegion string `json:"cdnRegion" yaml:"cdnRegion"`
|
||||
// When using URL passthrough, a few query parameters may be appended to links as users navigate through pages on your website
|
||||
URLPassthrough bool `json:"urlPassthrough" yaml:"urlPassthrough"`
|
||||
// If enabled, Google will deduce ad_storage, ad_user_data and ad_personalization data from the TC string.
|
||||
AdvertiserConsentModeEnabled bool `json:"advertiserConsentModeEnabled" yaml:"advertiserConsentModeEnabled"`
|
||||
// Default Consent state
|
||||
RegionSettings []CookiebotRegionSetting `json:"regionSettings" yaml:"regionSettings"`
|
||||
}
|
||||
|
||||
16
pkg/config/cookiebotregionsetting.go
Normal file
16
pkg/config/cookiebotregionsetting.go
Normal file
@ -0,0 +1,16 @@
|
||||
package config
|
||||
|
||||
type CookiebotRegionSetting struct {
|
||||
// Region (leave blank to apply globally)
|
||||
Region string `json:"region" yaml:"region"`
|
||||
// Default consent for functionality_storage and personalization_storage
|
||||
Preferences string `json:"preferences" yaml:"preferences"`
|
||||
// Default consent for analytics_storage
|
||||
Statistics string `json:"statistics" yaml:"statistics"`
|
||||
// Default consent for ad_storage
|
||||
Marketing string `json:"marketing" yaml:"marketing"`
|
||||
// Default consent ad_user_data
|
||||
AdUserData string `json:"adUserData" yaml:"adUserData"`
|
||||
// Default consent ad_personalization
|
||||
AdPersonalization string `json:"adPersonalization" yaml:"adPersonalization"`
|
||||
}
|
||||
@ -13,13 +13,14 @@ type (
|
||||
}
|
||||
GoogleAdsConversionServerContainer struct {
|
||||
contemplate.Config `json:",inline" yaml:",squash"`
|
||||
Settings map[string]GoogleAdsConversionTracking `json:"settings" yaml:"settings"`
|
||||
// Conversion settings map
|
||||
Settings map[string][]GoogleAdsConversionTracking `json:"settings" yaml:"settings"`
|
||||
}
|
||||
)
|
||||
|
||||
func (s *GoogleAdsConversionServerContainer) Setting(eventName string) GoogleAdsConversionTracking {
|
||||
func (s *GoogleAdsConversionServerContainer) Setting(eventName string) []GoogleAdsConversionTracking {
|
||||
if value, ok := s.Settings[eventName]; ok {
|
||||
return value
|
||||
}
|
||||
return GoogleAdsConversionTracking{}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package config
|
||||
|
||||
type GoogleAdsConversionTracking struct {
|
||||
// Conversion label
|
||||
Label string `json:"label" yaml:"label"`
|
||||
// Optional conversion id overriding the default
|
||||
ConversionID string `json:"conversionId" yaml:"conversionId"`
|
||||
}
|
||||
|
||||
@ -7,10 +7,16 @@ import (
|
||||
type GoogleAnalytics struct {
|
||||
// Enable provider
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Google Analytics account id
|
||||
AccountID string `json:"accountId" yaml:"accountId"`
|
||||
// Google Analytics property id
|
||||
PropertyID string `json:"propertyId" yaml:"propertyId"`
|
||||
// Google Consent settings
|
||||
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
|
||||
// GTag.js override configuration
|
||||
GoogleGTagJSOverride GoogleAnalyticsGTagJSOverride `json:"googleGTagJSOverride" yaml:"googleGTagJSOverride"`
|
||||
// Enable mpv2 user data transformation (experimental)
|
||||
EnableMPv2UserDataTransformation bool `json:"enableMPv2UserDataTransformation" yaml:"enableMPv2UserDataTransformation"`
|
||||
// Google Tag Manager web container settings
|
||||
WebContainer contemplate.Config `json:"webContainer" yaml:"webContainer"`
|
||||
// Google Tag Manager server container settings
|
||||
|
||||
@ -5,6 +5,8 @@ type GoogleTag struct {
|
||||
TagID string `json:"tagId" yaml:"tagId"`
|
||||
// Whether a page_view should be sent on initial load
|
||||
SendPageView bool `json:"sendPageView" yaml:"sendPageView"`
|
||||
// Optional custom server container url
|
||||
ServerContainerURL string `json:"serverContainerUrl" yaml:"serverContainerUrl"`
|
||||
// Data layer variables to be added to the event settings
|
||||
DataLayerVariables map[string]string `json:"dataLayerVariables" yaml:"dataLayerVariables"`
|
||||
// TypeScript settings
|
||||
|
||||
@ -5,6 +5,8 @@ type GoogleTagManagerContainer struct {
|
||||
TagID string `json:"tagId" yaml:"tagId"`
|
||||
// The container id
|
||||
ContainerID string `json:"containerId" yaml:"containerId"`
|
||||
// The workspace id that should be used by the api
|
||||
// (Optional) The workspace id that should be used by the api
|
||||
WorkspaceID string `json:"workspaceId" yaml:"workspaceId"`
|
||||
// (Optional) The workspace name that should be used by the api
|
||||
Workspace string `json:"workspace" yaml:"workspace"`
|
||||
}
|
||||
|
||||
30
pkg/config/mixpanel.go
Normal file
30
pkg/config/mixpanel.go
Normal file
@ -0,0 +1,30 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/foomo/gocontemplate/pkg/contemplate"
|
||||
)
|
||||
|
||||
type (
|
||||
Mixpanel struct {
|
||||
// Enable provider
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Mixpanel project token
|
||||
ProjectToken string `json:"projectToken" yaml:"projectToken"`
|
||||
// Google Consent settings
|
||||
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
|
||||
// Google Tag Manager server container settings
|
||||
ServerContainer MixpanelServerContainer `json:"serverContainer" yaml:"serverContainer"`
|
||||
}
|
||||
MixpanelServerContainer struct {
|
||||
// Set events
|
||||
Set contemplate.Config `json:"set" yaml:"set"`
|
||||
// SetOnce events
|
||||
SetOnce contemplate.Config `json:"setOnce" yaml:"setOnce"`
|
||||
// Reset events
|
||||
Reset contemplate.Config `json:"reset" yaml:"reset"`
|
||||
// Track events
|
||||
Track contemplate.Config `json:"track" yaml:"track"`
|
||||
// Identify events
|
||||
Identify contemplate.Config `json:"identify" yaml:"identify"`
|
||||
}
|
||||
)
|
||||
20
pkg/config/pinterest.go
Normal file
20
pkg/config/pinterest.go
Normal file
@ -0,0 +1,20 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/foomo/gocontemplate/pkg/contemplate"
|
||||
)
|
||||
|
||||
type Pinterest struct {
|
||||
// Enable provider
|
||||
Enabled bool `json:"enabled" yaml:"enabled"`
|
||||
// Pinterest advertiser id
|
||||
AdvertiserID string `json:"advertiserId" yaml:"advertiserId"`
|
||||
// Pinterest API access token
|
||||
APIAccessToken string `json:"apiAccessToken" yaml:"apiAccessToken"`
|
||||
// Enable test mode
|
||||
TestModeEnabled bool `json:"testModeEnabled" yaml:"testModeEnabled"`
|
||||
// Google Consent settings
|
||||
GoogleConsent GoogleConsent `json:"googleConsent" yaml:"googleConsent"`
|
||||
// Google Tag Manager server container settings
|
||||
ServerContainer contemplate.Config `json:"serverContainer" yaml:"serverContainer"`
|
||||
}
|
||||
@ -1,3 +1,3 @@
|
||||
package config
|
||||
|
||||
const Version = "1.0"
|
||||
const Version = "1.1"
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package conversionlinker
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
containertag "github.com/foomo/sesamy-cli/pkg/provider/conversionlinker/server/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/conversionlinker/server/trigger"
|
||||
@ -10,33 +12,30 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(tm *tagmanager.TagManager, cfg config.ConversionLinker) error {
|
||||
{
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.ConversionLinker) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var eventTriggerOpts []trigger.ConversionLinkerEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionLinkerEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewConversionLinkerEvent(NameConversionLinkerTrigger, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewConversionLinkerEvent(NameConversionLinkerTrigger, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+NameConversionLinkerTrigger)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(containertag.NewConversionLinker(Name, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewConversionLinker(Name, cfg.EnableLinkerParams, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func NewConversionLinker(name string, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
func NewConversionLinker(name string, enableLinkerParams bool, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: name,
|
||||
@ -14,7 +16,7 @@ func NewConversionLinker(name string, triggers ...*tagmanager.Trigger) *tagmanag
|
||||
{
|
||||
Key: "enableLinkerParams",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
Value: strconv.FormatBool(enableLinkerParams),
|
||||
},
|
||||
{
|
||||
Key: "enableCookieOverrides",
|
||||
|
||||
@ -1,28 +1,27 @@
|
||||
package cookiebot
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/cookiebot/web/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.Cookiebot) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.Cookiebot) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create event tags
|
||||
temmplate, err := tm.LookupTemplate(cfg.TemplateName)
|
||||
temmplate, err := tm.LookupTemplate(ctx, cfg.TemplateName)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Failed to lookup `%s`, please install the `%s` gallery tag template first (%s)", cfg.TemplateName, "Cookiebot CMP", "https://tagmanager.google.com/gallery/#/owners/cybotcorp/templates/gtm-templates-cookiebot-cmp")
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(tag.NewCookiebotInitialization(NameCookiebotTag, cfg, temmplate)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, tag.NewCookiebotInitialization(NameCookiebotTag, cfg, temmplate)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,62 +10,109 @@ import (
|
||||
)
|
||||
|
||||
func NewCookiebotInitialization(name string, cfg config.Cookiebot, template *tagmanager.CustomTemplate) *tagmanager.Tag {
|
||||
parameter := []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "adsDataRedaction",
|
||||
Type: "template",
|
||||
Value: "dynamic",
|
||||
},
|
||||
{
|
||||
Key: "addGeoRegion",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "serial",
|
||||
Type: "template",
|
||||
Value: cfg.CookiebotID,
|
||||
},
|
||||
{
|
||||
Key: "iabFramework",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "cdnRegion",
|
||||
Type: "template",
|
||||
Value: cfg.CDNRegion,
|
||||
},
|
||||
{
|
||||
Key: "advertiserConsentModeEnabled",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "language",
|
||||
Type: "template",
|
||||
Value: "auto",
|
||||
},
|
||||
{
|
||||
Key: "urlPassthrough",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(cfg.URLPassthrough),
|
||||
},
|
||||
{
|
||||
Key: "consentModeEnabled",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "waitForUpdate",
|
||||
Type: "template",
|
||||
Value: "2000",
|
||||
},
|
||||
}
|
||||
|
||||
if len(cfg.RegionSettings) > 0 {
|
||||
param := &tagmanager.Parameter{
|
||||
Key: "regionSettings",
|
||||
Type: "list",
|
||||
}
|
||||
for _, setting := range cfg.RegionSettings {
|
||||
param.List = append(param.List, &tagmanager.Parameter{
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "region",
|
||||
Type: "template",
|
||||
Value: setting.Region,
|
||||
},
|
||||
{
|
||||
Key: "defaultConsentPreferences",
|
||||
Type: "template",
|
||||
Value: setting.Preferences,
|
||||
},
|
||||
{
|
||||
Key: "defaultConsentStatistics",
|
||||
Type: "template",
|
||||
Value: setting.Statistics,
|
||||
},
|
||||
{
|
||||
Key: "defaultConsentMarketing",
|
||||
Type: "template",
|
||||
Value: setting.Marketing,
|
||||
},
|
||||
{
|
||||
Key: "defaultConsentMarketingAdUserData",
|
||||
Type: "template",
|
||||
Value: setting.AdUserData,
|
||||
},
|
||||
{
|
||||
Key: "defaultConsentMarketingAdPersonalization",
|
||||
Type: "template",
|
||||
Value: setting.AdPersonalization,
|
||||
},
|
||||
},
|
||||
Type: "map",
|
||||
})
|
||||
}
|
||||
parameter = append(parameter, param)
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
Name: name,
|
||||
FiringTriggerId: []string{trigger.IDConsentInitializtion},
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "adsDataRedaction",
|
||||
Type: "template",
|
||||
Value: "dynamic",
|
||||
},
|
||||
{
|
||||
Key: "addGeoRegion",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "serial",
|
||||
Type: "template",
|
||||
Value: cfg.CookiebotID,
|
||||
},
|
||||
{
|
||||
Key: "iabFramework",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "cdnRegion",
|
||||
Type: "template",
|
||||
Value: cfg.CDNRegion,
|
||||
},
|
||||
{
|
||||
Key: "advertiserConsentModeEnabled",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "language",
|
||||
Type: "template",
|
||||
Value: "auto",
|
||||
},
|
||||
{
|
||||
Key: "urlPassthrough",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(cfg.URLPassthrough),
|
||||
},
|
||||
{
|
||||
Key: "consentModeEnabled",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "waitForUpdate",
|
||||
Type: "template",
|
||||
Value: "2000",
|
||||
},
|
||||
},
|
||||
Type: utils.TemplateType(template),
|
||||
Parameter: parameter,
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package criteo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -14,40 +15,37 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.LookupTemplate(NameCriteoEventsAPITemplate)
|
||||
template, err := tm.LookupTemplate(ctx, NameCriteoEventsAPITemplate)
|
||||
if err != nil {
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Criteo Events API' template manually first")
|
||||
l.Warn("Please install the 'Criteo Events API' Tag Template manually first")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
callerID, err := tm.UpsertVariable(commonvariable.NewConstant(NameCallerID, cfg.CallerID))
|
||||
callerID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameCallerID, cfg.CallerID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
partnerID, err := tm.UpsertVariable(commonvariable.NewConstant(NamePartnerID, cfg.PartnerID))
|
||||
partnerID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NamePartnerID, cfg.PartnerID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
applicationID, err := tm.UpsertVariable(commonvariable.NewConstant(NameApplicationID, cfg.ApplicationID))
|
||||
applicationID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameApplicationID, cfg.ApplicationID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,22 +53,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.CriteoEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.CriteoEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewCriteoEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewCriteoEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewEventsAPITag(event, callerID, partnerID, applicationID, template, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewEventsAPITag(event, callerID, partnerID, applicationID, template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package criteo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
@ -10,16 +11,13 @@ import (
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
)
|
||||
|
||||
func Web(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.LookupTemplate(NameCriteoUserIdentificationTemplate)
|
||||
template, err := tm.LookupTemplate(ctx, NameCriteoUserIdentificationTemplate)
|
||||
if err != nil {
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Criteo User Identification' template manually first")
|
||||
@ -28,17 +26,17 @@ func Web(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Criteo) error {
|
||||
}
|
||||
|
||||
{ // setup criteo
|
||||
callerID, err := tm.UpsertVariable(commonvariable.NewConstant(NameCallerID, cfg.CallerID))
|
||||
callerID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameCallerID, cfg.CallerID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
partnerID, err := tm.UpsertVariable(commonvariable.NewConstant(NamePartnerID, cfg.PartnerID))
|
||||
partnerID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NamePartnerID, cfg.PartnerID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = tm.UpsertTag(client.NewUserIdentification(NameCriteoUserIdentificationTag, callerID, partnerID, template)); err != nil {
|
||||
if _, err = tm.UpsertTag(ctx, folder, client.NewUserIdentification(NameCriteoUserIdentificationTag, callerID, partnerID, template)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package emarsys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -16,38 +17,35 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Emarsys) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Emarsys) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // conversion
|
||||
merchantID, err := tm.UpsertVariable(commonvariable.NewConstant(NameMerchantIDConstant, cfg.MerchantID))
|
||||
merchantID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameMerchantIDConstant, cfg.MerchantID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysWebExtendTag(NameServerEmarsysWebExtendTagTemplate))
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewEmarsysWebExtendTag(NameServerEmarsysWebExtendTagTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysInitializationClient(NameServerEmarsysInitalizationClientTemplate))
|
||||
clientTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewEmarsysInitializationClient(NameServerEmarsysInitalizationClientTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tm.UpsertClient(serverclientx.NewEmarsys(NameServerEmarsysClient, cfg, clientTemplate))
|
||||
_, err = tm.UpsertClient(ctx, folder, serverclientx.NewEmarsys(NameServerEmarsysClient, cfg, clientTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,22 +53,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Emarsys) error
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EmarsysEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EmarsysEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewEmarsysEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEmarsysEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewEmarsys(event, merchantID, cfg.TestMode, cfg.DebugMode, tagTemplate, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewEmarsys(event, merchantID, cfg.TestMode, cfg.DebugMode, tagTemplate, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ const headers = {
|
||||
'user-agent': getRequestHeader('user-agent'),
|
||||
};
|
||||
|
||||
let query = ['xp=1', 'cp=1'];
|
||||
let query = ['xp=1', 'cp=1', 'test=true'];
|
||||
if (sessionId) query.push('s='+encodeUriComponent(sessionId));
|
||||
if (visitorId) query.push('vi='+encodeUriComponent(visitorId));
|
||||
if (pageViewId) query.push('pv='+encodeUriComponent(pageViewId));
|
||||
|
||||
@ -81,6 +81,7 @@ ___SANDBOXED_JS_FOR_SERVER___
|
||||
|
||||
const Math = require('Math');
|
||||
const JSON = require('JSON');
|
||||
const parseUrl = require('parseUrl');
|
||||
const setCookie = require('setCookie');
|
||||
const sendHttpGet = require('sendHttpGet');
|
||||
const setResponseBody = require('setResponseBody');
|
||||
@ -91,6 +92,7 @@ const getRequestHeader = require('getRequestHeader');
|
||||
const getCookieValues = require('getCookieValues');
|
||||
const generateRandom = require('generateRandom');
|
||||
const logToConsole = require('logToConsole');
|
||||
const createRegex = require('createRegex');
|
||||
|
||||
// --- Config ---
|
||||
|
||||
@ -111,7 +113,7 @@ const headerList = ["referer", "user-agent"];
|
||||
const requestUrl = merchantUrl+'?'+serializeData(mappedData);
|
||||
const requestOptions = {
|
||||
headers: generateRequestHeaders(headerList, cookieList),
|
||||
timeout: 500,
|
||||
timeout: 1000,
|
||||
};
|
||||
|
||||
return sendHttpGet(requestUrl, requestOptions).then((result) => {
|
||||
@ -142,6 +144,7 @@ function mapEventData() {
|
||||
referrer: eventData.page_referrer || null,
|
||||
orderId: null,
|
||||
order: null,
|
||||
search: null,
|
||||
category: null,
|
||||
view: null,
|
||||
cart: null,
|
||||
@ -150,25 +153,31 @@ function mapEventData() {
|
||||
switch (eventData.event_name) {
|
||||
case 'page_view': {
|
||||
mappedData.cart = serializeItems(eventData.items || []);
|
||||
mappedData.search = ((parseUrl(eventData.page_location) || {}).searchParams || {}).q || null;
|
||||
break;
|
||||
}
|
||||
case 'view_item': {
|
||||
mappedData.cart = serializeItems(eventData.items || []);
|
||||
mappedData.view = serializeItem(eventData.items[0] || {}, false);
|
||||
break;
|
||||
}
|
||||
case 'view_item_list': {
|
||||
mappedData.category = eventData.item_list_id;
|
||||
const prefix = createRegex('^/', 'i');
|
||||
const seperator = createRegex('/', 'i');
|
||||
mappedData.cart = serializeItems(eventData.items || []);
|
||||
mappedData.category = eventData.item_list_id.replace(prefix,"").replace(seperator, " > ");
|
||||
break;
|
||||
}
|
||||
case 'purchase': {
|
||||
mappedData.cart = [];
|
||||
mappedData.orderId = eventData.transaction_id;
|
||||
mappedData.order = serializeItems(eventData.items || []);
|
||||
if (eventData.tax) {
|
||||
mappedData.order[0].price += eventData.tax;
|
||||
}
|
||||
if (eventData.shipping) {
|
||||
mappedData.order[0].price += eventData.shipping;
|
||||
}
|
||||
if (eventData.tax) {
|
||||
mappedData.order[0].price += eventData.tax;
|
||||
}
|
||||
if (eventData.shipping) {
|
||||
mappedData.order[0].price += eventData.shipping;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -208,8 +217,7 @@ function serializeData(mappedData) {
|
||||
}
|
||||
if (mappedData.email) {
|
||||
slist.push("eh=" + encodeUriComponent(mappedData.email));
|
||||
}
|
||||
if (mappedData.customerId) {
|
||||
} else if (mappedData.customerId) {
|
||||
slist.push("ci=" + encodeUriComponent(mappedData.customerId));
|
||||
}
|
||||
if (mappedData.sessionId) {
|
||||
@ -234,6 +242,9 @@ function serializeData(mappedData) {
|
||||
slist.push("ca=" + encodeUriComponent(mappedData.cart));
|
||||
slist.push("cv=1");
|
||||
}
|
||||
if (mappedData.search) {
|
||||
slist.push("q=" + encodeUriComponent(mappedData.search));
|
||||
}
|
||||
if (mappedData.referrer) {
|
||||
slist.push("prev_url=" + encodeUriComponent(mappedData.referrer));
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package emarsys
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/emarsys/web/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/emarsys/web/template"
|
||||
@ -12,55 +14,52 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.Emarsys) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.Emarsys) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create initialization tag
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(template.NewEmarsysInitializationTag(NameWebEmarsysInitalizationTagTemplate))
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewEmarsysInitializationTag(NameWebEmarsysInitalizationTagTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = tm.UpsertTag(tag.NewEmarsysInitialization(NameWebEmarsysInitalizationTag, tagTemplate)); err != nil {
|
||||
if _, err = tm.UpsertTag(ctx, folder, tag.NewEmarsysInitialization(NameWebEmarsysInitalizationTag, tagTemplate)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := googletag.CreateWebDatalayerVariables(tm, map[string]string{
|
||||
if _, err := googletag.CreateWebDatalayerVariables(ctx, tm, map[string]string{
|
||||
"emarsys_page_view_id": "emarsys.page_view_id",
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create event tags
|
||||
tagID, err := tm.LookupVariable(googletag.NameGoogleTagID)
|
||||
tagID, err := tm.LookupVariable(ctx, googletag.NameGoogleTagID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventParameters, err := googletag.CreateWebEventTriggers(tm, cfg.WebContainer)
|
||||
eventParameters, err := googletag.CreateWebEventTriggers(ctx, tm, cfg.WebContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event := range eventParameters {
|
||||
eventTrigger, err := tm.LookupTrigger(commontrigger.EventName(event))
|
||||
eventTrigger, err := tm.LookupTrigger(ctx, commontrigger.EventName(event))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to lookup event trigger: "+event)
|
||||
}
|
||||
|
||||
eventSettings, err := tm.LookupVariable(commonvariable.GoogleTagEventSettingsName(event))
|
||||
eventSettings, err := tm.LookupVariable(ctx, commonvariable.GoogleTagEventSettingsName(event))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to lookup google tag event setting: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(containertag.NewGoogleAnalyticsEvent(event, tagID, eventSettings, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewGoogleAnalyticsEvent(event, tagID, eventSettings, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package facebook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -12,42 +13,44 @@ import (
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
tagmanager2 "google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Facebook) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Facebook) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pixelID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NamePixelIDConstant, cfg.PixelID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiAccessToken, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameAPIAcessTokenConstant, cfg.APIAccessToken))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var testEventToken *tagmanager2.Variable
|
||||
if cfg.TestEventToken != "" {
|
||||
var err error
|
||||
testEventToken, err = tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameTestEventTokenConstant, cfg.TestEventToken))
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
}
|
||||
|
||||
pixelID, err := tm.UpsertVariable(commonvariable.NewConstant(NamePixelIDConstant, cfg.PixelID))
|
||||
if err != nil {
|
||||
template, err := tm.LookupTemplate(ctx, NameConversionsAPITagTemplate)
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Conversions API Tag' by 'facebookincubator' template manually first")
|
||||
return err
|
||||
}
|
||||
|
||||
apiAccessToken, err := tm.UpsertVariable(commonvariable.NewConstant(NameAPIAcessTokenConstant, cfg.APIAccessToken))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
testEventToken, err := tm.UpsertVariable(commonvariable.NewConstant(NameTestEventTokenConstant, cfg.TestEventToken))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.LookupTemplate(NameConversionsAPITagTemplate)
|
||||
if err != nil {
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Conversion API' template manually first")
|
||||
}
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer.Config)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,22 +58,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Facebook) erro
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.FacebookEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.FacebookEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewFacebookEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewFacebookEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewConversionsAPITag(event, pixelID, apiAccessToken, testEventToken, cfg.ServerContainer.Setting(event), template, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewConversionsAPITag(event, pixelID, apiAccessToken, testEventToken, cfg.ServerContainer.Setting(event), template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,42 +13,48 @@ func ConversionsAPITagName(v string) string {
|
||||
}
|
||||
|
||||
func NewConversionsAPITag(name string, pixelID, apiAccessToken, testEventCode *tagmanager.Variable, settings config.FacebookConversionAPITag, template *tagmanager.CustomTemplate, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
params := []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "pixelId",
|
||||
Type: "template",
|
||||
Value: "{{" + pixelID.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "apiAccessToken",
|
||||
Type: "template",
|
||||
Value: "{{" + apiAccessToken.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "enableEventEnhancement",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(settings.EnableEventEnhancement),
|
||||
},
|
||||
{
|
||||
Key: "extendCookies",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(settings.ExtendCookies),
|
||||
},
|
||||
{
|
||||
Key: "actionSource",
|
||||
Type: "template",
|
||||
Value: "website",
|
||||
},
|
||||
}
|
||||
|
||||
if testEventCode != nil {
|
||||
params = append(params, &tagmanager.Parameter{
|
||||
Key: "testEventCode",
|
||||
Type: "template",
|
||||
Value: "{{" + testEventCode.Name + "}}",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: ConversionsAPITagName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "pixelId",
|
||||
Type: "template",
|
||||
Value: "{{" + pixelID.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "apiAccessToken",
|
||||
Type: "template",
|
||||
Value: "{{" + apiAccessToken.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "testEventCode",
|
||||
Type: "template",
|
||||
Value: "{{" + testEventCode.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "enableEventEnhancement",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(settings.EnableEventEnhancement),
|
||||
},
|
||||
{
|
||||
Key: "extendCookies",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(settings.ExtendCookies),
|
||||
},
|
||||
{
|
||||
Key: "actionSource",
|
||||
Type: "template",
|
||||
Value: "website",
|
||||
},
|
||||
},
|
||||
Type: utils.TemplateType(template),
|
||||
Parameter: params,
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
|
||||
12
pkg/provider/googleads/folder.go
Normal file
12
pkg/provider/googleads/folder.go
Normal file
@ -0,0 +1,12 @@
|
||||
package googleads
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pkgtagmanager "github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Folder(ctx context.Context, tm *pkgtagmanager.TagManager) (*tagmanager.Folder, error) {
|
||||
return tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package googleads
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -8,6 +9,7 @@ import (
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleads/server/trigger"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent"
|
||||
googleconsentvariable "github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager/server/variable"
|
||||
@ -15,34 +17,36 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.GoogleAds) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.GoogleAds) error {
|
||||
folder, err := Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conversionID, err := tm.UpsertVariable(commonvariable.NewConstant(NameConversionIDConstant, cfg.ConversionID))
|
||||
gtmFolder, err := googletagmanager.Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conversionID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameConversionIDConstant, cfg.ConversionID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// conversion
|
||||
if cfg.Conversion.Enabled {
|
||||
value, err := tm.UpsertVariable(variable.NewEventData("value"))
|
||||
value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData("value"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currency, err := tm.UpsertVariable(variable.NewEventData("currency"))
|
||||
currency, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData("currency"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.Conversion.ServerContainer.Config)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.Conversion.ServerContainer.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -50,23 +54,25 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.GoogleAds) err
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.GoogleAdsEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAdsEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewGoogleAdsEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewGoogleAdsEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewGoogleAdsConversionTracking(event, value, currency, conversionID, cfg.Conversion.ServerContainer.Setting(event), eventTrigger)); err != nil {
|
||||
return err
|
||||
for _, setting := range cfg.Conversion.ServerContainer.Setting(event) {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewGoogleAdsConversionTracking(event, value, currency, conversionID, setting, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,22 +81,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.GoogleAds) err
|
||||
if cfg.Remarketing.Enabled {
|
||||
var eventTriggerOpts []trigger.GoogleAdsRemarketingEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAdsRemarketingEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewGoogleAdsRemarketingEvent(NameGoogleAdsRemarketingTrigger, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewGoogleAdsRemarketingEvent(NameGoogleAdsRemarketingTrigger, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+NameGoogleAdsRemarketingTrigger)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewGoogleAdsRemarketing(NameGoogleAdsRemarketingTag, conversionID, cfg.Remarketing, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewGoogleAdsRemarketing(NameGoogleAdsRemarketingTag, conversionID, cfg.Remarketing, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,9 +11,16 @@ func GoogleAdsConversionTrackingName(v string) string {
|
||||
}
|
||||
|
||||
func NewGoogleAdsConversionTracking(name string, value, currency, conversionID *tagmanager.Variable, settings config.GoogleAdsConversionTracking, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
tagName := GoogleAdsConversionTrackingName(name)
|
||||
tagConversionID := "{{" + conversionID.Name + "}}"
|
||||
if settings.ConversionID != "" {
|
||||
tagName += " (" + settings.ConversionID + ")"
|
||||
tagConversionID = settings.ConversionID
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: GoogleAdsConversionTrackingName(name),
|
||||
Name: tagName,
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
@ -39,7 +46,7 @@ func NewGoogleAdsConversionTracking(name string, value, currency, conversionID *
|
||||
{
|
||||
Key: "conversionId",
|
||||
Type: "template",
|
||||
Value: "{{" + conversionID.Name + "}}",
|
||||
Value: tagConversionID,
|
||||
},
|
||||
{
|
||||
Key: "currencyCode",
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
googleanalyticsclient "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/client"
|
||||
containertag "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/server/tag"
|
||||
@ -20,77 +22,76 @@ import (
|
||||
api "google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitorIP, enableGeoResolution bool) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitorIP, enableGeoResolution bool) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create clients
|
||||
{
|
||||
measurementID, err := tm.LookupVariable(googletag.NameGoogleTagMeasurementID)
|
||||
measurementID, err := tm.LookupVariable(ctx, googletag.NameGoogleTagMeasurementID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
visitorRegion, err := tm.LookupVariable(googletagmanager.NameGoogleTagManagerVisitorRegion)
|
||||
visitorRegion, err := tm.LookupVariable(ctx, googletagmanager.NameGoogleTagManagerVisitorRegion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := tm.UpsertClient(googleanalyticsclient.NewGoogleAnalyticsGA4(NameGoogleAnalyticsGA4Client, enableGeoResolution, visitorRegion, measurementID))
|
||||
client, err := tm.UpsertClient(ctx, folder, googleanalyticsclient.NewGoogleAnalyticsGA4(NameGoogleAnalyticsGA4Client, enableGeoResolution, visitorRegion, measurementID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = tm.UpsertTrigger(servertrigger.NewClient(NameGoogleAnalyticsGA4ClientTrigger, client)); err != nil {
|
||||
if _, err = tm.UpsertTrigger(ctx, folder, servertrigger.NewClient(NameGoogleAnalyticsGA4ClientTrigger, client)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
client, err := tm.UpsertClient(googleanalyticsclient.NewMeasurementProtocolGA4(NameMeasurementProtocolGA4Client))
|
||||
client, err := tm.UpsertClient(ctx, folder, googleanalyticsclient.NewMeasurementProtocolGA4(NameMeasurementProtocolGA4Client))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tm.UpsertTrigger(servertrigger.NewClient(NameMeasurementProtocolGA4ClientTrigger, client)); err != nil {
|
||||
if _, err = tm.UpsertTrigger(ctx, folder, servertrigger.NewClient(NameMeasurementProtocolGA4ClientTrigger, client)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userDataTemplate, err := tm.UpsertCustomTemplate(servertemplate.NewJSONRequestValue(NameJSONRequestValueTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cfg.EnableMPv2UserDataTransformation {
|
||||
userDataTemplate, err := tm.UpsertCustomTemplate(ctx, servertemplate.NewJSONRequestValue(NameJSONRequestValueTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userDataVariable, err := tm.UpsertVariable(servervariable.NewMPv2Data("user_data", userDataTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userDataVariable, err := tm.UpsertVariable(ctx, folder, servervariable.NewMPv2Data("user_data", userDataTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
debugModeVariable, err := tm.UpsertVariable(servervariable.NewMPv2Data("debug_mode", userDataTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
debugModeVariable, err := tm.UpsertVariable(ctx, folder, servervariable.NewMPv2Data("debug_mode", userDataTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tm.UpsertTransformation(servertransformation.NewMPv2UserData(NameMPv2UserDataTransformation, map[string]*api.Variable{
|
||||
"user_data": userDataVariable,
|
||||
"debug_mode": debugModeVariable,
|
||||
}, client))
|
||||
if err != nil {
|
||||
return err
|
||||
_, err = tm.UpsertTransformation(ctx, folder, servertransformation.NewMPv2UserData(NameMPv2UserDataTransformation, map[string]*api.Variable{
|
||||
"user_data": userDataVariable,
|
||||
"debug_mode": debugModeVariable,
|
||||
}, client))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.GoogleGTagJSOverride.Enabled {
|
||||
template, err := tm.UpsertCustomTemplate(googleanalyticstemplate.NewGoogleGTagClient(NameGoogleGTagClientTemplate))
|
||||
template, err := tm.UpsertCustomTemplate(ctx, googleanalyticstemplate.NewGoogleGTagClient(NameGoogleGTagClientTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tm.UpsertClient(googleanalyticsclient.NewGoogleGTag(NameGoogleGTagClient, cfg.GoogleGTagJSOverride, template))
|
||||
_, err = tm.UpsertClient(ctx, folder, googleanalyticsclient.NewGoogleGTag(NameGoogleGTagClient, cfg.GoogleGTagJSOverride, template))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +99,7 @@ func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitor
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -106,22 +107,22 @@ func Server(tm *tagmanager.TagManager, cfg config.GoogleAnalytics, redactVisitor
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.GoogleAnalyticsEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.GoogleAnalyticsEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewGoogleAnalyticsEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewGoogleAnalyticsEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(containertag.NewGoogleAnalytics(event, redactVisitorIP, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewGoogleAnalytics(event, redactVisitorIP, eventTrigger)); err != nil {
|
||||
return errors.Wrap(err, "failed to upsert google analytics ga4 tag: "+event)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ func NewGoogleAnalyticsGA4(name string, enableGeoResolution bool, visitorRegion,
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "activateResponseCompression",
|
||||
Type: "template",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package googleanalytics
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
containertag "github.com/foomo/sesamy-cli/pkg/provider/googleanalytics/web/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletag"
|
||||
@ -10,38 +12,35 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.GoogleAnalytics) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleAnalytics) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create event tags
|
||||
tagID, err := tm.LookupVariable(googletag.NameGoogleTagID)
|
||||
tagID, err := tm.LookupVariable(ctx, googletag.NameGoogleTagID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventParameters, err := googletag.CreateWebEventTriggers(tm, cfg.WebContainer)
|
||||
eventParameters, err := googletag.CreateWebEventTriggers(ctx, tm, cfg.WebContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event := range eventParameters {
|
||||
eventTrigger, err := tm.LookupTrigger(commontrigger.EventName(event))
|
||||
eventTrigger, err := tm.LookupTrigger(ctx, commontrigger.EventName(event))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to lookup event trigger: "+event)
|
||||
}
|
||||
|
||||
eventSettings, err := tm.LookupVariable(commonvariable.GoogleTagEventSettingsName(event))
|
||||
eventSettings, err := tm.LookupVariable(ctx, commonvariable.GoogleTagEventSettingsName(event))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to lookup google tag event setting: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(containertag.NewGoogleAnalyticsEvent(event, tagID, eventSettings, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewGoogleAnalyticsEvent(event, tagID, eventSettings, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +1,28 @@
|
||||
package googleconsent
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/template"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
)
|
||||
|
||||
func ServerEnsure(tm *tagmanager.TagManager) error {
|
||||
folderName := tm.FolderName()
|
||||
defer tm.SetFolderName(folderName)
|
||||
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func ServerEnsure(ctx context.Context, tm *tagmanager.TagManager) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create clients
|
||||
consentTemplate, err := tm.UpsertCustomTemplate(template.NewGoogleConsentModeCheck(NameGoogleConsentModeCheckVariableTemplate))
|
||||
consentTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewGoogleConsentModeCheck(NameGoogleConsentModeCheckVariableTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tm.UpsertVariable(variable.NewGoogleConsentModeAdStorage(consentTemplate)); err != nil {
|
||||
if _, err = tm.UpsertVariable(ctx, folder, variable.NewGoogleConsentModeAdStorage(consentTemplate)); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tm.UpsertVariable(variable.NewGoogleConsentModeAnalyticsStorage(consentTemplate)); err != nil {
|
||||
if _, err = tm.UpsertVariable(ctx, folder, variable.NewGoogleConsentModeAnalyticsStorage(consentTemplate)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
12
pkg/provider/googletag/folder.go
Normal file
12
pkg/provider/googletag/folder.go
Normal file
@ -0,0 +1,12 @@
|
||||
package googletag
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pkgtagmanager "github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Folder(ctx context.Context, tm *pkgtagmanager.TagManager) (*tagmanager.Folder, error) {
|
||||
return tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
}
|
||||
@ -1,22 +1,21 @@
|
||||
package googletag
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
)
|
||||
|
||||
func Server(tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
folder, err := Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create constants
|
||||
if _, err := tm.UpsertVariable(commonvariable.NewConstant(NameGoogleTagMeasurementID, cfg.TagID)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameGoogleTagMeasurementID, cfg.TagID)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package googletag
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/gocontemplate/pkg/contemplate"
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
webtag "github.com/foomo/sesamy-cli/pkg/provider/googletag/web/tag"
|
||||
@ -13,13 +15,10 @@ import (
|
||||
api "google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
folder, err := Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // setup google tag
|
||||
@ -29,26 +28,29 @@ func Web(tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
if !cfg.SendPageView {
|
||||
configSettings["send_page_view"] = "false"
|
||||
}
|
||||
if cfg.ServerContainerURL != "" {
|
||||
configSettings["server_container_url"] = cfg.ServerContainerURL
|
||||
}
|
||||
|
||||
eventSettings := map[string]*api.Variable{}
|
||||
for k, v := range cfg.DataLayerVariables {
|
||||
dlv, err := tm.UpsertVariable(variable.NewDataLayer(v))
|
||||
dlv, err := tm.UpsertVariable(ctx, folder, variable.NewDataLayer(v))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventSettings[k] = dlv
|
||||
}
|
||||
|
||||
tagID, err := tm.UpsertVariable(commonvariable.NewConstant(NameGoogleTagID, cfg.TagID))
|
||||
tagID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameGoogleTagID, cfg.TagID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
settingsVariable, err := tm.UpsertVariable(containervariable.NewGoogleTagConfigurationSettings(NameGoogleTagSettings, configSettings))
|
||||
settingsVariable, err := tm.UpsertVariable(ctx, folder, containervariable.NewGoogleTagConfigurationSettings(NameGoogleTagSettings, configSettings))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = tm.UpsertTag(webtag.NewGoogleTag(NameGoogleTag, tagID, settingsVariable, eventSettings)); err != nil {
|
||||
if _, err = tm.UpsertTag(ctx, folder, webtag.NewGoogleTag(NameGoogleTag, tagID, settingsVariable, eventSettings)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -56,27 +58,28 @@ func Web(tm *tagmanager.TagManager, cfg config.GoogleTag) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateWebEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (map[string]map[string]string, error) {
|
||||
previousFolderName := tm.FolderName()
|
||||
tm.SetFolderName("Sesamy - " + Name)
|
||||
defer tm.SetFolderName(previousFolderName)
|
||||
func CreateWebEventTriggers(ctx context.Context, tm *tagmanager.TagManager, cfg contemplate.Config) (map[string]map[string]string, error) {
|
||||
folder, err := tm.LookupFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
eventParameters, err := utils.LoadEventParams(cfg)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for event, parameters := range eventParameters {
|
||||
if _, err = tm.UpsertTrigger(commontrigger.NewEvent(event)); err != nil {
|
||||
if _, err = tm.UpsertTrigger(ctx, folder, commontrigger.NewEvent(event)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
variables, err := CreateWebDatalayerVariables(tm, parameters)
|
||||
variables, err := CreateWebDatalayerVariables(ctx, tm, parameters)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertVariable(containervariable.NewGoogleTagEventSettings(event, variables)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, containervariable.NewGoogleTagEventSettings(event, variables)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -84,14 +87,15 @@ func CreateWebEventTriggers(tm *tagmanager.TagManager, cfg contemplate.Config) (
|
||||
return eventParameters, nil
|
||||
}
|
||||
|
||||
func CreateWebDatalayerVariables(tm *tagmanager.TagManager, parameters map[string]string) (map[string]*api.Variable, error) {
|
||||
previousFolderName := tm.FolderName()
|
||||
tm.SetFolderName("Sesamy - " + Name)
|
||||
defer tm.SetFolderName(previousFolderName)
|
||||
var err error
|
||||
func CreateWebDatalayerVariables(ctx context.Context, tm *tagmanager.TagManager, parameters map[string]string) (map[string]*api.Variable, error) {
|
||||
folder, err := tm.LookupFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
variables := make(map[string]*api.Variable, len(parameters))
|
||||
for parameterName, parameterValue := range parameters {
|
||||
if variables[parameterName], err = tm.UpsertVariable(variable.NewDataLayer(parameterValue)); err != nil {
|
||||
if variables[parameterName], err = tm.UpsertVariable(ctx, folder, variable.NewDataLayer(parameterValue)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,32 +1,30 @@
|
||||
package variable
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func NewGoogleTagConfigurationSettings(name string, variables map[string]string) *tagmanager.Variable {
|
||||
parameters := make([]string, 0, len(variables))
|
||||
for k := range variables {
|
||||
parameters = append(parameters, k)
|
||||
}
|
||||
sort.Strings(parameters)
|
||||
variableKeys := slices.AppendSeq(make([]string, 0, len(variables)), maps.Keys(variables))
|
||||
slices.Sort(variableKeys)
|
||||
|
||||
list := make([]*tagmanager.Parameter, len(parameters))
|
||||
for i, parameter := range parameters {
|
||||
list := make([]*tagmanager.Parameter, len(variables))
|
||||
for i, k := range variableKeys {
|
||||
list[i] = &tagmanager.Parameter{
|
||||
Type: "map",
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "parameter",
|
||||
Type: "template",
|
||||
Value: parameter,
|
||||
Value: k,
|
||||
},
|
||||
{
|
||||
Key: "parameterValue",
|
||||
Type: "template",
|
||||
Value: variables[parameter],
|
||||
Value: variables[k],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
12
pkg/provider/googletagmanager/folder.go
Normal file
12
pkg/provider/googletagmanager/folder.go
Normal file
@ -0,0 +1,12 @@
|
||||
package googletagmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pkgtagmanager "github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Folder(ctx context.Context, tm *pkgtagmanager.TagManager) (*tagmanager.Folder, error) {
|
||||
return tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
package googletagmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager/server/client"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager/server/variable"
|
||||
@ -9,40 +11,37 @@ import (
|
||||
servervariable "github.com/foomo/sesamy-cli/pkg/tagmanager/server/variable"
|
||||
)
|
||||
|
||||
func Server(tm *tagmanager.TagManager, cfg config.GoogleTagManager, enableGeoResolution bool) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTagManager, enableGeoResolution bool) error {
|
||||
folder, err := Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // enable build in variables
|
||||
if _, err := tm.EnableBuiltInVariable("clientName"); err != nil {
|
||||
if _, err := tm.EnableBuiltInVariable(ctx, "clientName"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
{ // create client
|
||||
visitorRegion, err := tm.UpsertVariable(variable.NewVisitorRegion(NameGoogleTagManagerVisitorRegion))
|
||||
visitorRegion, err := tm.UpsertVariable(ctx, folder, variable.NewVisitorRegion(NameGoogleTagManagerVisitorRegion))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertClient(client.NewGoogleTagManagerWebContainer(NameGoogleTagManagerWebContainerClient, cfg.WebContainer.TagID, enableGeoResolution, visitorRegion)); err != nil {
|
||||
if _, err := tm.UpsertClient(ctx, folder, client.NewGoogleTagManagerWebContainer(NameGoogleTagManagerWebContainerClient, cfg.WebContainer.TagID, enableGeoResolution, visitorRegion)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
{ // create variables
|
||||
for _, value := range cfg.ServerContaienrVariables.EventData {
|
||||
if _, err := tm.UpsertVariable(servervariable.NewEventData(value)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, servervariable.NewEventData(value)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for key, value := range cfg.ServerContaienrVariables.LookupTables {
|
||||
if _, err := tm.UpsertVariable(commonvariable.NewLookupTable(key, value)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, commonvariable.NewLookupTable(key, value)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,28 @@
|
||||
package googletagmanager
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager/web/variable"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.GoogleTagManager) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.GoogleTagManager) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create variables
|
||||
for _, value := range cfg.WebContaienrVariables.DataLayer {
|
||||
if _, err := tm.UpsertVariable(variable.NewDataLayer(value)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, variable.NewDataLayer(value)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for key, value := range cfg.WebContaienrVariables.LookupTables {
|
||||
if _, err := tm.UpsertVariable(commonvariable.NewLookupTable(key, value)); err != nil {
|
||||
if _, err := tm.UpsertVariable(ctx, folder, commonvariable.NewLookupTable(key, value)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,28 +1,27 @@
|
||||
package hotjar
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
client "github.com/foomo/sesamy-cli/pkg/provider/hotjar/web/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
)
|
||||
|
||||
func Web(tm *tagmanager.TagManager, cfg config.Hotjar) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Web(ctx context.Context, tm *tagmanager.TagManager, cfg config.Hotjar) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // setup hotjar
|
||||
siteID, err := tm.UpsertVariable(commonvariable.NewConstant(NameSiteID, cfg.SiteID))
|
||||
siteID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameSiteID, cfg.SiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = tm.UpsertTag(client.NewHotjar(NameHotjarTag, siteID)); err != nil {
|
||||
if _, err = tm.UpsertTag(ctx, folder, client.NewHotjar(NameHotjarTag, siteID)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package microsoftads
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -15,28 +16,25 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.MicrosoftAds) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.MicrosoftAds) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagID, err := tm.UpsertVariable(commonvariable.NewConstant(NameTagIDConstant, cfg.TagID))
|
||||
tagID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameTagIDConstant, cfg.TagID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.Conversion.Enabled {
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(template.NewConversionTag(NameConversionsTagTemplate))
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewConversionTag(NameConversionsTagTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.Conversion.ServerContainer.Config)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.Conversion.ServerContainer.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -44,22 +42,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.MicrosoftAds)
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.ConversionEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewConversionEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewConversionEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewConversion(event, tagID, tagTemplate, cfg.Conversion.ServerContainer.Setting(event), eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewConversion(event, tagID, tagTemplate, cfg.Conversion.ServerContainer.Setting(event), eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,7 +531,7 @@ if (data.activateLogs) {
|
||||
|
||||
return sendHttpGet(url, {
|
||||
headers: {key: 'value'},
|
||||
timeout: 500,
|
||||
timeout: 1000,
|
||||
}).then((result) => {
|
||||
if (result.statusCode >= 200 && result.statusCode < 300) {
|
||||
data.gtmOnSuccess();
|
||||
|
||||
8
pkg/provider/mixpanel/constants.go
Normal file
8
pkg/provider/mixpanel/constants.go
Normal file
@ -0,0 +1,8 @@
|
||||
package mixpanel
|
||||
|
||||
const (
|
||||
Tag = "mixpanel"
|
||||
Name = "Mixpanel"
|
||||
NameTagTemplate = "Mixpanel"
|
||||
NamePrjectTokenConstant = "Mixpanel Project Token"
|
||||
)
|
||||
12
pkg/provider/mixpanel/folder.go
Normal file
12
pkg/provider/mixpanel/folder.go
Normal file
@ -0,0 +1,12 @@
|
||||
package mixpanel
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pkgtagmanager "github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Folder(ctx context.Context, tm *pkgtagmanager.TagManager) (*tagmanager.Folder, error) {
|
||||
return tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
}
|
||||
228
pkg/provider/mixpanel/server.go
Normal file
228
pkg/provider/mixpanel/server.go
Normal file
@ -0,0 +1,228 @@
|
||||
package mixpanel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent"
|
||||
googleconsentvariable "github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googletagmanager"
|
||||
servertagx "github.com/foomo/sesamy-cli/pkg/provider/mixpanel/server/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/mixpanel/server/trigger"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
commonvariable "github.com/foomo/sesamy-cli/pkg/tagmanager/common/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager/server/variable"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
tagmanager2 "google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Mixpanel) error {
|
||||
folder, err := Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gtmFolder, err := googletagmanager.Folder(ctx, tm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.LookupTemplate(ctx, NameTagTemplate)
|
||||
if err != nil {
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Mixpanel' by stape-io Tag Template manually first")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
projectToken, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NamePrjectTokenConstant, cfg.ProjectToken))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create set tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.Set)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event, params := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventParams := map[string]*tagmanager2.Variable{}
|
||||
for k := range params {
|
||||
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
eventParams[k] = value
|
||||
}
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewSet(event, projectToken, template, eventParams, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // create set once tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.SetOnce)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event, params := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventParams := map[string]*tagmanager2.Variable{}
|
||||
for k := range params {
|
||||
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
eventParams[k] = value
|
||||
}
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewSetOnce(event, projectToken, template, eventParams, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // create reset tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.Reset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewReset(event, projectToken, template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // create track tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.Track)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event, params := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventParams := map[string]*tagmanager2.Variable{}
|
||||
for k := range params {
|
||||
if value, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData(k)); err != nil {
|
||||
return err
|
||||
} else {
|
||||
eventParams[k] = value
|
||||
}
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewTrack(event, projectToken, template, eventParams, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // create reset tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer.Identify)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.EventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
userID, err := tm.UpsertVariable(ctx, gtmFolder, variable.NewEventData("user_id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewIdentify(event, userID, projectToken, template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
51
pkg/provider/mixpanel/server/tag/identify.go
Normal file
51
pkg/provider/mixpanel/server/tag/identify.go
Normal file
@ -0,0 +1,51 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func IdentifyName(v string) string {
|
||||
return "Mixpanel Identify - " + v
|
||||
}
|
||||
|
||||
func NewIdentify(name string, identifier, projectToken *tagmanager.Variable, template *tagmanager.CustomTemplate, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: IdentifyName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "serverEU",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "logType",
|
||||
Type: "template",
|
||||
Value: "debug",
|
||||
},
|
||||
{
|
||||
Key: "identifier",
|
||||
Type: "template",
|
||||
Value: "{{" + identifier.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "identifyAuto",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Type: "template",
|
||||
Value: "reset",
|
||||
},
|
||||
{
|
||||
Key: "token",
|
||||
Type: "template",
|
||||
Value: "{{" + projectToken.Name + "}}",
|
||||
},
|
||||
},
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
41
pkg/provider/mixpanel/server/tag/reset.go
Normal file
41
pkg/provider/mixpanel/server/tag/reset.go
Normal file
@ -0,0 +1,41 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func ResetName(v string) string {
|
||||
return "Mixpanel Reset - " + v
|
||||
}
|
||||
|
||||
func NewReset(name string, projectToken *tagmanager.Variable, template *tagmanager.CustomTemplate, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: ResetName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "serverEU",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "logType",
|
||||
Type: "template",
|
||||
Value: "debug",
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Type: "template",
|
||||
Value: "reset",
|
||||
},
|
||||
{
|
||||
Key: "token",
|
||||
Type: "template",
|
||||
Value: "{{" + projectToken.Name + "}}",
|
||||
},
|
||||
},
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
88
pkg/provider/mixpanel/server/tag/set.go
Normal file
88
pkg/provider/mixpanel/server/tag/set.go
Normal file
@ -0,0 +1,88 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func SetName(v string) string {
|
||||
return "Mixpanel Set - " + v
|
||||
}
|
||||
|
||||
func NewSet(name string, projectToken *tagmanager.Variable, template *tagmanager.CustomTemplate, params map[string]*tagmanager.Variable, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
parameter := []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "serverEU",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "logType",
|
||||
Type: "template",
|
||||
Value: "debug",
|
||||
},
|
||||
{
|
||||
Key: "identifyAuto",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "trackName",
|
||||
Type: "template",
|
||||
Value: name,
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Type: "template",
|
||||
Value: "profile-set",
|
||||
},
|
||||
{
|
||||
Key: "token",
|
||||
Type: "template",
|
||||
Value: "{{" + projectToken.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "trackFromVariable",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
}
|
||||
|
||||
if len(params) > 0 {
|
||||
var list []*tagmanager.Parameter
|
||||
for _, key := range slices.Sorted(maps.Keys(params)) {
|
||||
param := params[key]
|
||||
list = append(list, &tagmanager.Parameter{
|
||||
Type: "map",
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "name",
|
||||
Type: "template",
|
||||
Value: key,
|
||||
},
|
||||
{
|
||||
Key: "value",
|
||||
Type: "template",
|
||||
Value: "{{" + param.Name + "}}",
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
parameter = append(parameter, &tagmanager.Parameter{
|
||||
Key: "userPropertiesTable",
|
||||
Type: "list",
|
||||
List: list,
|
||||
})
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: SetName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: parameter,
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
88
pkg/provider/mixpanel/server/tag/setonce.go
Normal file
88
pkg/provider/mixpanel/server/tag/setonce.go
Normal file
@ -0,0 +1,88 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func SetOnceName(v string) string {
|
||||
return "Mixpanel SetOnce - " + v
|
||||
}
|
||||
|
||||
func NewSetOnce(name string, projectToken *tagmanager.Variable, template *tagmanager.CustomTemplate, params map[string]*tagmanager.Variable, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
parameter := []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "serverEU",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "logType",
|
||||
Type: "template",
|
||||
Value: "debug",
|
||||
},
|
||||
{
|
||||
Key: "identifyAuto",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "trackName",
|
||||
Type: "template",
|
||||
Value: name,
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Type: "template",
|
||||
Value: "profile-set-once",
|
||||
},
|
||||
{
|
||||
Key: "token",
|
||||
Type: "template",
|
||||
Value: "{{" + projectToken.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "trackFromVariable",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
}
|
||||
|
||||
if len(params) > 0 {
|
||||
var list []*tagmanager.Parameter
|
||||
for _, key := range slices.Sorted(maps.Keys(params)) {
|
||||
param := params[key]
|
||||
list = append(list, &tagmanager.Parameter{
|
||||
Type: "map",
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "name",
|
||||
Type: "template",
|
||||
Value: key,
|
||||
},
|
||||
{
|
||||
Key: "value",
|
||||
Type: "template",
|
||||
Value: "{{" + param.Name + "}}",
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
parameter = append(parameter, &tagmanager.Parameter{
|
||||
Key: "userPropertiesToSetOnce",
|
||||
Type: "list",
|
||||
List: list,
|
||||
})
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: SetOnceName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: parameter,
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
93
pkg/provider/mixpanel/server/tag/track.go
Normal file
93
pkg/provider/mixpanel/server/tag/track.go
Normal file
@ -0,0 +1,93 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func TrackName(v string) string {
|
||||
return "Mixpanel Track - " + v
|
||||
}
|
||||
|
||||
func NewTrack(name string, projectToken *tagmanager.Variable, template *tagmanager.CustomTemplate, params map[string]*tagmanager.Variable, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
parameter := []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "serverEU",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "logType",
|
||||
Type: "template",
|
||||
Value: "debug",
|
||||
},
|
||||
{
|
||||
Key: "trackCommonData",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "identifyAuto",
|
||||
Type: "boolean",
|
||||
Value: "true",
|
||||
},
|
||||
{
|
||||
Key: "trackName",
|
||||
Type: "template",
|
||||
Value: name,
|
||||
},
|
||||
{
|
||||
Key: "type",
|
||||
Type: "template",
|
||||
Value: "track",
|
||||
},
|
||||
{
|
||||
Key: "token",
|
||||
Type: "template",
|
||||
Value: "{{" + projectToken.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "trackFromVariable",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
}
|
||||
|
||||
if len(params) > 0 {
|
||||
var list []*tagmanager.Parameter
|
||||
for _, key := range slices.Sorted(maps.Keys(params)) {
|
||||
param := params[key]
|
||||
list = append(list, &tagmanager.Parameter{
|
||||
Type: "map",
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "name",
|
||||
Type: "template",
|
||||
Value: key,
|
||||
},
|
||||
{
|
||||
Key: "value",
|
||||
Type: "template",
|
||||
Value: "{{" + param.Name + "}}",
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
parameter = append(parameter, &tagmanager.Parameter{
|
||||
Key: "trackParameters",
|
||||
Type: "list",
|
||||
List: list,
|
||||
})
|
||||
}
|
||||
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: TrackName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: parameter,
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
75
pkg/provider/mixpanel/server/trigger/event.go
Normal file
75
pkg/provider/mixpanel/server/trigger/event.go
Normal file
@ -0,0 +1,75 @@
|
||||
package trigger
|
||||
|
||||
import (
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func EventName(v string) string {
|
||||
return "Mixpanel - " + v
|
||||
}
|
||||
|
||||
type (
|
||||
EventOptions struct {
|
||||
consentMode *tagmanager.Variable
|
||||
}
|
||||
EventOption func(*EventOptions)
|
||||
)
|
||||
|
||||
func EventWithConsentMode(mode *tagmanager.Variable) EventOption {
|
||||
return func(o *EventOptions) {
|
||||
o.consentMode = mode
|
||||
}
|
||||
}
|
||||
|
||||
func NewEvent(name string, opts ...EventOption) *tagmanager.Trigger {
|
||||
o := &EventOptions{}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
opt(o)
|
||||
}
|
||||
}
|
||||
|
||||
var filter []*tagmanager.Condition
|
||||
if o.consentMode != nil {
|
||||
filter = append(filter,
|
||||
&tagmanager.Condition{
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "arg0",
|
||||
Type: "template",
|
||||
Value: "{{" + o.consentMode.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "arg1",
|
||||
Type: "template",
|
||||
Value: "granted",
|
||||
},
|
||||
},
|
||||
Type: "equals",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return &tagmanager.Trigger{
|
||||
Type: "customEvent",
|
||||
Name: EventName(name),
|
||||
CustomEventFilter: []*tagmanager.Condition{
|
||||
{
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "arg0",
|
||||
Type: "template",
|
||||
Value: "{{_event}}",
|
||||
},
|
||||
{
|
||||
Key: "arg1",
|
||||
Type: "template",
|
||||
Value: name,
|
||||
},
|
||||
},
|
||||
Type: "equals",
|
||||
},
|
||||
},
|
||||
Filter: filter,
|
||||
}
|
||||
}
|
||||
7
pkg/provider/pinterest/constants.go
Normal file
7
pkg/provider/pinterest/constants.go
Normal file
@ -0,0 +1,7 @@
|
||||
package pinterest
|
||||
|
||||
const (
|
||||
Tag = "pinterest"
|
||||
Name = "Pinterest"
|
||||
NameTagTemplate = "Pinterest API for Conversions Tag"
|
||||
)
|
||||
62
pkg/provider/pinterest/server.go
Normal file
62
pkg/provider/pinterest/server.go
Normal file
@ -0,0 +1,62 @@
|
||||
package pinterest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent"
|
||||
googleconsentvariable "github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
|
||||
containertag "github.com/foomo/sesamy-cli/pkg/provider/pinterest/server/tag"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/pinterest/server/trigger"
|
||||
"github.com/foomo/sesamy-cli/pkg/tagmanager"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Pinterest) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.LookupTemplate(ctx, NameTagTemplate)
|
||||
if err != nil {
|
||||
if errors.Is(err, tagmanager.ErrNotFound) {
|
||||
l.Warn("Please install the 'Pinterest API for Conversions Ta' Tag Template manually first")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.EventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.ConversionWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewConversion(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewConversion(event, cfg, template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
59
pkg/provider/pinterest/server/tag/conversion.go
Normal file
59
pkg/provider/pinterest/server/tag/conversion.go
Normal file
@ -0,0 +1,59 @@
|
||||
package tag
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/utils"
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func ConversionName(v string) string {
|
||||
return "Pinterest Conversion - " + v
|
||||
}
|
||||
|
||||
func NewConversion(name string, cfg config.Pinterest, template *tagmanager.CustomTemplate, triggers ...*tagmanager.Trigger) *tagmanager.Tag {
|
||||
return &tagmanager.Tag{
|
||||
FiringTriggerId: utils.TriggerIDs(triggers),
|
||||
Name: ConversionName(name),
|
||||
TagFiringOption: "oncePerEvent",
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "apiAccessToken",
|
||||
Type: "template",
|
||||
Value: cfg.APIAccessToken,
|
||||
},
|
||||
{
|
||||
Key: "testMode",
|
||||
Type: "boolean",
|
||||
Value: strconv.FormatBool(cfg.TestModeEnabled),
|
||||
},
|
||||
{
|
||||
Key: "eventName",
|
||||
Type: "template",
|
||||
Value: "inherit",
|
||||
},
|
||||
{
|
||||
Key: "logMode",
|
||||
Type: "template",
|
||||
Value: func(testMode bool) string {
|
||||
if testMode {
|
||||
return "log"
|
||||
}
|
||||
return "donotlog"
|
||||
}(cfg.TestModeEnabled),
|
||||
},
|
||||
{
|
||||
Key: "overrideMode",
|
||||
Type: "boolean",
|
||||
Value: "false",
|
||||
},
|
||||
{
|
||||
Key: "advertiserId",
|
||||
Type: "template",
|
||||
Value: cfg.AdvertiserID,
|
||||
},
|
||||
},
|
||||
Type: utils.TemplateType(template),
|
||||
}
|
||||
}
|
||||
83
pkg/provider/pinterest/server/trigger/conversion.go
Normal file
83
pkg/provider/pinterest/server/trigger/conversion.go
Normal file
@ -0,0 +1,83 @@
|
||||
package trigger
|
||||
|
||||
import (
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func ConversionName(v string) string {
|
||||
return "Pinterest Conversion - " + v
|
||||
}
|
||||
|
||||
type (
|
||||
EventOptions struct {
|
||||
consentMode *tagmanager.Variable
|
||||
}
|
||||
EventOption func(*EventOptions)
|
||||
)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func ConversionWithConsentMode(mode *tagmanager.Variable) EventOption {
|
||||
return func(o *EventOptions) {
|
||||
o.consentMode = mode
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Constructor
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func NewConversion(name string, opts ...EventOption) *tagmanager.Trigger {
|
||||
o := &EventOptions{}
|
||||
for _, opt := range opts {
|
||||
if opt != nil {
|
||||
opt(o)
|
||||
}
|
||||
}
|
||||
|
||||
var filter []*tagmanager.Condition
|
||||
if o.consentMode != nil {
|
||||
filter = append(filter,
|
||||
&tagmanager.Condition{
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "arg0",
|
||||
Type: "template",
|
||||
Value: "{{" + o.consentMode.Name + "}}",
|
||||
},
|
||||
{
|
||||
Key: "arg1",
|
||||
Type: "template",
|
||||
Value: "granted",
|
||||
},
|
||||
},
|
||||
Type: "equals",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
return &tagmanager.Trigger{
|
||||
Type: "customEvent",
|
||||
Name: ConversionName(name),
|
||||
CustomEventFilter: []*tagmanager.Condition{
|
||||
{
|
||||
Parameter: []*tagmanager.Parameter{
|
||||
{
|
||||
Key: "arg0",
|
||||
Type: "template",
|
||||
Value: "{{_event}}",
|
||||
},
|
||||
{
|
||||
Key: "arg1",
|
||||
Type: "template",
|
||||
Value: name,
|
||||
},
|
||||
},
|
||||
Type: "equals",
|
||||
},
|
||||
},
|
||||
Filter: filter,
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package tracify
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
@ -15,33 +16,30 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Tracify) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Tracify - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, l *slog.Logger, tm *tagmanager.TagManager, cfg config.Tracify) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Tracify - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // conversion
|
||||
token, err := tm.UpsertVariable(commonvariable.NewConstant(NameTokenConstant, cfg.Token))
|
||||
token, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameTokenConstant, cfg.Token))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
customerSiteID, err := tm.UpsertVariable(commonvariable.NewConstant(NameCustomerSiteIDConstant, cfg.CustomerSiteID))
|
||||
customerSiteID, err := tm.UpsertVariable(ctx, folder, commonvariable.NewConstant(NameCustomerSiteIDConstant, cfg.CustomerSiteID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(template.NewTracifyTag(NameTracifyServerTagTemplate))
|
||||
tagTemplate, err := tm.UpsertCustomTemplate(ctx, template.NewTracifyTag(NameTracifyServerTagTemplate))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -49,22 +47,22 @@ func Server(l *slog.Logger, tm *tagmanager.TagManager, cfg config.Tracify) error
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.TracifyEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.TracifyEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewTracifyEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewTracifyEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(servertagx.NewTracify(event, token, customerSiteID, tagTemplate, cfg, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, servertagx.NewTracify(event, token, customerSiteID, tagTemplate, cfg, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ if (!isConsentGivenOrNotRequired()) {
|
||||
const options = {
|
||||
headers: {'tracify-token': data.token},
|
||||
method: 'POST',
|
||||
timeout: 500,
|
||||
timeout: 1000,
|
||||
};
|
||||
const body = mapEventData();
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package umami
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/foomo/sesamy-cli/pkg/config"
|
||||
"github.com/foomo/sesamy-cli/pkg/provider/googleconsent"
|
||||
googleconsentvariable "github.com/foomo/sesamy-cli/pkg/provider/googleconsent/server/variable"
|
||||
@ -12,22 +14,19 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func Server(tm *tagmanager.TagManager, cfg config.Umami) error {
|
||||
{ // create folder
|
||||
if folder, err := tm.UpsertFolder("Sesamy - " + Name); err != nil {
|
||||
return err
|
||||
} else {
|
||||
tm.SetFolderName(folder.Name)
|
||||
}
|
||||
func Server(ctx context.Context, tm *tagmanager.TagManager, cfg config.Umami) error {
|
||||
folder, err := tm.UpsertFolder(ctx, "Sesamy - "+Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
template, err := tm.UpsertCustomTemplate(containertemplate.NewUmami(Name))
|
||||
template, err := tm.UpsertCustomTemplate(ctx, containertemplate.NewUmami(Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
{ // create tags
|
||||
eventParameters, err := utils.LoadEventParams(cfg.ServerContainer)
|
||||
eventParameters, err := utils.LoadEventParams(ctx, cfg.ServerContainer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -35,22 +34,22 @@ func Server(tm *tagmanager.TagManager, cfg config.Umami) error {
|
||||
for event := range eventParameters {
|
||||
var eventTriggerOpts []trigger.UmamiEventOption
|
||||
if cfg.GoogleConsent.Enabled {
|
||||
if err := googleconsent.ServerEnsure(tm); err != nil {
|
||||
if err := googleconsent.ServerEnsure(ctx, tm); err != nil {
|
||||
return err
|
||||
}
|
||||
consentVariable, err := tm.LookupVariable(googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
consentVariable, err := tm.LookupVariable(ctx, googleconsentvariable.GoogleConsentModeName(cfg.GoogleConsent.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
eventTriggerOpts = append(eventTriggerOpts, trigger.UmamiEventWithConsentMode(consentVariable))
|
||||
}
|
||||
|
||||
eventTrigger, err := tm.UpsertTrigger(trigger.NewUmamiEvent(event, eventTriggerOpts...))
|
||||
eventTrigger, err := tm.UpsertTrigger(ctx, folder, trigger.NewUmamiEvent(event, eventTriggerOpts...))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upsert event trigger: "+event)
|
||||
}
|
||||
|
||||
if _, err := tm.UpsertTag(containertag.NewUmami(event, cfg, template, eventTrigger)); err != nil {
|
||||
if _, err := tm.UpsertTag(ctx, folder, containertag.NewUmami(event, cfg, template, eventTrigger)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
85
pkg/pterm/sloghandler.go
Normal file
85
pkg/pterm/sloghandler.go
Normal file
@ -0,0 +1,85 @@
|
||||
package pterm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
type SlogHandler struct {
|
||||
attrs []slog.Attr
|
||||
}
|
||||
|
||||
// NewSlogHandler returns a new logging handler that can be intrgrated with log/slog.
|
||||
func NewSlogHandler() *SlogHandler {
|
||||
return &SlogHandler{}
|
||||
}
|
||||
|
||||
// Enabled returns true if the given level is enabled.
|
||||
func (s *SlogHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
switch level {
|
||||
case slog.LevelDebug:
|
||||
return pterm.PrintDebugMessages
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Handle handles the given record.
|
||||
func (s *SlogHandler) Handle(ctx context.Context, record slog.Record) error {
|
||||
level := record.Level
|
||||
message := record.Message
|
||||
|
||||
// Convert slog Attrs to a map.
|
||||
keyValsMap := make(map[string]any)
|
||||
|
||||
record.Attrs(func(attr slog.Attr) bool {
|
||||
keyValsMap[attr.Key] = attr.Value
|
||||
return true
|
||||
})
|
||||
|
||||
for _, attr := range s.attrs {
|
||||
keyValsMap[attr.Key] = attr.Value
|
||||
}
|
||||
|
||||
args := pterm.DefaultLogger.ArgsFromMap(keyValsMap)
|
||||
|
||||
// Wrapping args inside another slice to match [][]LoggerArgument
|
||||
argsWrapped := [][]pterm.LoggerArgument{args}
|
||||
|
||||
for _, arg := range argsWrapped {
|
||||
for _, attr := range arg {
|
||||
message += " " + attr.Key + ": " + fmt.Sprintf("%v", attr.Value)
|
||||
}
|
||||
}
|
||||
|
||||
switch level {
|
||||
case slog.LevelDebug:
|
||||
pterm.Debug.Println(message)
|
||||
case slog.LevelInfo:
|
||||
pterm.Info.Println(message)
|
||||
case slog.LevelWarn:
|
||||
pterm.Warning.Println(message)
|
||||
case slog.LevelError:
|
||||
pterm.Error.Println(message)
|
||||
default:
|
||||
pterm.Info.Println(message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithAttrs returns a new handler with the given attributes.
|
||||
func (s *SlogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
newS := *s
|
||||
newS.attrs = attrs
|
||||
return &newS
|
||||
}
|
||||
|
||||
// WithGroup is not yet supported.
|
||||
func (s *SlogHandler) WithGroup(name string) slog.Handler {
|
||||
// Grouping is not yet supported by pterm.
|
||||
return s
|
||||
}
|
||||
20
pkg/pterm/writer.go
Normal file
20
pkg/pterm/writer.go
Normal file
@ -0,0 +1,20 @@
|
||||
package pterm
|
||||
|
||||
import (
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
||||
type Writer struct {
|
||||
printer pterm.PrefixPrinter
|
||||
}
|
||||
|
||||
func NewWriter(printer pterm.PrefixPrinter) *Writer {
|
||||
return &Writer{
|
||||
printer: printer,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Writer) Write(b []byte) (int, error) {
|
||||
p.printer.Println(string(b))
|
||||
return len(b), nil
|
||||
}
|
||||
@ -1,13 +1,19 @@
|
||||
package transformation
|
||||
|
||||
import (
|
||||
"maps"
|
||||
"slices"
|
||||
|
||||
"google.golang.org/api/tagmanager/v2"
|
||||
)
|
||||
|
||||
func NewMPv2UserData(name string, variables map[string]*tagmanager.Variable, client *tagmanager.Client) *tagmanager.Transformation {
|
||||
var list []*tagmanager.Parameter
|
||||
for k, v := range variables {
|
||||
list = append(list, &tagmanager.Parameter{
|
||||
variableKeys := slices.AppendSeq(make([]string, 0, len(variables)), maps.Keys(variables))
|
||||
slices.Sort(variableKeys)
|
||||
|
||||
list := make([]*tagmanager.Parameter, len(variables))
|
||||
for i, k := range variableKeys {
|
||||
list[i] = &tagmanager.Parameter{
|
||||
IsWeakReference: false,
|
||||
Map: []*tagmanager.Parameter{
|
||||
{
|
||||
@ -18,11 +24,11 @@ func NewMPv2UserData(name string, variables map[string]*tagmanager.Variable, cli
|
||||
{
|
||||
Key: "paramValue",
|
||||
Type: "template",
|
||||
Value: "{{" + v.Name + "}}",
|
||||
Value: "{{" + variables[k].Name + "}}",
|
||||
},
|
||||
},
|
||||
Type: "map",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &tagmanager.Transformation{
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
func EventDataName(v string) string {
|
||||
return "event." + v
|
||||
return "eventData." + v
|
||||
}
|
||||
|
||||
func NewEventData(name string) *tagmanager.Variable {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user