mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-27 17:25:38 +08:00
release: Add publish testflight
This commit is contained in:
parent
3a94e792a2
commit
50576084c6
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
|
@ -393,7 +393,7 @@ jobs:
|
||||||
- name: Setup Xcode stable
|
- name: Setup Xcode stable
|
||||||
if: matrix.if && github.ref == 'refs/heads/main-next'
|
if: matrix.if && github.ref == 'refs/heads/main-next'
|
||||||
run: |-
|
run: |-
|
||||||
sudo xcode-select -s /Applications/Xcode_16.1.app
|
sudo xcode-select -s /Applications/Xcode_16.2.app
|
||||||
- name: Setup Xcode beta
|
- name: Setup Xcode beta
|
||||||
if: matrix.if && github.ref == 'refs/heads/dev-next'
|
if: matrix.if && github.ref == 'refs/heads/dev-next'
|
||||||
run: |-
|
run: |-
|
||||||
|
@ -491,6 +491,10 @@ jobs:
|
||||||
-authenticationKeyPath $ASC_KEY_PATH \
|
-authenticationKeyPath $ASC_KEY_PATH \
|
||||||
-authenticationKeyID $ASC_KEY_ID \
|
-authenticationKeyID $ASC_KEY_ID \
|
||||||
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID
|
-authenticationKeyIssuerID $ASC_KEY_ISSUER_ID
|
||||||
|
- name: Publish to TestFlight
|
||||||
|
if: matrix.if && matrix.name != 'macOS-standalone' && github.event_name == 'workflow_dispatch' && github.ref =='refs/heads/dev-next'
|
||||||
|
run: |-
|
||||||
|
go run -v ./cmd/internal/app_store_connect publish_testflight ${{ matrix.platform }}
|
||||||
- name: Build image
|
- name: Build image
|
||||||
if: matrix.if && matrix.name == 'macOS-standalone' && github.event_name == 'workflow_dispatch'
|
if: matrix.if && matrix.name == 'macOS-standalone' && github.event_name == 'workflow_dispatch'
|
||||||
run: |-
|
run: |-
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
_ "unsafe"
|
|
||||||
|
|
||||||
"github.com/cidertool/asc-go/asc"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
*asc.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) UpdateBuildForAppStoreVersion(ctx context.Context, id string, buildID *string) (*asc.Response, error) {
|
|
||||||
linkage := newRelationshipDeclaration(buildID, "builds")
|
|
||||||
url := fmt.Sprintf("appStoreVersions/%s/relationships/build", id)
|
|
||||||
return c.patch(ctx, url, newRequestBody(linkage), nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRelationshipDeclaration(id *string, relationshipType string) *asc.RelationshipData {
|
|
||||||
if id == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &asc.RelationshipData{
|
|
||||||
ID: *id,
|
|
||||||
Type: relationshipType,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,140 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
_ "unsafe"
|
|
||||||
|
|
||||||
"github.com/cidertool/asc-go/asc"
|
|
||||||
"github.com/google/go-querystring/query"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (c *Client) newRequest(ctx context.Context, method string, path string, body *requestBody, options ...requestOption) (*http.Request, error) {
|
|
||||||
return clientNewRequest(c.Client, ctx, method, path, body, options...)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname clientNewRequest github.com/cidertool/asc-go/asc.(*Client).newRequest
|
|
||||||
func clientNewRequest(c *asc.Client, ctx context.Context, method string, path string, body *requestBody, options ...requestOption) (*http.Request, error)
|
|
||||||
|
|
||||||
func (c *Client) do(ctx context.Context, req *http.Request, v interface{}) (*asc.Response, error) {
|
|
||||||
return clientDo(c.Client, ctx, req, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname clientDo github.com/cidertool/asc-go/asc.(*Client).do
|
|
||||||
func clientDo(c *asc.Client, ctx context.Context, req *http.Request, v interface{}) (*asc.Response, error)
|
|
||||||
|
|
||||||
// get sends a GET request to the API as configured.
|
|
||||||
func (c *Client) get(ctx context.Context, url string, query interface{}, v interface{}, options ...requestOption) (*asc.Response, error) {
|
|
||||||
var err error
|
|
||||||
if query != nil {
|
|
||||||
url, err = appendingQueryOptions(url, query)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := c.newRequest(ctx, "GET", url, nil, options...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.do(ctx, req, v)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// post sends a POST request to the API as configured.
|
|
||||||
func (c *Client) post(ctx context.Context, url string, body *requestBody, v interface{}) (*asc.Response, error) {
|
|
||||||
req, err := c.newRequest(ctx, "POST", url, body, withContentType("application/json"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.do(ctx, req, v)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// patch sends a PATCH request to the API as configured.
|
|
||||||
func (c *Client) patch(ctx context.Context, url string, body *requestBody, v interface{}) (*asc.Response, error) {
|
|
||||||
req, err := c.newRequest(ctx, "PATCH", url, body, withContentType("application/json"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.do(ctx, req, v)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete sends a DELETE request to the API as configured.
|
|
||||||
func (c *Client) delete(ctx context.Context, url string, body *requestBody) (*asc.Response, error) {
|
|
||||||
req, err := c.newRequest(ctx, "DELETE", url, body, withContentType("application/json"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.do(ctx, req, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// request is a common structure for a request body sent to the API.
|
|
||||||
type requestBody struct {
|
|
||||||
Data interface{} `json:"data"`
|
|
||||||
Included interface{} `json:"included,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRequestBody(data interface{}) *requestBody {
|
|
||||||
return newRequestBodyWithIncluded(data, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRequestBodyWithIncluded(data interface{}, included interface{}) *requestBody {
|
|
||||||
return &requestBody{Data: data, Included: included}
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestOption func(*http.Request)
|
|
||||||
|
|
||||||
func withAccept(typ string) requestOption {
|
|
||||||
return func(req *http.Request) {
|
|
||||||
req.Header.Set("Accept", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func withContentType(typ string) requestOption {
|
|
||||||
return func(req *http.Request) {
|
|
||||||
req.Header.Set("Content-Type", typ)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddOptions adds the parameters in opt as URL query parameters to s. opt
|
|
||||||
// must be a struct whose fields may contain "url" tags.
|
|
||||||
func appendingQueryOptions(s string, opt interface{}) (string, error) {
|
|
||||||
v := reflect.ValueOf(opt)
|
|
||||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := url.Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
|
|
||||||
qs, err := query.Values(opt)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
|
|
||||||
u.RawQuery = qs.Encode()
|
|
||||||
|
|
||||||
return u.String(), nil
|
|
||||||
}
|
|
|
@ -7,13 +7,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/asc-go/asc"
|
||||||
"github.com/sagernet/sing-box/cmd/internal/build_shared"
|
"github.com/sagernet/sing-box/cmd/internal/build_shared"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
|
|
||||||
"github.com/cidertool/asc-go/asc"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -54,20 +53,20 @@ const (
|
||||||
groupID = "5c5f3b78-b7a0-40c0-bcad-e6ef87bbefda"
|
groupID = "5c5f3b78-b7a0-40c0-bcad-e6ef87bbefda"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createClient() *Client {
|
func createClient(expireDuration time.Duration) *asc.Client {
|
||||||
privateKey, err := os.ReadFile(os.Getenv("ASC_KEY_PATH"))
|
privateKey, err := os.ReadFile(os.Getenv("ASC_KEY_PATH"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
tokenConfig, err := asc.NewTokenConfig(os.Getenv("ASC_KEY_ID"), os.Getenv("ASC_KEY_ISSUER_ID"), time.Minute, privateKey)
|
tokenConfig, err := asc.NewTokenConfig(os.Getenv("ASC_KEY_ID"), os.Getenv("ASC_KEY_ISSUER_ID"), expireDuration, privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return &Client{asc.NewClient(tokenConfig.Client())}
|
return asc.NewClient(tokenConfig.Client())
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchMacOSVersion(ctx context.Context) error {
|
func fetchMacOSVersion(ctx context.Context) error {
|
||||||
client := createClient()
|
client := createClient(time.Minute)
|
||||||
versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{
|
versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{
|
||||||
FilterPlatform: []string{"MAC_OS"},
|
FilterPlatform: []string{"MAC_OS"},
|
||||||
})
|
})
|
||||||
|
@ -105,71 +104,101 @@ func publishTestflight(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tag := tagVersion.VersionString()
|
tag := tagVersion.VersionString()
|
||||||
client := createClient()
|
client := createClient(10 * time.Minute)
|
||||||
|
|
||||||
|
log.Info(tag, " list build IDs")
|
||||||
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
|
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buildIDS := common.Map(buildIDsResponse.Data, func(it asc.RelationshipData) string {
|
buildIDs := common.Map(buildIDsResponse.Data, func(it asc.RelationshipData) string {
|
||||||
return it.ID
|
return it.ID
|
||||||
})
|
})
|
||||||
for _, platform := range []asc.Platform{
|
var platforms []asc.Platform
|
||||||
asc.PlatformIOS,
|
if len(os.Args) == 3 {
|
||||||
asc.PlatformMACOS,
|
switch os.Args[2] {
|
||||||
asc.PlatformTVOS,
|
case "ios":
|
||||||
} {
|
platforms = []asc.Platform{asc.PlatformIOS}
|
||||||
|
case "macos":
|
||||||
|
platforms = []asc.Platform{asc.PlatformMACOS}
|
||||||
|
case "tvos":
|
||||||
|
platforms = []asc.Platform{asc.PlatformTVOS}
|
||||||
|
default:
|
||||||
|
return E.New("unknown platform: ", os.Args[2])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
platforms = []asc.Platform{
|
||||||
|
asc.PlatformIOS,
|
||||||
|
asc.PlatformMACOS,
|
||||||
|
asc.PlatformTVOS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, platform := range platforms {
|
||||||
log.Info(string(platform), " list builds")
|
log.Info(string(platform), " list builds")
|
||||||
builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{
|
for {
|
||||||
FilterApp: []string{appID},
|
builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{
|
||||||
FilterPreReleaseVersionPlatform: []string{string(platform)},
|
FilterApp: []string{appID},
|
||||||
})
|
FilterPreReleaseVersionPlatform: []string{string(platform)},
|
||||||
if err != nil {
|
})
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Info(string(platform), " ", tag, " list localizations")
|
|
||||||
localizations, _, err := client.TestFlight.ListBetaBuildLocalizationsForBuild(ctx, builds.Data[0].ID, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
localization := common.Find(localizations.Data, func(it asc.BetaBuildLocalization) bool {
|
|
||||||
return *it.Attributes.Locale == "en-US"
|
|
||||||
})
|
|
||||||
if localization.ID == "" {
|
|
||||||
log.Fatal(string(platform), " ", tag, " no en-US localization found")
|
|
||||||
}
|
|
||||||
if localization.Attributes == nil || localization.Attributes.WhatsNew == nil || *localization.Attributes.WhatsNew == "" {
|
|
||||||
log.Info(string(platform), " ", tag, " update localization")
|
|
||||||
_, _, err = client.TestFlight.UpdateBetaBuildLocalization(ctx, localization.ID, common.Ptr(
|
|
||||||
F.ToString("sing-box ", tag),
|
|
||||||
))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
build := builds.Data[0]
|
||||||
if !common.Contains(buildIDS, builds.Data[0].ID) {
|
if common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 5*time.Minute {
|
||||||
|
log.Info(string(platform), " ", tag, " waiting for process")
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if *build.Attributes.ProcessingState != "VALID" {
|
||||||
|
log.Info(string(platform), " ", tag, " waiting for process: ", *build.Attributes.ProcessingState)
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Info(string(platform), " ", tag, " list localizations")
|
||||||
|
localizations, _, err := client.TestFlight.ListBetaBuildLocalizationsForBuild(ctx, build.ID, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
localization := common.Find(localizations.Data, func(it asc.BetaBuildLocalization) bool {
|
||||||
|
return *it.Attributes.Locale == "en-US"
|
||||||
|
})
|
||||||
|
if localization.ID == "" {
|
||||||
|
log.Fatal(string(platform), " ", tag, " no en-US localization found")
|
||||||
|
}
|
||||||
|
if localization.Attributes == nil || localization.Attributes.WhatsNew == nil || *localization.Attributes.WhatsNew == "" {
|
||||||
|
log.Info(string(platform), " ", tag, " update localization")
|
||||||
|
_, _, err = client.TestFlight.UpdateBetaBuildLocalization(ctx, localization.ID, common.Ptr(
|
||||||
|
F.ToString("sing-box ", tagVersion.String()),
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
log.Info(string(platform), " ", tag, " publish")
|
log.Info(string(platform), " ", tag, " publish")
|
||||||
_, err = client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{builds.Data[0].ID})
|
response, err := client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{build.ID})
|
||||||
|
if response != nil && response.StatusCode == http.StatusUnprocessableEntity {
|
||||||
|
log.Info("waiting for process")
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info(string(platform), " ", tag, " list submissions")
|
||||||
|
betaSubmissions, _, err := client.TestFlight.ListBetaAppReviewSubmissions(ctx, &asc.ListBetaAppReviewSubmissionsQuery{
|
||||||
|
FilterBuild: []string{build.ID},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
if len(betaSubmissions.Data) == 0 {
|
||||||
log.Info(string(platform), " ", tag, " list submissions")
|
log.Info(string(platform), " ", tag, " create submission")
|
||||||
betaSubmissions, _, err := client.TestFlight.ListBetaAppReviewSubmissions(ctx, &asc.ListBetaAppReviewSubmissionsQuery{
|
_, _, err = client.TestFlight.CreateBetaAppReviewSubmission(ctx, build.ID)
|
||||||
FilterBuild: []string{builds.Data[0].ID},
|
if err != nil {
|
||||||
})
|
return err
|
||||||
if err != nil {
|
}
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(betaSubmissions.Data) == 0 {
|
|
||||||
log.Info(string(platform), " ", tag, " create submission")
|
|
||||||
_, _, err = client.TestFlight.CreateBetaAppReviewSubmission(ctx, builds.Data[0].ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
continue
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -187,34 +216,40 @@ func cancelAppStore(ctx context.Context, platform string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client := createClient()
|
client := createClient(time.Minute)
|
||||||
log.Info(platform, " list versions")
|
for {
|
||||||
versions, _, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{
|
log.Info(platform, " list versions")
|
||||||
FilterPlatform: []string{string(platform)},
|
versions, response, err := client.Apps.ListAppStoreVersionsForApp(ctx, appID, &asc.ListAppStoreVersionsQuery{
|
||||||
})
|
FilterPlatform: []string{string(platform)},
|
||||||
if err != nil {
|
})
|
||||||
return err
|
if isRetryable(response) {
|
||||||
}
|
continue
|
||||||
version := common.Find(versions.Data, func(it asc.AppStoreVersion) bool {
|
} else if err != nil {
|
||||||
return *it.Attributes.VersionString == tag
|
return err
|
||||||
})
|
}
|
||||||
if version.ID == "" {
|
version := common.Find(versions.Data, func(it asc.AppStoreVersion) bool {
|
||||||
|
return *it.Attributes.VersionString == tag
|
||||||
|
})
|
||||||
|
if version.ID == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Info(platform, " ", tag, " get submission")
|
||||||
|
submission, response, err := client.Submission.GetAppStoreVersionSubmissionForAppStoreVersion(ctx, version.ID, nil)
|
||||||
|
if response != nil && response.StatusCode == http.StatusNotFound {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if isRetryable(response) {
|
||||||
|
continue
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Info(platform, " ", tag, " delete submission")
|
||||||
|
_, err = client.Submission.DeleteSubmission(ctx, submission.Data.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Info(string(platform), " ", tag, " get submission")
|
|
||||||
submission, response, err := client.Submission.GetAppStoreVersionSubmissionForAppStoreVersion(ctx, version.ID, nil)
|
|
||||||
if response != nil && response.StatusCode == http.StatusNotFound {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Info(platform, " ", tag, " delete submission")
|
|
||||||
_, err = client.Submission.DeleteSubmission(ctx, submission.Data.ID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAppStore(ctx context.Context) error {
|
func prepareAppStore(ctx context.Context) error {
|
||||||
|
@ -222,7 +257,7 @@ func prepareAppStore(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client := createClient()
|
client := createClient(time.Minute)
|
||||||
for _, platform := range []asc.Platform{
|
for _, platform := range []asc.Platform{
|
||||||
asc.PlatformIOS,
|
asc.PlatformIOS,
|
||||||
asc.PlatformMACOS,
|
asc.PlatformMACOS,
|
||||||
|
@ -291,7 +326,7 @@ func prepareAppStore(ctx context.Context) error {
|
||||||
log.Fatal(string(platform), " ", tag, " unknown state ", string(*version.Attributes.AppStoreState))
|
log.Fatal(string(platform), " ", tag, " unknown state ", string(*version.Attributes.AppStoreState))
|
||||||
}
|
}
|
||||||
log.Info(string(platform), " ", tag, " update build")
|
log.Info(string(platform), " ", tag, " update build")
|
||||||
response, err = client.UpdateBuildForAppStoreVersion(ctx, version.ID, buildID)
|
response, err = client.Apps.UpdateBuildForAppStoreVersion(ctx, version.ID, buildID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -364,7 +399,7 @@ func publishAppStore(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
client := createClient()
|
client := createClient(time.Minute)
|
||||||
for _, platform := range []asc.Platform{
|
for _, platform := range []asc.Platform{
|
||||||
asc.PlatformIOS,
|
asc.PlatformIOS,
|
||||||
asc.PlatformMACOS,
|
asc.PlatformMACOS,
|
||||||
|
@ -398,3 +433,15 @@ func publishAppStore(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRetryable(response *asc.Response) bool {
|
||||||
|
if response == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch response.StatusCode {
|
||||||
|
case http.StatusInternalServerError, http.StatusUnprocessableEntity:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
go.mod
6
go.mod
|
@ -5,7 +5,6 @@ go 1.20
|
||||||
require (
|
require (
|
||||||
berty.tech/go-libtor v1.0.385
|
berty.tech/go-libtor v1.0.385
|
||||||
github.com/caddyserver/certmagic v0.20.0
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
github.com/cidertool/asc-go v0.5.1
|
|
||||||
github.com/cloudflare/circl v1.3.7
|
github.com/cloudflare/circl v1.3.7
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/go-chi/chi/v5 v5.1.0
|
github.com/go-chi/chi/v5 v5.1.0
|
||||||
|
@ -20,6 +19,7 @@ require (
|
||||||
github.com/miekg/dns v1.1.62
|
github.com/miekg/dns v1.1.62
|
||||||
github.com/ooni/go-libtor v1.1.8
|
github.com/ooni/go-libtor v1.1.8
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
|
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
|
@ -61,7 +61,7 @@ require (
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
|
@ -71,7 +71,7 @@ require (
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
|
13
go.sum
13
go.sum
|
@ -6,10 +6,8 @@ github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sx
|
||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
||||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
github.com/cidertool/asc-go v0.5.1 h1:KYki2Y8IXJMOkOXy9y1sdr8tz6IdW2ti770K4bk7WY0=
|
|
||||||
github.com/cidertool/asc-go v0.5.1/go.mod h1:LyrZWU7DeCh8cWrFwXcpl93ixRUUL2aEZV7/0h07FxA=
|
|
||||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
@ -41,10 +39,11 @@ github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
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.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||||
|
@ -102,6 +101,8 @@ github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4=
|
||||||
|
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU=
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
|
||||||
|
|
Loading…
Reference in New Issue
Block a user